Skip to main content
RunBook Academy

KubernetesLXXVIII · Version SkewVersion skew

Version skew policy — the compatibility matrix

Advanced⏱ ~14 minkubectlkubeadm

What you'll learn

  • State the version skew policy for each component
  • Apply the policy to a 1.34.x cluster
  • Identify valid and invalid skew combinations
  • Plan multi-minor upgrades around the skew policy

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The version skew policy is the official Kubernetes compatibility matrix. It defines which combinations of component versions are supported. This lesson walks the policy, applies it to a 1.34.x cluster, and identifies valid and invalid combinations.

The components

A Kubernetes cluster has these versioned components:

ComponentWhere it runsVersioning
kube-apiserverControl planeTracks Kubernetes minor
kube-controller-managerControl planeTracks Kubernetes minor
kube-schedulerControl planeTracks Kubernetes minor
cloud-controller-managerControl planeTracks Kubernetes minor
kube-proxyWorkerTracks Kubernetes minor
kubeletWorkerTracks Kubernetes minor
kubectlOperator workstationTracks Kubernetes minor
etcdControl plane (or external)etcd’s own versioning

Everything above etcd is a Kubernetes component; etcd is a separate project with its own release train.

flowchart LR
    A["kube-apiserver<br/>the newest component"]
    A -->|up to 1 minor older| B[kube-controller-manager]
    A -->|up to 1 minor older| C[kube-scheduler]
    A -->|up to 1 minor older| D[cloud-controller-manager]
    A -->|up to 3 minor older| E[kube-proxy]
    A -->|up to 3 minor older| F[kubelet]
    G["kubectl<br/>1 minor either side"] --> A
    A --> H[etcd]

The skew policy

The official policy (kubernetes.io/releases/version-skew-policy):

ComponentAllowed skew relative to kube-apiserver
kube-apiserverThe reference. In an HA control plane the oldest and newest instances stay within 1 minor of each other
kube-controller-manager, kube-scheduler, cloud-controller-managerUp to 1 minor older; never newer
kubeletUp to 3 minor older; never newer
kube-proxyUp to 3 minor older; never newer (and within 3 minor of the kubelet it runs alongside)
kubectlWithin 1 minor either side
etcdNot governed by this policy; kubeadm pins one etcd version per K8s minor (3.6.x for 1.34.x)

The policy is one-directional. The kube-apiserver is the newest Kubernetes component in the cluster: every other component may lag it, and none of them may run ahead of it. The window differs — 1 minor for the controller managers and the scheduler, 3 minors for the kubelet and kube-proxy — but the direction does not. kubectl is the single exception, because it is a client rather than a cluster component, and is supported 1 minor on either side.

Applying to 1.34.x

For a cluster at 1.34.x:

  • kube-apiserver: 1.34.x
  • kube-controller-manager, kube-scheduler, cloud-controller-manager: 1.33.x or 1.34.x
  • kubelet: 1.31.x, 1.32.x, 1.33.x, or 1.34.x
  • kube-proxy: 1.31.x, 1.32.x, 1.33.x, or 1.34.x
  • kubectl: 1.33.x, 1.34.x, or 1.35.x
  • etcd: 3.6.x — the version kubeadm 1.34 ships

The valid combinations are bounded by the policy.

ComponentMin versionMax version
kube-apiserver1.34.01.34.x
kube-controller-manager1.33.01.34.x
kube-scheduler1.33.01.34.x
cloud-controller-manager1.33.01.34.x
kube-proxy1.31.01.34.x
kubelet1.31.01.34.x
kubectl1.33.01.35.x
etcd3.6.03.6.x

kubectl is the only row whose maximum is above 1.34.x.

Valid combinations

Valid for 1.34.x apiserver:
  apiserver:  1.34.0
  kubelet:    1.31.0, 1.32.0, 1.33.0, 1.34.0 → all OK
  kube-proxy: 1.31.0, 1.32.0, 1.33.0, 1.34.0 → all OK
  scheduler:  1.33.0, 1.34.0 → both OK
  kubectl:    1.33.0, 1.34.0, 1.35.0 → all OK
  etcd:       3.6.x → OK

