Skip to content

APT Package Management for Kubernetes Upgrades

Reference: https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/


Why Package Pinning Exists

In a production cluster, you never want apt upgrade or an automated update system to accidentally pull a new Kubernetes version. A surprise kubelet upgrade can kill running workloads — the kubelet restarts and takes all containers on that node with it.

apt-mark hold <package> pins a package to its current version. It's excluded from all upgrades — even apt upgrade or unattended-upgrades — until you explicitly unhold it.

apt-mark hold kubeadm kubelet kubectl

This means you can safely run apt upgrade on the system (for OS security patches) without accidentally touching Kubernetes packages.


The Hold / Unhold Pattern

Every single Kubernetes package upgrade follows this exact pattern:

1. apt-mark unhold <package>     ← remove the pin so you can install a different version
2. apt-get install -y <package>=<exact version>
3. apt-mark hold <package>       ← re-pin it so future upgrades can't touch it

Why re-pin after installing? If you forget to re-hold, the next time someone runs apt upgrade the package gets bumped to whatever the latest version is. That's exactly the accident you were trying to prevent.


apt-mark Commands

apt-mark hold kubeadm           # pin — exclude from upgrades
apt-mark unhold kubeadm         # unpin — allow version change
apt-mark showhold               # list all currently held packages

Verify a package is held:

apt-mark showhold | grep kubeadm

If it returns kubeadm, it's pinned. If it returns nothing, it's not pinned.


Finding What Versions Are Available — apt-cache madison

apt-cache madison kubeadm

What apt-cache madison does: Queries the local APT package cache and lists all available versions of a package from all configured repositories, in descending order (newest first).

Output:

   kubeadm | 1.34.5-1.1 | https://pkgs.k8s.io/...
   kubeadm | 1.34.4-1.1 | https://pkgs.k8s.io/...
   kubeadm | 1.34.3-1.1 | https://pkgs.k8s.io/...

If you're on 1.34.3, the next version up is 1.34.4. That is the version you install. Not 1.34.5.

If apt-cache madison returns nothing or only shows your current version:

apt-get update
apt-cache madison kubeadm

apt-get update refreshes the package index from the configured repositories. Without this, APT only knows about versions it already saw — it won't know about packages released since the last update. Always run apt-get update before checking versions.


Version Format — What Is -1.1?

When you see 1.34.4-1.1 in the apt output:

  • 1.34.4 = the Kubernetes version
  • -1.1 = the Debian/Ubuntu package revision (the packaging build number, not a Kubernetes thing)

When you install, you include the full string:

apt-get install -y kubeadm='1.34.4-1.1'

The quotes and exact string matter. apt-get install kubeadm=1.34.4 without the -1.1 suffix will fail or install the wrong thing.


Full Upgrade Command — With Every Flag Explained

apt-mark unhold kubeadm && \
apt-get update && \
apt-get install -y kubeadm='1.34.4-1.1' && \
apt-mark hold kubeadm
Part What it does
apt-mark unhold kubeadm Remove the version pin so apt can install a different version
&& Only proceed to the next command if the previous one succeeded. If unhold fails, nothing else runs.
apt-get update Refresh the package index from repositories. Without this, apt might not know the new version exists
apt-get install -y kubeadm='1.34.4-1.1' Install exactly this version. -y = auto-yes to all prompts (non-interactive, needed in scripts)
apt-mark hold kubeadm Re-pin it so future apt upgrades don't touch it

Why chain with && instead of ;? - && = run next command only if previous succeeded (exit code 0) - ; = run next command regardless of whether previous failed

If apt-get update fails (no network, repo down), you don't want to install a package with a stale index. && stops the chain immediately on failure.


apt-get vs apt

apt-get install -y kubeadm='1.34.4-1.1'   # scripting — stable, predictable output
apt install kubeadm='1.34.4-1.1'           # interactive use — same thing with a progress bar

In scripts and exam answers, use apt-get. It has stable, parseable output designed for scripting. apt is the human-friendly frontend — the output format can change between versions.


Verify the Install

kubeadm version

Always run this after installing. Never skip it. If the install silently failed (package already at that version, or apt error that was swallowed), kubeadm upgrade apply with the old binary does nothing — and you won't know why. Verify first.