Upgrade Best Practices
A field-tested checklist for moving a production cluster between versions without downtime. Work top to bottom: prepare, upgrade the control plane, then roll the nodes, verifying at each step.
Search across all documentation pages
A field-tested checklist for moving a production cluster between versions without downtime. Work top to bottom: prepare, upgrade the control plane, then roll the nodes, verifying at each step.
Treat the groups as phases in order, not a menu.
Group A happens days before the change window; groups B through D happen during it.
Each bullet leads with the practice in bold, then the reason. Adopt them as gates, and do not advance a phase until the previous one is green.
pluto over rendered manifests and check the apiserver_requested_deprecated_apis metric on live traffic.maxUnavailable: 0 with surge) so new nodes join Ready before old ones drain - no capacity dip.minAvailable or maxUnavailable so drains cannot evict all replicas at once.maxUnavailable: 0 PDB blocks every eviction and hangs the drain - keep budgets realistic.SIGTERM, fail readiness, drain connections, and set terminationGracePeriodSeconds to cover your slowest request.--ignore-daemonsets on manual drains. DaemonSet pods are node-bound and cannot be evicted, so drain requires you to acknowledge them.kubectl get nodes -o wide shows the expected kubelet version and all nodes Ready.Every node reports the target kubelet version and Ready, and no workload dropped below its PodDisruptionBudget during the roll.
Deprecated APIs are gone from both manifests and live traffic, and all add-ons are on compatible versions.
You have a written record and, for risky changes, a proven rollback path still available.
What is the single most important rule? Upgrade the control plane before any node, and never let a node run a newer version than the API server.
Why rehearse on a separate cluster? Because add-on and API incompatibilities surface there safely, before they can break production.
Can I skip minor versions to save time? No for the control plane. Step through each minor; only nodes may jump because they are replaced.
How do I avoid a capacity dip? Provision surge so new nodes join before old ones drain, and set realistic PodDisruptionBudgets.
How do I know the upgrade succeeded?
All nodes Ready at the target version, no PDB breaches, clean smoke tests, and stable error and latency metrics.
What is the safest option for a risky upgrade? Blue/green node groups - keep the old pool until the new one is proven so rollback is instant.
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