Upgrades Basics
This page covers the mechanics of moving a cluster between versions: check the skew, upgrade the control plane first, then roll the node pools. Examples cover both managed clusters and self-managed kubeadm.
Search across all documentation pages
This page covers the mechanics of moving a cluster between versions: check the skew, upgrade the control plane first, then roll the node pools. Examples cover both managed clusters and self-managed kubeadm.
kubectl within one minor of your API server (1.35, 1.36, or 1.37 for a 1.36 cluster).aws, gcloud, or az).kubeadm, kubelet, and SSH to each node.Quick check of your tooling:
kubectl version
kubeadm versionSee where the control plane and every node sit today.
kubectl version
kubectl get nodes -o widekubectl version reports both the client and the API server version.get nodes -o wide shows each node's KUBELET-VERSION in its own column.You may only lag nodes so far behind the control plane.
kubectl get nodes -o custom-columns=NAME:.metadata.name,KUBELET:.status.nodeInfo.kubeletVersionkube-proxy on each node tracks that node's kubelet minor version.A minor upgrade can delete an API your manifests still use.
kubectl get --raw /metrics | grep apiserver_requested_deprecated_apisOn managed platforms the provider replaces the control plane for you.
aws eks update-cluster-version \
--name prod \
--kubernetes-version 1.36gcloud container clusters upgrade --master and az aks upgrade --control-plane-only.On kubeadm clusters you drive the control plane yourself.
# On the first control-plane node
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v1.36.2upgrade plan prints the available target versions and component changes.upgrade apply upgrades the static control-plane pods on that node.kubeadm upgrade node on any additional control-plane nodes afterward.kubeadm refuses to skip minors.The control-plane node's own kubelet must be updated after the components.
sudo apt-get install -y kubelet=1.36.2-* kubectl=1.36.2-*
sudo systemctl daemon-reload
sudo systemctl restart kubeletkubeadm upgrade.yum/dnf distributions but the sequence is identical.Ready with the new kubelet version.With the control plane on the new minor, bring nodes forward.
aws eks update-nodegroup-version \
--cluster-name prod \
--nodegroup-name workers \
--kubernetes-version 1.36gcloud container clusters upgrade and az aks nodepool upgrade do the same.On kubeadm you cordon and drain each worker yourself before upgrading it.
kubectl cordon ip-10-0-1-15
kubectl drain ip-10-0-1-15 \
--ignore-daemonsets \
--delete-emptydir-datacordon marks the node unschedulable so no new pods land on it.drain evicts existing pods, honoring PodDisruptionBudgets.--ignore-daemonsets is required because DaemonSet pods cannot be evicted.kubectl uncordon to restore scheduling.Catch removed APIs in your own YAML, not just live traffic.
pluto detect-files -d ./manifestspluto flags API versions removed or deprecated in target releases.apiserver_requested_deprecated_apis metric for full coverage.Core add-ons have their own supported version matrix.
helm upgrade cilium cilium/cilium \
--namespace kube-system \
--reuse-values \
--version <chart-for-1.36>--reuse-values preserves your existing configuration during the bump.Confirm every component landed on the target version before declaring done.
kubectl get nodes -o wide
kubectl get pods -A --field-selector=status.phase!=RunningReady status.Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026