KubernetesLXXIV · kubeadmkubeadm
kubeadm upgrade apply — phases, validation, post-upgrade checks
What you'll learn
- Run kubeadm upgrade apply with the right flags
- Walk the per-host phases and what they produce
- Verify the cluster after each upgrade step
- Apply the production discipline of upgrade validation
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
kubeadm upgrade apply is the command that takes a
control-plane host from one Kubernetes version to the
next. The command is multi-phase and order-sensitive.
This lesson walks the phases, the validation, and the
production discipline of running upgrades.
The command
On the leader (or the first control plane host):
sudo kubeadm upgrade apply v1.34.1
The version argument is a specific patch version. The command:
- Pre-flight checks.
- Pulls new images.
- Updates the cluster-info map.
- Writes new static pod manifests.
- Restarts the static pods (kubelet observes the manifest change).
- Updates the kubelet configuration.
- Updates the cluster’s Kubernetes version.
sequenceDiagram
autonumber
participant Op as Operator
participant KU as kubeadmUpgrade
participant I as ImageRegistry
participant K as kubelet
participant CM as kubeadmConfig
Op->>KU: kubeadm upgrade apply v1.34.1
KU->>KU: preflight checks
KU->>I: pull new control plane images
KU->>CM: update ClusterConfiguration
KU->>K: write new static pod manifests
K->>K: observe manifest change
KU->>K: update kubelet configuration
K-->>Op: upgrade complete
Each phase is observable in the command’s output.
The preflight checks
[preflight] Running preflight checks
[preflight] Pulling images required for this upgrade
[preflight] This might take a minute or two depending on the speed of your internet connection.
[preflight] Note: Some of the preflight checks may take a few seconds to complete.
[preflight] Note: Some recommended components (CNI, kube-proxy, CoreDNS) have not been upgraded.
Please double-check the upgrade plan documentation.
[upgrade] Running cluster health checks
The preflight checks:
- The cluster is healthy (components Running).
- kubeadm has the right images.
- The kubelet can be upgraded.
A failing preflight stops the upgrade.
The pull-images phase
[upgrade/etcd] Pulling image: registry.k8s.io/etcd:3.6.5-0
[upgrade/etcd] Pulled image: etcd 3.6.5-0
[upgrade/apiserver] Pulling image: registry.k8s.io/kube-apiserver:v1.34.1
[upgrade/apiserver] Pulled image: kube-apiserver v1.34.1
[upgrade/controller-manager] Pulling image: ...
[upgrade/scheduler] Pulling image: ...
The images are pulled via containerd. The kubelet will use them when the manifests are updated.
The static pod updates
[upgrade/apiserver] Updated static pod manifest for kube-apiserver
[upgrade/controller-manager] Updated static pod manifest for kube-controller-manager
[upgrade/scheduler] Updated static pod manifest for kube-scheduler
[upgrade/etch] Updated static pod manifest for etcd
The static pod manifests at
/etc/kubernetes/manifests/ are rewritten. The kubelet
observes the change and restarts the pods.
The kubelet reconfiguration
[upgrade/kubelet] Upgrading kubelet configuration...
[upgrade/kubelet] Restarting kubelet...
The kubelet’s --config flag points at
/var/lib/kubelet/config.yaml, which is regenerated.
The kubelet is restarted.
$ kubectl -n kube-system get cm kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' | grep kubernetesVersionkubernetesVersion: v1.34.1The follow-up command
On each follower:
sudo kubeadm upgrade node
The follower’s command:
- Verifies the kubelet version.
- Restarts kubelet.
- Upgrades the local kubeadm.
The follower’s static pods are already updated; only the kubelet needs restart.
[upgrade] Upgrading kubelet...
[upgrade] Restarting kubelet after upgrade...
The follower is now at v1.34.1.
The worker upgrade
On each worker:
# Substitute your own value before running:
WORKER=worker-01
# 1. Drain the worker
kubectl drain "$WORKER" --ignore-daemonsets --delete-emptydir-data
# 2. Upgrade on the worker
sudo kubeadm upgrade node
# 3. Bring the worker back
kubectl uncordon "$WORKER"
The drain moves Pods off the worker; the upgrade + restart the kubelet; uncordon re-enables scheduling.
The image pulling options
sudo kubeadm upgrade apply v1.34.1 \
--image-pull-timeout=15m \
--etcd-upgrade=true \
--certificate-renewal=true
Flags:
| Flag | Purpose |
|---|---|
--image-pull-timeout | Time to pull images before timing out |
--etcd-upgrade | Allow etcd to be upgraded to a newer minor |
--certificate-renewal | Auto-renew cluster certificates during upgrade |
The post-upgrade validation
# 1. The cluster's version is updated
kubectl version
# 2. The control plane nodes reflect the upgrade
kubectl get nodes
# Version column: v1.34.1
# 3. The components are healthy
kubectl get pods -n kube-system
# All Running
# 4. API responses are clean
kubectl get ns
kubectl get nodes -o wide
kubectl api-resources
# 5. Endpoints are populated
kubectl get endpointslices -A | head
The validation checklist
POST-UPGRADE VALIDATION
=======================
Date: 2026-08-16
Operator: <name>
Cluster: production
Upgrade: 1.34.0 → 1.34.1
Pre-upgrade: kubectl get nodes -o wide > /tmp/before.txt
[ ] All nodes Ready
[ ] All control plane pods Running
[ ] API requests succeed
[ ] API resources load without error
[ ] Endpoints populated for key services
[ ] Workloads continue running (deployments, statefulsets, etc.)
[ ] Network policies enforced
[ ] DNS resolves
[ ] Smoke test passes
Post-upgrade snapshot: /backup/etcd-snapshot-post-20260816-1230.db
The rollback procedure
If the upgrade fails or breaks the cluster:
flowchart LR
A[Upgrade broke cluster] --> B[Restore from pre-upgrade snapshot]
B --> C[Re-init on prior version]
C --> D[Re-validate]
The restore is identical to the procedure in Part LXIX. The pre-upgrade snapshot is the rollback path.
The sub-phases of upgrade
sudo kubeadm upgrade apply v1.34.1 --dry-run
A dry-run shows what would happen without changing the cluster.
sudo kubeadm upgrade apply v1.34.1 -f
# -f forces the upgrade
A force option overrides some preflight checks (use carefully).
The image sources
The images are pulled from registry.k8s.io by default.
For airgapped clusters:
sudo kubeadm upgrade apply v1.34.1 \
--kubernetes-version=v1.34.1 \
--image-repository=registry.internal.example/kubernetes
The image repository points to the cluster’s private registry.
The post-upgrade cleanup
# 1. Verify the cluster
kubectl cluster-info
# Kubernetes control plane is running at https://api.example:6443
# 2. Check the kubelet logs
sudo journalctl -u kubelet --since "30 minutes ago"
# Look for: started kubelet v1.34.1, no errors
# 3. Check the static pods
sudo crictl pods | grep -E 'etcd|apiserver|scheduler|controller'
# 4. Final: take a post-upgrade snapshot
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=... --cert=... --key=... \
snapshot save /backup/etcd-snapshot-post-upgrade.db
The post-upgrade snapshot is the new “known-good” state.
The CNI upgrade
After Kubernetes is upgraded, upgrade the CNI to a compatible version:
# Cilium example
helm upgrade cilium cilium/cilium --version 1.16.x \
-n kube-system \
--set kubeProxyReplacement=true
The CNI’s release notes specify the supported Kubernetes versions.
Quiz
Knowledge check · 4 questions
Q1. Which kubeadm upgrade subcommand runs on the leader control-plane host?
Q2. kubeadm upgrade can update etcd implicitly without explicit opt-in.
Q3. The control plane upgrade partially completes: API server is on the new version; etcd upgrade was skipped (no flag). Walk the remediation.
The team runs `kubeadm upgrade apply v1.34.1` on the leader; the command reports success for API server, controller-manager, scheduler; etcd was not upgraded. The team did not pass --etcd-upgrade=true, so etcd is still at 3.5.x but the API server expects 3.5.x-1.
Q4. Why is `kubeadm upgrade apply` only valid on the leader / first control-plane host? What happens if run on a follower?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Backup before upgrade. Always.
- Validate at each step. Each phase has a verifiable outcome.
- Apply on the leader, upgrade node on followers. The sequence matters.
- Post-upgrade snapshot. The new “known-good” anchor.
- CNI + add-ons after. They need version-specific configs.
- Document every step. The plan + outcome feed the runbook.
kubeadm upgrade apply is the cluster’s controlled
disruption. Operating it well is the foundation of every
future cluster operation.