Upgrading Kubernetes Clusters



Keeping Kubernetes cluster up to date is essential. With every new release, Kubernetes brings important bug fixes, performance improvements, and new features that can help our applications run better and more securely. But upgrading a Kubernetes cluster isn't just a matter of running a single command. We need to plan carefully, test thoroughly, and execute the upgrade process step by step to ensure everything works smoothly.

In this chapter, we’ll walk through how to upgrade a Kubernetes cluster—whether we’re using kubeadm, minikube, or managed services like Google Kubernetes Engine (GKE). We'll focus mainly on clusters managed with kubeadm, as that gives us more control and is common in many on-prem and cloud setups.

Why Upgrading Matters

Kubernetes follows a quarterly release cycle. Each release is supported for approximately 12 months, so we should plan to upgrade at least once or twice a year.

The following list highlights why upgrading matters −

  • Security Fixes: Each version includes patches for known vulnerabilities.
  • New Features: Kubernetes evolves rapidly, and new capabilities can improve performance, security, and usability.
  • API Deprecations: Staying up to date helps avoid using deprecated APIs that may be removed in future versions.
  • Community Support: Older versions eventually stop receiving support or updates from the Kubernetes community.

Types of Upgrades

  • Control Plane (Master) Components: kube-apiserver, kube-controller-manager, kube-scheduler, etc.
  • Node Components: kubelet, kube-proxy, container runtime (e.g., containerd), and CNI plugins.
  • Add-ons: DNS, network plugins (like Calico or Flannel), metrics-server, etc.
  • Applications: Anything running on top of Kubernetes (this is usually upgraded separately).

Pre-Upgrade Checklist

Backup your cluster: Use tools like etcdctl, Velero, or kube-backup to back up your etcd database and Kubernetes resources.

Check the version skew policy: Kubernetes only supports a one-minor-version difference between control plane components and kubelets. So if we're on v1.27, we can upgrade to v1.28 directly, but not to v1.29.

Prerequisites

  • You have a Kubernetes cluster initialized with kubeadm.
  • You have root or sudo access on all nodes.
  • All nodes are healthy and Ready.

Upgrading a Kubeadm Cluster

Most production clusters use kubeadm to manage control plane and node upgrades. We’ll break this into control plane and node steps.

In this guide, we’re using Kubernetes version 1.31.6 and we want to upgrade to version 1.31.8.

Check Current Version

$ kubectl version

Output

Client Version: v1.31.6
Kustomize Version: v5.4.2
Server Version: v1.31.6
$ kubeadm version

Output

kubeadm version: &version.Info{Major:"1", Minor:"31", GitVersion:"v1.31.6",
GitCommit:"6b3560758b37680cb713dfc71da03c04cadd657c", GitTreeState:"clean",
BuildDate:"2025-02-12T21:31:09Z", GoVersion:"go1.22.12", Compiler:"gc", 
Platform:"linux/amd64"}

Check Available Upgrade Options

$ sudo kubeadm upgrade plan

Output

Upgrade to the latest version in the v1.31 series:
COMPONENT                 NODE           CURRENT    TARGET
kube-apiserver            controlplane   v1.31.6    v1.31.8
kube-controller-manager   controlplane   v1.31.6    v1.31.8
kube-scheduler            controlplane   v1.31.6    v1.31.8
kube-proxy                               1.31.6     v1.31.8
CoreDNS                                  v1.11.3    v1.11.3
etcd                      controlplane   3.5.15-0   3.5.15-0

Upgrade kubeadm to v1.31.8

Run this command to check if v1.31.8 is available:

$ apt-cache madison kubeadm
 kubeadm | 1.31.8-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.7-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.6-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.5-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.4-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.3-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.2-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.1-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages
   kubeadm | 1.31.0-1.1 | https://pkgs.k8s.io/core:/stable:/v1.31/deb  Packages

Now upgrade:

$ sudo apt-get install -y kubeadm=1.31.8-1.1

Output

Preparing to unpack .../kubeadm_1.31.8-1.1_amd64.deb ...
Unpacking kubeadm (1.31.8-1.1) over (1.31.6-1.1) ...
Setting up kubeadm (1.31.8-1.1) ...

Verify:

$ kubeadm version

Output

kubeadm version: &version.Info{Major:"1", Minor:"31", GitVersion:"v1.31.8",
GitCommit:"3f46d435cd795e85aeea6b1a73742edad13b5222", GitTreeState:"clean",
BuildDate:"2025-04-22T15:58:45Z", GoVersion:"go1.23.6", Compiler:"gc", Platform:"linux/amd64"}

Apply the Control Plane Upgrade

$ sudo kubeadm upgrade apply v1.31.8

Output

[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.31.8". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.

Upgrade kubelet and kubectl on the Control Plane

$ sudo apt-get install -y kubelet=1.31.8-1.1 kubectl=1.31.8-1.1

Output

Preparing to unpack .../kubectl_1.31.8-1.1_amd64.deb ...
Unpacking kubectl (1.31.8-1.1) over (1.31.6-1.1) ...
Preparing to unpack .../kubelet_1.31.8-1.1_amd64.deb ...
Unpacking kubelet (1.31.8-1.1) over (1.31.6-1.1) ...
Setting up kubectl (1.31.8-1.1) ...
Setting up kubelet (1.31.8-1.1) ...

Then restart the kubelet:

$ sudo systemctl daemon-reexec
$ sudo systemctl restart kubelet

Verify:

$ kubectl get nodes

Output

NAME           STATUS   ROLES           AGE    VERSION
controlplane   Ready    control-plane   147m   v1.31.8
node01         Ready    <none>          147m   v1.31.6

Troubleshooting

  • If kubeadm upgrade apply fails with a version mismatch error, ensure your local kubeadm is upgraded first.
  • Use --dry-run with most commands to preview changes.
  • If you see component issues, restart the node or check logs with journalctl.

Conclusion

We’ve successfully upgraded our Kubernetes cluster from v1.31.6 to v1.31.8 using kubeadm, one node at a time. The key is to:

  • Upgrade kubeadm
  • Use it to apply the upgrade
  • Then upgrade kubelet and kubectl

This upgrade flow ensures a smooth, stable transition between patch versions in the same minor series.

Advertisements