Invalid combinations

Invalid for 1.34.x apiserver:
  apiserver:  1.34.0
  kubelet:    1.30.0 → INVALID (4 minor behind)
  kubelet:    1.35.0 → INVALID (newer than the apiserver)
  kube-proxy: 1.35.0 → INVALID (newer than the apiserver)
  scheduler:  1.32.0 → INVALID (2 minor behind)
  scheduler:  1.35.0 → INVALID (newer than the apiserver)
  kubectl:    1.32.0 → INVALID (2 minor behind)
  etcd:       3.4.x → INVALID (1+ minor mismatch)

A combination that violates the skew policy is not supported. The cluster may continue to run, but the behavior is undefined.

The skew during a rolling upgrade

A typical rolling upgrade:

gantt
    title Rolling upgrade skew
    dateFormat  YYYY-MM-DD
    section Apiserver
    v1.33.0              :done, 2026-08-10, 1d
    v1.34.0              :active, 2026-08-11, 7d
    section Kubelet
    Some v1.32.0         :done, 2026-08-10, 1d
    Some v1.33.0         :active, 2026-08-11, 7d
    All v1.34.0          :crit, 2026-08-15, 5d

During the upgrade, the apiserver is at 1.34.0, but some kubelets are still at 1.32.0 or 1.33.0. The skew is within policy (1.32.0 is 2 minor behind, OK). The cluster is functioning.

The skew during a multi-minor upgrade

A multi-minor upgrade (1.31 → 1.34) is not supported in a single call. The intermediate steps are required:

1.31 → 1.32 → 1.33 → 1.34

Each step is a separate upgrade. The cluster is at 1.31, then 1.32, then 1.33, then 1.34. The skew policy is maintained at each step.

The skew and kubectl

kubectl is the operator’s client, and the only piece of the picture supported 1 minor either side of the apiserver. A kubectl one minor behind cannot drive resources or subcommands the newer apiserver added; a kubectl one minor ahead may send fields the older apiserver silently drops. Neither is an error condition, but both are a reason to keep the workstation in step with the cluster.

kubectl version

--short was removed in Kubernetes 1.28; plain kubectl version has printed the short form by default ever since, and passing --short now fails with unknown flag: --short. The output is three lines — Client Version, Kustomize Version (the kustomize build embedded in this kubectl, which tracks the kubectl release rather than the cluster), and Server Version. The first and the last are the two to compare; when they agree, the client and server versions are aligned. Use kubectl version -o json when you want to read the versions from a script rather than by eye.

Cross-course references

  • The Linux course covers binary compatibility concepts.
  • The Terraform course covers Kubernetes provider version pinning.
  • The Ansible course covers module version pinning.

Quiz

Knowledge check · 4 questions

  1. Q1. How many minor versions can a kubelet be behind the kube-apiserver?

  2. Q2. kubeadm supports upgrading a cluster from 1.31 to 1.34 in a single call.

  3. Q3. Validate the version skew of a 3-control-plane + 5-worker cluster.

    Cluster: apiserver 1.34.0; kubelets on 3 workers at 1.32.0 (older wave), 2 workers at 1.34.0 (newer wave); kube-proxy 1.34.0; kubectl on operator workstation 1.35.0; etcd 3.6.x.

  4. Q4. Summarize the skew policy for kube-controller-manager, kube-scheduler, and cloud-controller-manager.

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Track the version of every component. kubeadm upgrade plan reports the current and target versions.
  • Stay within the skew policy. Components outside the policy are unsupported.
  • Plan multi-minor upgrades as a sequence. Each intermediate step is a separate upgrade.
  • Update kubectl alongside the cluster. Version drift is a common operational issue.
  • Document the skew in the runbook. The component versions, the policy boundary, the upgrade plan.
  • Validate the skew before every operation. A pre-flight check before an upgrade.

The skew policy is the cluster’s compatibility contract. Operating it well is staying within the policy and planning upgrades around it.