Upgrading clusters and draining nodes
Upgrade a kubeadm cluster one minor version at a time: the first control plane with kubeadm upgrade apply, then every other node drained, upgraded and returned to service.
After this lesson
- 01You can state the version skew rules and explain the upgrade order they force.
- 02You can upgrade the first control plane with kubeadm upgrade plan and apply, then its kubelet and kubectl.
- 03You can drain, upgrade and uncordon nodes one at a time, and you know what each drain flag is for.
Upgrades are the heart of the competency Manage the lifecycle of Kubernetes clusters. A kubeadm upgrade is a fixed sequence of about fifteen commands, and the exam punishes small slips in it: a package left unpinned, a kubelet never restarted, a node left cordoned. This lesson gives you the sequence and the reasoning behind it, then lets you practice the part kind can do for real: draining and returning a node.
Version skew decides the order
Two rules fall out of that table. The control plane goes first, because nothing may be newer than the API server. And kubeadm moves one minor version per upgrade: 1.36 to 1.37 works, 1.35 straight to 1.37 is refused, while skipping patch releases is fine. Remember that the VERSION column of kubectl get nodes shows each node's kubelet version. It changes only after you upgrade and restart the kubelet on that node, never because of kubeadm upgrade apply.
Upgrade the first control plane
# exam: ssh <control-plane>; sudo -i
# root may need: export KUBECONFIG=/etc/kubernetes/admin.conf
# 1. Point apt at the new minor version and find the exact package
sed -i 's#/v1.36/#/v1.37/#' /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-cache madison kubeadm | head -3 # e.g. 1.37.1-1.1
# 2. kubeadm first
apt-mark unhold kubeadm
apt-get install -y kubeadm=1.37.1-1.1
apt-mark hold kubeadm
kubeadm version -o short # v1.37.1
# 3. Plan, then apply exactly the version you installed
kubeadm upgrade plan
kubeadm upgrade apply v1.37.1 # -y skips the confirmation prompt
# 4. kubelet and kubectl, with the node drained
kubectl drain <control-plane> --ignore-daemonsets
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=1.37.1-1.1 kubectl=1.37.1-1.1
apt-mark hold kubelet kubectl
systemctl daemon-reload
systemctl restart kubelet
kubectl uncordon <control-plane>
kubectl get nodeskubeadm upgrade plan checks that the cluster is healthy and lists the versions you can move to. kubeadm upgrade apply pulls the new images and rewrites the static Pod manifests one component at a time, keeping backups under /etc/kubernetes/tmp and rolling a component back if its new Pod does not come up. It also renews the control plane certificates and upgrades the CoreDNS and kube-proxy add-ons. It does not touch the kubelet binary; that is the package step that follows.
Other control planes and the workers
# Additional control plane nodes: the same package steps, but instead of "upgrade apply":
kubeadm upgrade node
# Each worker. On the worker (ssh <worker>; sudo -i):
sed -i 's#/v1.36/#/v1.37/#' /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-mark unhold kubeadm && apt-get install -y kubeadm=1.37.1-1.1 && apt-mark hold kubeadm
kubeadm upgrade node
# Wherever kubectl has admin credentials:
kubectl drain <worker> --ignore-daemonsets --delete-emptydir-data
# Back on the worker:
apt-mark unhold kubelet kubectl && apt-get install -y kubelet=1.37.1-1.1 kubectl=1.37.1-1.1 && apt-mark hold kubelet kubectl
systemctl daemon-reload && systemctl restart kubelet
# And from the admin side again:
kubectl uncordon <worker>
kubectl get nodeskubeadm upgrade node is the per-node half of the upgrade. On another control plane node it rewrites that node's static Pod manifests for the version the cluster now runs; on a worker it refreshes the kubelet configuration in /var/lib/kubelet/config.yaml. It takes no version argument because it reads the target from the cluster. Never run upgrade apply again on the other control planes. Do workers one at a time, or in batches small enough for your spare capacity and PodDisruptionBudgets.
cordon, drain, uncordon
In the docs · the tab you get on exam day
- Upgrading kubeadm clusters ↗search: “kubeadm upgrade”
- Version Skew Policy ↗search: “version skew policy”
- Safely Drain a Node ↗search: “drain node”
- Changing The Kubernetes Package Repository ↗search: “change package repository”
Cluster: a kubeadm-built cluster (VM lab). The kind lab cannot run this one.
Upgrade a kubeadm cluster by one minor version
cp1 and worker w1, both on Kubernetes v1.36 and installed from pkgs.k8s.io. Upgrade the control plane components, kubelets and kubectl on both nodes to the newest v1.37 patch release available. Upgrade one node at a time, drain each node before upgrading its kubelet, and leave both nodes schedulable. You work from cp1; ssh w1 reaches the worker.This one needs a cluster you built with kubeadm. Read it and the solution now; run it when you have the VM lab.
- 01
Nothing to set up
Start on a healthy lab. Check it with lab-check.sh if unsure.
- 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-upgrade-1/verify | bashCounts toward your readiness score.
context · kubectl config use-context kind-cka
Drain a node for maintenance
cka-worker2 is going down for maintenance. Make sure no new Pods can be scheduled onto it and move every Pod off it, except those managed by DaemonSets. The Pods of Deployment web in namespace ar-drain keep scratch data in an emptyDir volume; that data may be discarded. Leave the node unschedulable, since the maintenance team will return it to service themselves.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-upgrade-2/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-upgrade-2/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-upgrade-2/cleanup | bash
Finished reading?
0 of 2 tasks passed. Readiness counts tasks, so run them before you move on.