Cluster Upgrades in Kubernetes

Cluster Upgrades in Kubernetes

Kubernetes ships a new version about every four months, and every cluster has to keep up. Learn how upgrades really work, in what order things must change, how to keep your applications online while it happens, and how to recover when something goes wrong.

Imagine you live in a large apartment building, and the owner announces that the plumbing, the wiring and the elevators all need replacing this year. Nobody wants to move out. Everyone still needs water in the morning and light at night. So the workers plan carefully: one floor at a time, one pipe at a time, with notices on every door and a spare route for the water while the old one is switched off.

Upgrading a Kubernetes cluster is exactly like that. Your cluster is the building. Your applications are the residents who refuse to leave. The Kubernetes software that runs the cluster must be replaced piece by piece, and during all that work the lights must stay on. Done with care, upgrades are boring, and boring is the goal. Done carelessly, they cause some of the most memorable outages in our industry.

This guide assumes you know nothing about the topic. We will explain every new word the first time it appears, use everyday comparisons for each big idea, and build up from the basic rules of version numbers to the habits that experienced platform teams use to upgrade dozens of clusters without losing sleep.

Why Upgrades Matter, and Why They Feel Scary

Before learning the steps, it helps to understand why you cannot simply leave a working cluster alone.

What is a cluster upgrade?

A Kubernetes cluster is a group of computers that work together to run your applications. Some of these computers form the control plane, which is the brain that decides what should run where. The others are worker nodes, the machines that actually run your containers. A cluster upgrade means moving all of these parts from one Kubernetes version to a newer one, for example from version 1.30 to version 1.31.

It sounds like installing an update on a phone, but there is a big difference. A phone is one device and it can restart whenever it likes. A cluster is dozens or hundreds of machines running thousands of other people’s programs, and every one of those programs expects the cluster to keep working while it is being changed.

Everyday analogy

Think of an airline that wants to fit new engines to its planes. It cannot cancel every flight for a month. Instead it takes one plane out of service at a time, swaps the engines, tests it, and puts it back, while the other planes carry on flying the schedule. A cluster upgrade is the same dance: take a little capacity out, change it, test it, return it, and move on to the next piece.

Four reasons you must keep upgrading

Security

Old versions stop getting fixes

The Kubernetes community only provides security patches for the most recent few versions. Once your version falls off that list, newly found weaknesses stay open forever.

Support

Vendors and add-ons move on

Cloud providers, networking plugins and storage drivers all test against recent versions. Running an old one means you are on your own when something breaks.

Features

New abilities and fixes arrive

Each release adds improvements to scheduling, storage, security and stability that you can only use after upgrading.

Debt

Small steps are safer than big jumps

Skipping upgrades does not remove the work. It stacks the changes into one huge, risky leap that nobody on the team remembers how to do.

Why it feels scary

Teams fear upgrades for good reasons. The control plane is a shared dependency for everything. Some features get removed between versions, so a manifest that worked yesterday may be rejected tomorrow. Add-ons such as networking plugins have their own version rules. And stateful applications, such as databases, do not like having their machines taken away.

The good news is that almost every danger is predictable. Kubernetes publishes clear rules about which versions work together, which features are going away and in what order components must be changed. The skill is in learning those rules and turning them into a calm, repeatable routine.

~3 per year
New Kubernetes minor versions released
3 versions
Kept in community support at any time
~14 months
Approximate patch support for one minor version
!
Mindset

The safest upgrade is a small, frequent, well-rehearsed one. If an upgrade feels like a special event, you are probably doing it too rarely.

Kubernetes Versions and the Release Rhythm

Understanding the numbers in a version tells you how risky a change is.

Reading a version number

Kubernetes uses a three-part number such as 1.31.4. The first part, 1, is the major version, and it has stayed at 1 for years. The middle part, 31, is the minor version and is the one that matters most. The last part, 4, is the patch version.

PartWhat it meansTypical riskHow often
Patch (1.31.4)Bug and security fixes only, no new featuresLowRoughly monthly
Minor (1.31.4)New features, changes, deprecations and removalsMedium to high, needs planningAbout three times a year
Major (1.31.4)Reserved for huge breaking changesNot used recentlyNever lately

The release rhythm

The Kubernetes project follows a steady schedule. Roughly every four months a new minor version is released, and each one is supported with patches for about a year plus a couple of months to give people time to move. At any moment the project looks after the three most recent minor versions. When a fourth one arrives, the oldest falls out of support.

This means that if you installed a version and never touched it, you will be outside of support in a little over a year. There is no long-term support edition in the open source project. Some cloud vendors offer paid extended support, but that is only a delay, not an escape.

Everyday analogy

Think of milk in a shop. Every few days a fresh batch arrives, and the shop removes the oldest bottles from the shelf. You are free to keep a bottle at home for a long time, but nobody will vouch for it after the date on the label. Kubernetes versions have a label date too.

Patch upgrades versus minor upgrades

A patch upgrade, for example from 1.31.2 to 1.31.4, is usually uneventful. You can often apply it in a short window with the same process as a minor one but with far fewer surprises. A minor upgrade, from 1.30 to 1.31, is where the real planning is needed. You must read the release notes, check deprecated features, and test your add-ons.

One rule is absolute: you upgrade one minor version at a time for the control plane. To go from 1.29 to 1.32 you pass through 1.30 and 1.31 on the way. Skipping a minor version is not supported, because the project only tests the move from one version to the very next.

The deprecation policy

Kubernetes makes a promise about removing features. When something is going to be removed, it is first marked deprecated, which is a warning label meaning “stop using this, it will disappear”. The project then keeps it for a minimum period before removal. Stable (general availability) APIs are promised to last much longer than beta ones, while alpha ones can change or vanish quickly. Because of this promise, you get advance warning, but only if you read the notes and watch the warnings your cluster prints.

!
Do not rely on luck

A deprecation warning is easy to ignore until the version where the feature is finally removed. Treat each warning as a small task on your to-do list, not as background noise.

What Actually Gets Upgraded

A cluster is many separate programs, and each has its own version and its own rules.

When people say “upgrade the cluster” they usually mean many different upgrades bundled together. It helps to list every piece, because forgetting one is a common mistake.

Control plane

kube-apiserver

The front door of the cluster. Every command and every component talks through it. It is always upgraded first.

Control plane

Controller manager and scheduler

The controller manager runs the loops that keep things in the desired state. The scheduler chooses which machine each new pod lands on.

Storage

etcd

The database that stores the entire state of the cluster. It has its own version and must be backed up before any serious change.

Nodes

kubelet

The agent on each worker machine that starts and stops containers as instructed by the control plane.

Nodes

kube-proxy

Handles network rules on each node so that Services can find their pods.

Nodes

Container runtime

The program, such as containerd or CRI-O, that really runs containers. It has its own compatibility range.

Add-ons

Network, DNS and storage drivers

The network plugin, the DNS service called CoreDNS, and storage drivers all need to match the new Kubernetes version.

Extensions

Operators, webhooks and custom resources

Third-party add-ons that extend Kubernetes. They may depend on API versions that change or disappear.

Everyday analogy

A hospital has surgeons, nurses, a records system, pharmacy deliveries and cleaners. Upgrading “the hospital” does not mean one change. It means updating each department in the right order so that patients keep receiving care. The control plane is the management office, the nodes are the wards, and the add-ons are the support services that everyone leans on.

Where the control plane lives

How you upgrade the control plane depends on how it was built. In a self-managed cluster, which you build yourself with tools such as kubeadm, you own the control plane machines and must upgrade them directly. In a managed cluster, such as Amazon EKS, Google GKE or Azure AKS, the cloud provider runs the control plane for you and upgrades it when you press the button or when your schedule says so. In both cases you still own the nodes and the add-ons, which is why even managed services need a careful routine.

Two kinds of state

It also helps to separate what the cluster is made of from what the cluster remembers. The programs can be replaced freely. The data in etcd, the cluster’s memory, cannot. Almost every safe upgrade plan therefore starts with the same step: take a verified backup of that memory before touching anything else.

Version Skew: Who Can Be Older Than Whom

During an upgrade, different parts of the cluster run different versions for a while. The skew rules say how different they may be.

What is version skew?

Because you cannot change everything at the same instant, your cluster will spend some time in a mixed state. For example, the control plane may already be on 1.31 while the nodes are still on 1.30. The difference in version numbers between two components is called skew. Kubernetes publishes a strict policy that describes the largest skew each pair of components can handle.

flowchart TB
    API["kube-apiserver at version N - always upgraded first"]
    CMS["controller-manager, scheduler, cloud-controller-manager: N or one older"]
    KUB["kubelet: up to three minor versions older than N, never newer"]
    PRX["kube-proxy: no newer than kubelet, within the kubelet range"]
    CTL["kubectl: one minor older or newer than N"]
    API --> CMS
    API --> KUB
    KUB --> PRX
    API --> CTL
    
Figure 1 — Allowed version differences, measured against the API server version N
ComponentAllowed relative to kube-apiserverPlain meaning
Other kube-apiserver copies (in a highly available control plane)Within one minor versionWhile you roll the control plane, copies may differ by one step
kube-controller-manager, kube-schedulerSame version or one older, never newerUpgrade them after the API server
kubeletSame or older by up to three minor versions, never newerNodes can lag behind, which gives you time to upgrade them
kube-proxyNot newer than the API server and within the kubelet skew rangeKeep it close to the kubelet on the same node
kubectlOne minor version newer or olderKeep your own tools current too

Why the order follows the skew

These rules explain the upgrade order. Because the API server must never be older than the other pieces, it goes first. Because a kubelet must never be newer than the API server, nodes go after. Because nodes are allowed to be several versions behind, you do not have to upgrade every machine in one maintenance window. You can spread node upgrades over days or weeks.

Everyday analogy

Imagine a head office that sends instructions to branch offices. The head office can start using a new form, and the branches can keep using an older version for a while because the head office still understands it. But a branch must never start using a form that the head office has not learned yet. Newer-than-the-boss is the thing that is not allowed.

The three-version window is a gift, not a goal

The wide room for kubelets, which grew in recent releases, exists to give teams breathing space. It is not an invitation to leave nodes behind indefinitely. Old nodes miss security fixes, and some features simply do not work when nodes lag. Aim to finish node upgrades soon after the control plane, ideally within the same week.

!
Check the current policy

The exact skew numbers have changed between releases, for example the allowed kubelet lag increased in a recent version. Always confirm the numbers in the official version skew policy for the version you are targeting before you plan.

The Upgrade Order and Lifecycle

There is a standard order of operations that nearly every Kubernetes upgrade follows. Learn it once and reuse it forever.

flowchart LR
    A["1. Plan: read release notes and check deprecated APIs"] --> B["2. Back up etcd and key configuration"]
    B --> C["3. Upgrade the control plane, one node at a time"]
    C --> D["4. Upgrade cluster add-ons: network, DNS, proxy"]
    D --> E["5. Upgrade worker nodes in small batches"]
    E --> F["6. Validate: health checks, tests, dashboards"]
    F --> G["7. Document, clean up and plan the next upgrade"]
    
Figure 2 — The standard lifecycle of a minor version upgrade
1

Plan

Read the release notes for the target version, list removed and deprecated features, and confirm that your add-ons support the new version. Choose a time when traffic is low and when staff are available.

2

Back up

Take a snapshot of etcd and save copies of important configuration. Test that you can read the backup. A backup you have never tried to restore is only a hope.

3

Control plane

Upgrade the API server first, then the controller manager and scheduler, one control plane machine at a time, checking health after each step.

4

Add-ons

Upgrade or verify the network plugin, DNS, kube-proxy and similar components to versions that support the new Kubernetes release.

5

Nodes

Work through the worker machines in small batches. For each, move pods off safely, upgrade or replace it, and bring it back before starting the next batch.

6

Validate

Confirm all nodes report the new version, all system pods are healthy, test traffic passes, and your key dashboards look normal.

7

Wrap up

Record what happened, fix anything that surprised you, and update your runbook so the next upgrade is easier.

Where the order comes from

This order is not arbitrary. It is the direct result of the skew rules and of how components depend on each other. The API server is what everything else talks to, so it must be able to understand both old and new clients. Nodes only need to speak to the API server, so they can follow later. Add-ons sit in between because they depend on both sides.

i
Environments first

Practice the full sequence on a development cluster, then a staging cluster that resembles production, and only then production. Every problem found early is a problem your customers never see.

Before You Upgrade: The Readiness Checklist

Most upgrade failures are decided before the first command is typed. Preparation is where the real work lives.

Read the release notes

Every Kubernetes release comes with notes that describe new features, deprecations, removals and “urgent upgrade notes” that call out changes requiring action. Read the sections for every minor version you are crossing. It takes an hour and saves days. Look especially for removed APIs, changed defaults, and changes in the behavior of the kubelet and container runtime.

The checklist

AreaQuestion to answerWhy it matters
Deprecated APIsDoes anything we run use an API version that is removed in the target?Removed APIs make deployments and tools fail immediately
Add-on compatibilityDoes every add-on list support for the new version?Unsupported networking or storage drivers can break pods
BackupsDo we have a recent etcd snapshot, and have we tested a restore?It is your only real way back from a bad control plane failure
CapacityCan the cluster run its workload with one batch of nodes missing?Draining nodes shifts load onto the others
Disruption budgetsAre PodDisruptionBudgets present and reasonable?Too strict blocks the drain, too loose lets too many pods vanish
CertificatesWhen do cluster certificates expire?Expired certificates cause sudden outages, and upgrades are a good time to renew
WebhooksAre admission webhooks healthy and tolerant of restarts?A broken webhook can block new pods from starting
People and timingWho is on call, and is there a freeze on other changes?Surprises multiply when many changes happen together
Rollback planWhat will we do if step three fails?Decide while calm, not in the middle of an incident

Check the health of the cluster first

Never start an upgrade on a cluster that is already unhealthy. If some nodes are not ready, some system pods are crashing or etcd is complaining, fix those first. Otherwise you will not know whether a problem after the upgrade was caused by the upgrade or was already there. Take a note of the state before you begin: how many nodes, how many pods, which alerts are firing. This becomes your “before” picture.

Everyday analogy

Before a long road trip you check the tires, the oil and the fuel, and you plan where to stop. You do not set off with a warning light already glowing on the dashboard. A readiness checklist is your pre-trip inspection.

Communicate

Tell the teams that run applications on the cluster what is coming and when. Share the plan, the time window, what they might notice, and how to reach you. Good communication turns a surprise into a scheduled event, and it gives application owners a chance to say “please do not do this during our launch”.

!
Practical tip

Keep the checklist in version control as a living document. Each upgrade, add the lesson you learned. After a few rounds you will have a runbook tailored to your own cluster.

Deprecated and Removed APIs

The number one cause of broken upgrades is a feature that was removed while someone was still using it.

What is an API version?

Every kind of object in Kubernetes, such as a Deployment or an Ingress, is described by an API group and version, written at the top of its definition. As features mature, their version changes from a beta label to a stable one. When the stable version is ready, the older beta version is deprecated and, after a waiting period, removed from the API server.

If your configuration files, deployment tools or add-ons still use a removed version, the API server will simply refuse them. The failure can be sudden: your next deployment fails, an operator crashes, or a pipeline that has worked for years turns red.

Famous removals

VersionWhat was removedWhat to use instead
1.22Beta versions of Ingress and several other older APIsThe stable networking Ingress API
1.24Dockershim, the built-in bridge to Docker Enginecontainerd or CRI-O as the container runtime
1.25PodSecurityPolicy and the beta CronJob APIPod Security Admission, and the stable batch CronJob API
1.26Older beta versions of the HorizontalPodAutoscalerThe stable autoscaling v2 API
1.29Older beta versions of flow control APIsThe newer flowcontrol API versions

These examples show that removals come in many flavors. Some are plain version changes in a configuration file. The dockershim removal was a deeper change that forced teams to migrate their container runtime on every node. The removal of PodSecurityPolicy required a new approach to security rules altogether.

Everyday analogy

It is like a country changing its electrical plug standard. Appliances you own may still be perfectly good, but they will not fit the new sockets. A warning period lets you buy adapters or new appliances, but only if you notice the notice.

How to find what you are using

Live cluster

API server metrics and warnings

The API server counts requests made to deprecated APIs in a metric, and prints warnings to clients. Watching these over a few weeks shows real usage, including from controllers you forgot about.

Scanners

Pluto and kube-no-trouble

Open source tools that scan running resources, manifest files and Helm releases and report deprecated or removed API versions.

Validation

Schema checkers in your pipeline

Tools such as kubeconform validate manifests against the schemas of the target version, so a mistake is caught in review, not at deploy time.

Conversion

kubectl convert plugin

Helps rewrite old manifests to newer API versions, saving manual editing.

Things people forget

  • Helm releases: Helm stores the manifests of each release inside the cluster. If those stored manifests use a removed API, Helm may fail to upgrade or roll back that release. A community plugin exists to rewrite them.
  • Operators and controllers: A tool installed years ago may still call an old API. Check vendor notes and update them before the control plane.
  • CI and deployment tools: Pipelines, templates and internal scripts often hold their own copies of old manifests.
  • Stored objects: Data in etcd is saved in a particular version. When an old version is going away, a migration step rewrites stored objects into a newer form so nothing is left unreadable.
!
Fix before you upgrade

Update manifests and tools to the new API versions before the control plane upgrade, while the old version still works. Both versions are usually served together for a while, which makes this a calm change instead of an emergency.

Upgrading the Control Plane

The control plane is the brain of the cluster. The goal is to change it without ever letting the cluster lose its mind.

Why the control plane is special

While the control plane is briefly unavailable, your existing applications keep running, because the kubelet on each node continues to look after the containers it already has. What stops working is change: you cannot deploy, scale, or replace failed pods, and nothing reacts to events. A short control plane pause is usually harmless, but a long one is a serious risk, especially if a node fails during that time.

Everyday analogy

Picture an air traffic control tower being renovated. Planes already in the air keep flying along their agreed routes, and pilots keep following their instructions. But no new flights can be coordinated until the tower works again. The tower should therefore be renovated with a second tower standing by.

High availability makes it safe

A production control plane normally runs on three machines, each with a copy of the API server, the controller manager, the scheduler and, in the common layout, etcd. Because there are three copies, you can take one down while the other two continue serving. This is what makes a rolling control plane upgrade possible with no downtime.

There is one rule to respect here. etcd uses a voting system called quorum, meaning a majority of members must agree. With three members, two must be healthy. If you take one down for upgrade and a second one fails at the same time, the cluster freezes. So you upgrade one control plane machine at a time and wait until it is fully healthy before touching the next.

The typical sequence with a self-managed cluster

1

Upgrade the tooling

Install the new version of the cluster management tool, for example kubeadm, on the first control plane machine. Run its planning command, which checks that the cluster can move to the target version and lists the components and versions it will change.

2

Apply to the first control plane node

The tool upgrades the API server, controller manager, scheduler and, if it manages them, etcd and the cluster DNS and proxy add-ons. It also renews the control plane certificates by default, which is a useful side benefit.

3

Upgrade the node agent on that machine

Move the machine’s pods away, upgrade the kubelet and command line tool packages, restart the kubelet, and mark the machine schedulable again.

4

Repeat on the other control plane machines

For each remaining machine, use the lighter “upgrade node” form of the command, then update its kubelet in the same way. Check health between each machine.

5

Verify

Confirm that every control plane component reports the new version, etcd has a healthy quorum, and the API server answers quickly.

Small but important details

  • Load balancer: The load balancer in front of the API servers should stop sending requests to a machine that is being upgraded. Make sure its health checks work.
  • Webhooks: If admission webhooks that are configured to fail closed point at services on the same cluster, a restart can briefly block object creation. Know which ones you have.
  • Leader election: The controller manager and scheduler elect one active copy, so brief changes of leader are normal during the rollout.
  • Managed control planes: In a managed service, this whole chapter becomes one action in the provider’s console or tooling, but the provider still expects you to prepare in the same ways and to upgrade your own nodes afterwards.
!
Do it slowly

The control plane upgrade is the step with the fewest machines but the largest impact. Take your time, check health after each machine, and never run two risky actions at once.

Upgrading Worker Nodes: Cordon, Drain, Uncordon

Worker nodes are where your applications live. Upgrading them safely means moving the residents out gently before the walls are repainted.

Three verbs to remember

Node upgrades use a small vocabulary of three actions. Once you understand them, every node strategy in this guide is just a variation on the same theme.

Step A

Cordon

Mark the node as unschedulable. Existing pods stay put, but no new pods are placed there. Think of it as hanging a “no new guests” sign on the door.

Step B

Drain

Politely ask every pod on the node to leave. Kubernetes evicts them and their controllers start replacements on other nodes.

Step C

Uncordon

After the node is upgraded and healthy, remove the sign so that new pods may be placed there again.

sequenceDiagram
    participant OP as Operator or Automation
    participant API as API Server
    participant OLD as Node being upgraded
    participant SCH as Scheduler
    participant OTH as Other healthy nodes
    OP->>API: Cordon the node
    API->>OLD: Mark as unschedulable
    OP->>API: Drain the node
    API->>API: Check PodDisruptionBudgets for each pod
    API->>OLD: Evict pod with a graceful shutdown
    OLD-->>API: Pod has stopped
    API->>SCH: Controller creates a replacement pod
    SCH->>OTH: Place replacement on a healthy node
    OTH-->>API: Replacement is ready
    OP->>OLD: Upgrade kubelet and restart it
    OP->>API: Uncordon the node
    
Figure 3 — The life of one node upgrade, from the cordon sign to the uncordon

What happens during a drain

A drain does not simply delete pods. It uses the Eviction API, a polite request that the API server checks against any PodDisruptionBudget (PDB) before allowing it. A PDB is a rule that says how many copies of an application must stay available at any time. If removing a pod would break that rule, the eviction is refused and the drain waits and retries.

Once a pod is evicted, it receives a termination signal and gets a grace period to finish its work, 30 seconds by default. Well-written applications use this time to stop taking new requests, finish current ones, close connections and exit. Then the owning controller, such as a Deployment, notices a missing replica and creates a new pod, which the scheduler places on another node.

Everyday analogy

Draining a node is like closing a restaurant section for cleaning. The host stops seating new tables there (cordon), waiters help current diners finish their meals and move to other sections (drain), and when cleaning is done the host opens the section again (uncordon). A rule that says “at least half the tables must stay open” is a PodDisruptionBudget.

What a drain does not save

  • DaemonSet pods run one per node by design, so a drain skips them. You normally tell the command to ignore them.
  • Bare pods that were created directly without any controller are not recreated elsewhere. They are gone once evicted, so avoid using them in real workloads.
  • Local temporary storage in a pod is erased when it leaves. The drain command requires you to acknowledge this explicitly.
  • Pods that ignore shutdown signals will be force killed after the grace period, which can drop in-flight requests.

Upgrading the node itself

With the node empty, you upgrade its software: the kubelet, the container runtime if required, and often the operating system too. Then restart the kubelet, wait until the node reports ready on the new version, and uncordon it. Many teams use this moment to also apply operating system patches, since the machine is already empty and will restart anyway.

!
Set a timeout

Use a drain timeout so that automation does not hang forever on a stubborn pod. When a drain times out, a human or a smart workflow should decide what to do, rather than blindly forcing the pod off.

Node Upgrade Strategies Compared

There are three main ways to move a fleet of nodes to a new version. Each trades speed, cost and safety differently.

Strategy 1: In-place upgrade

With an in-place upgrade, you take each existing machine, drain it, upgrade its software while it is still the same machine, and put it back. This is what traditional kubeadm-style workflows do. It needs no extra machines, so it costs nothing extra, but it reduces your capacity by one machine (or one batch) at a time, and any drift on old machines comes along for the ride.

Strategy 2: Rolling replacement with surge

With rolling replacement, you do not upgrade old machines at all. Instead you create fresh machines already running the new version, move workloads over, and then delete the old machines. Adding extra machines before removing old ones is called surge, and it means capacity never dips. Most managed services and infrastructure-as-code setups prefer this approach because the new machines come from a clean, known image.

Strategy 3: Blue/green node pools

In a blue/green node pool upgrade, you create an entire second group of nodes (the green pool) on the new version beside the old (blue) pool. Then you cordon and drain the blue pool in controlled steps, shifting everything to green. If something looks wrong, you can pause, and in many cases move back, because the old nodes still exist. The price is running double capacity for a while.

StrategyExtra costSpeedSafetyBest for
In-placeNoneMediumMedium, capacity dips during each batchSmall or on-premises clusters with no spare machines
Rolling with surgeA little, for the extra nodesFastHigh, capacity stays steadyMost cloud clusters and managed node groups
Blue/green node poolsDouble nodes during the moveSlower, with pausesHighest, easy to pause and compareCritical workloads where mistakes are very costly
Everyday analogy

Renovating a hotel offers three plans. In-place is repainting rooms one at a time while guests stay in the others. Rolling replacement is building a few spare rooms first, so you never run short. Blue/green is constructing a whole second wing, moving everyone across floor by floor, and only then demolishing the old wing.

Choosing batch size

All three strategies need a decision about how many nodes to change at once. Cloud services expose this as settings such as max surge (how many extra nodes may be created) and max unavailable (how many may be down at once). A small batch is safer but slower. A good starting point is to keep the number of unavailable nodes small enough that the rest of the cluster can comfortably carry the load, and then increase it once you trust your tests. Use one node first as a canary, check that workloads behave, and only then continue in larger batches.

Immutable nodes and drift

The industry is moving toward immutable nodes, which means you never patch a machine in place but replace it with a freshly built one. This avoids configuration drift, the slow buildup of small differences between machines that makes behavior hard to predict. Tools that automatically replace nodes whose image or version no longer matches the desired state, such as Karpenter’s drift handling, make this a natural fit for Kubernetes upgrades.

i
Remember the skew

Whichever strategy you choose, new nodes must obey the skew rules. They should run a kubelet version no newer than the control plane. Upgrade the control plane first, then build new nodes to match it.

Blue/Green Cluster Upgrades

Some teams skip in-place upgrades altogether. They build a brand new cluster and move traffic across.

The idea

Instead of changing a running cluster, you create a second cluster on the new version, deploy all your applications to it from the same source of truth, test it, and then gradually shift real user traffic. The old cluster stays alive until you are completely happy. If something goes wrong, you send the traffic back. This is sometimes called the blue/green cluster or cluster replacement pattern.

flowchart TB
    USR["Users"] --> GLB["DNS or Global Load Balancer"]
    GLB -->|"most traffic at first"| BLUE["Blue cluster at the current version"]
    GLB -.->|"small share, then growing"| GREEN["Green cluster at the new version"]
    REPO["Git repository with all desired configuration"] --> BLUE
    REPO --> GREEN
    BLUE --> DATA["Shared databases, queues and storage"]
    GREEN --> DATA
    
Figure 4 — Blue/green clusters sharing one source of truth and the same data services

Advantages

  • Skips the risky in-place changes to the control plane
  • Allows long, careful testing with real traffic
  • Rollback is as simple as moving traffic back
  • Lets you jump further than one minor version if you rebuild properly
  • Naturally removes drift and old, forgotten configuration

Disadvantages and trade-offs

  • Costs double for a period
  • Requires everything to be reproducible from code
  • State is hard: databases, queues and volumes need a plan
  • Needs a traffic switching layer outside the cluster
  • External addresses, certificates and allow-lists may change

What makes it work

Blue/green clusters only work when your platform is built for it. All configuration must live in version control and be applied automatically, a practice known as GitOps. Secrets, DNS records, certificates and load balancers must be created by automation rather than by hand. And any state that lives inside the cluster, such as persistent volumes, must either be moved with a tested process or kept outside the cluster in managed data services that both clusters can reach.

Everyday analogy

A restaurant opens a new kitchen next door with the same recipes and the same suppliers. For a week, only a few tables are sent to the new kitchen. When diners are happy, more tables move. The old kitchen stays ready until the owner is certain. The recipes (your code) are what make the move easy, as long as the pantry (your data) can be shared.

When to choose it

Blue/green clusters shine when the cost of a failed upgrade is very high, when your clusters are numerous and mostly stateless, or when you want to move several versions at once without a long chain of in-place steps. For a small team with a single stateful cluster, in-place or surge upgrades are normally simpler and cheaper.

Protecting Your Workloads During the Change

The cluster upgrade is only as smooth as the applications running on it are well behaved.

Draining a node is routine for Kubernetes, but it will expose any application that was not built to move. The best time to find out is before the upgrade. Here are the settings that decide whether your pods leave quietly or noisily.

Replicas

Run more than one copy

A single replica means the application is down every time its node is drained. Run at least two or three for anything that matters.

PodDisruptionBudget

Set a sensible minimum

Choose a number that keeps the service healthy but still leaves room to evict at least one pod. A rule that demands every replica always be available blocks every drain forever.

Spread

Use topology spread rules

Spread copies across different nodes and zones so a drain never removes all replicas at once.

Readiness

Accurate readiness checks

A replacement pod should only receive traffic when it is truly ready. Otherwise, the drain “succeeds” while users receive errors.

Shutdown

Handle termination signals

Stop accepting new work, finish current requests, and exit before the grace period ends. A short pause before shutdown gives load balancers time to stop routing to the pod.

Startup

Start quickly

Pods that take minutes to start slow every node drain. Smaller images and efficient start-up shorten the whole upgrade.

The trap of the too-strict budget

One of the most common upgrade blockers is a PodDisruptionBudget that cannot be satisfied. Suppose a Deployment has three replicas and its PDB says that three must always be available. Kubernetes can never evict even one pod without breaking that promise, so the drain waits forever. The same happens when a single-replica application has a budget requiring one pod to always be available. Check your budgets before the upgrade by looking for any whose allowed disruptions equal zero.

Everyday analogy

It is like a rule in a hospital that says “all ten nurses must be on duty at every minute of the day”. The rule sounds safe, but no nurse could ever take a break or go home, and the hospital would grind to a halt. A good rule says “at least eight must be on duty”, which leaves space for people to rotate.

Capacity during the move

While a node is empty, its pods have moved elsewhere. If the remaining nodes are already nearly full, replacement pods will remain Pending, the drain will stall, and your services will run on reduced capacity. Make sure there is enough spare room to lose a batch of nodes. Surge nodes, which add capacity before removing it, are the standard cure.

!
Test with a single node first

Drain one non-critical node in a test cluster and watch what happens. Every surprise you see there, such as pods that will not leave or services that return errors, is one fewer surprise during the real upgrade.

Stateful Workloads and Storage

Databases, message brokers and anything that remembers data need extra care when machines come and go.

Why state changes the game

A stateless web server can be thrown away and recreated in seconds, because it holds nothing important. A database holds the only copy of something precious, so moving it means moving data, replicating data, or at least reattaching a disk. Each of those steps takes time and can go wrong, which is why stateful workloads deserve their own upgrade plan.

Everyday analogy

Moving a stateless service is like moving a rented chair: pick it up and place it anywhere. Moving a database is like moving a grand piano. It needs the right people, the right route and a firm plan, and you do not hurry it.

Key issues to plan for

ConcernWhat can happenWhat to do
Volumes tied to a zoneA disk exists in one availability zone, so its pod can only run in that zone. A replacement node in another zone leaves the pod Pending.Make sure surge or new nodes exist in every zone that holds volumes
Volume detach and attach timeMoving a disk between machines can take a minute or moreAllow generous timeouts and avoid draining several stateful pods together
Local disksIf data is stored on a node’s own disk, replacing the node destroys itUse replication, and replace nodes one at a time while replicas catch up
Quorum-based systemsTaking too many members of a cluster down at once breaks consensusUse PodDisruptionBudgets that preserve a majority
Primary and replica rolesDraining the primary forces a failover at an awkward momentUpgrade replicas first and fail over to a healthy one in a planned way
Storage driversStorage plugins have version rules tooUpgrade or verify drivers before nodes

StatefulSets and their special ordering

A StatefulSet is the Kubernetes object designed for applications that need stable identities and storage. It updates pods one at a time in a fixed order and waits for each to be healthy before continuing. It also has a setting called partition that lets you update only some pods first, which is a convenient way to try a change on one replica before touching the rest.

Operators help, but verify

Many databases run under an operator, a piece of software that knows how to run that particular database on Kubernetes, including safe failovers. A good operator makes node drains much safer. But the operator is itself a program with API dependencies, so confirm its supported Kubernetes versions before the upgrade and read its notes on node maintenance.

!
Back up the data, not only the cluster

An etcd snapshot protects the cluster’s configuration. It does not protect your database contents. Make sure application-level backups are fresh and restorable before an upgrade that touches stateful nodes.

Add-ons, Networking and the Container Runtime

The extras you install around Kubernetes have their own version rules, and they cause a large share of upgrade trouble.

Add-ons are part of the cluster

A bare Kubernetes installation does little. Real clusters add a network plugin (also called CNI) so pods can talk to each other, CoreDNS so that names resolve, kube-proxy for service routing, storage drivers (CSI) to create volumes, an ingress controller to receive outside traffic, certificate managers, monitoring agents and often a service mesh. Every one of these has a compatibility table that says which Kubernetes versions it supports.

Network

CNI plugin

If the network plugin is incompatible, pods lose connectivity. Upgrade it according to its own guide, usually before or with the control plane.

DNS

CoreDNS

Every service lookup depends on it. Run several replicas so DNS stays up when pods move during node drains.

Storage

CSI drivers and snapshot controllers

Needed to create, attach and expand volumes. Check support for the target version.

Traffic

Ingress and gateways

Older controllers may depend on removed APIs. Test routes, certificates and rules after the upgrade.

Mesh

Service mesh proxies

Mesh components often require specific Kubernetes ranges and must be upgraded in their own careful order.

Operators

CRDs and controllers

Custom resource definitions and their controllers need compatible versions on both sides of the upgrade.

The container runtime

The container runtime is the engine that actually starts containers on each node. Kubernetes talks to it through a standard interface. For many years some clusters used Docker through a built-in bridge called dockershim. That bridge was removed in version 1.24, so clusters that depended on it had to move to containerd or CRI-O first. This change is a good reminder to check runtime versions, cgroup settings and any tools that expected to find the Docker socket on a node, such as older log collectors or build agents.

Everyday analogy

If the cluster is a city, the add-ons are the utilities: roads, water, electricity and mail. When you rebuild the city hall, you must also make sure the utilities still connect to it. Nobody notices good utilities, but everyone notices a day without water.

The safe approach to add-ons

  1. Make an inventory of every add-on, with its current version and its supported range.
  2. Read each project’s upgrade notes for the target Kubernetes version.
  3. Upgrade add-ons that must move first, as their guides specify, and leave the rest until after the control plane.
  4. Run tests that touch each add-on: a pod to pod connection, a DNS lookup, a volume creation, an ingress request.
  5. Keep this inventory in version control so the next upgrade starts from a ready list.
!
Order can matter

Some add-ons must be upgraded before the control plane, and others after. There is no universal answer, so always follow the add-on’s own documentation rather than assuming.

Managed Kubernetes and Cluster API

Cloud services and automation frameworks take over much of the effort, but not all of the responsibility.

Managed services

In services such as Amazon EKS, Google GKE and Azure AKS, the provider operates the control plane. You request a new version, and the provider upgrades the control plane machines, usually with no downtime for your workloads. You remain responsible for the nodes, the add-ons and your applications. Each provider has its own way of expressing policy.

ServiceHow versions and upgrades are handledThings to know
Amazon EKSYou start a control plane upgrade one minor version at a time. Managed node groups can roll nodes with a configurable number unavailable. Core add-ons such as the VPC CNI, CoreDNS and kube-proxy are updated separately.Versions have a standard support period, and a longer paid extended support option exists. Update add-ons as part of the plan.
Google GKEClusters follow release channels such as Rapid, Regular, Stable and Extended, with automatic upgrades. Node pools support surge upgrades and blue/green upgrades.Use maintenance windows and exclusions to avoid upgrades during busy periods.
Azure AKSYou can choose automatic upgrade channels for new versions or for patches only, and a separate channel for node images. Max surge controls how many extra nodes are used.Cluster and node pool versions are upgraded as separate steps.
Everyday analogy

Using a managed service is like renting a flat in a building with a caretaker. The caretaker looks after the lifts, the roof and the plumbing in the shared areas. But you are still responsible for your own furniture and for telling the caretaker when you will be out. The shared parts being cared for does not mean your own belongings are safe from the move.

Release channels and auto-upgrade

Letting the platform upgrade automatically is a good idea for non-production clusters and often for production too, as long as you control the timing. A release channel lets you choose how early you want to receive new versions. Early channels give you access to features sooner but with less time-tested software. Later channels favor stability. Pair them with maintenance windows, and test in an early-channel staging cluster before the same version arrives in production.

Cluster API: upgrades as a declaration

Cluster API is a Kubernetes project that treats clusters themselves as Kubernetes objects. You describe the cluster and its machine groups in YAML-style objects, and controllers create and maintain the real machines. To upgrade, you change the declared version on the control plane object, then on each machine group, and the controllers perform a rolling replacement of machines on your behalf. It turns the upgrade from a long manual runbook into a reviewed code change.

What you still own

  • Checking removed APIs and add-on compatibility.
  • Upgrading node groups and verifying that applications tolerate the move.
  • Choosing timing, batch sizes and the disruption budgets that protect your services.
  • Testing and monitoring, before, during and after.
i
One way only

Managed control planes generally cannot be downgraded once upgraded. Treat the upgrade as a one-way door and make your testing count before you walk through it.

Security During and After Upgrades

Upgrades are one of the best security tools you have, and also a moment when mistakes in access and process can hurt.

Why upgrading is a security practice

When researchers find a weakness in Kubernetes or in the software that runs underneath it, the fix is released in a new patch version of the supported releases. If your cluster is not on a supported version, there will be no fix for you. Falling behind on patches is the same as leaving a known unlocked door in your building. Regular patch upgrades keep that door shut at low risk, and minor upgrades keep you inside the support window.

Everyday analogy

A locksmith announces that a certain brand of lock can be opened with a paperclip and sends out replacements. If you do not change your lock, the announcement helps burglars more than it helps you, because now everyone knows the trick. Public security fixes make unpatched systems easier targets.

Access

Limit who can upgrade

Upgrade rights are extremely powerful. Use role-based access control, short-lived credentials and approvals for production changes.

Supply chain

Trust the source

Install packages and images only from official or verified repositories, and check signatures and checksums.

Certificates

Renew while you are there

Cluster certificates expire, often after a year. Upgrading with kubeadm renews control plane certificates, which prevents a surprise outage on the expiry date.

Policy

Replace removed controls

When a security feature is removed, such as PodSecurityPolicy, make sure its replacement, like Pod Security Admission, is already enforcing equivalent rules before the old one disappears.

Nodes

Patch the operating system too

The node upgrade is a convenient moment to apply operating system and runtime patches, using fresh images where possible.

Audit

Keep a record

Enable audit logs and record who approved and executed each upgrade step. These records matter for both investigations and compliance.

Security can break during an upgrade

Changes in defaults between versions can quietly alter your security posture. A new default might tighten something that used to be open, breaking an application, or an admission rule might stop being enforced after an API change. After every upgrade, run a short security smoke check: confirm that network policies still block what they should, that role bindings are unchanged, that admission controls are active, and that audit logging continues to flow.

!
Patch fast, minor on schedule

Many teams treat patch upgrades as a quick routine to apply within days of release, and plan minor upgrades on a regular quarterly rhythm. This keeps them safe without making every update a big event.

Monitoring and Validating the Upgrade

You cannot manage what you cannot see. During an upgrade, the right dashboards turn fear into facts.

What to watch while it happens

An upgrade is a short period when the system is deliberately changing, so normal alerts may fire and normal patterns may shift. Prepare a single dashboard that shows the vital signs of both the cluster and the applications on it. Watch it live during each step, and compare it with the “before” picture you recorded.

SignalHealthy during upgradeWarning sign
API server request latency and error rateBrief blips while a control plane node restartsSustained errors or very slow responses
etcd health and leader changesOne leader change when its host restartsRepeated elections or slow disk writes
Node readiness countOne batch temporarily NotReady or cordonedNodes staying NotReady after the upgrade
Pending and crash-looping podsA short spike while pods movePods stuck Pending or restarting repeatedly
Application error rate and latencyFlat or a tiny blipRising errors correlated with drains
DNS and network checksAlways passingAny failed lookup or connection
Deprecated API request metricFalling to zero over timeNew callers appearing
flowchart LR
    CP["Control plane metrics"] --> PROM["Prometheus or monitoring platform"]
    ND["Node and kubelet metrics"] --> PROM
    APPS["Application and SLO metrics"] --> PROM
    SYN["Synthetic checks and smoke tests"] --> PROM
    PROM --> DASH["Upgrade dashboard"]
    PROM --> ALRT["Alert routing"]
    DASH --> ENG["Engineer running the upgrade"]
    ALRT --> ENG
    
Figure 5 — Feeding one upgrade dashboard from the control plane, nodes, applications and synthetic checks

Smoke tests after each stage

A smoke test is a small, fast check that the basics still work. Run a handful after the control plane, after the add-ons and after each node batch. A good set includes creating and deleting a test deployment, resolving a service name through DNS, calling one service from another, creating a volume and attaching it to a pod, and reaching your application through its public address. Automate these so that they run the same way every time.

Everyday analogy

After a plumber works on a house, the owner turns on every tap, flushes every toilet and checks for leaks before paying the bill. Nobody waits for a flood to discover a missed pipe. A smoke test is that quick walk around the house.

Deeper validation

For major platform changes, you can also run the Kubernetes conformance tests, using a tool such as Sonobuoy. These are a large suite of tests that check whether a cluster behaves like a standard Kubernetes should. They do not replace your own application tests but they catch problems in the platform itself. Finish by comparing your final state with the “before” picture: same number of nodes, same set of healthy pods, no new alerts.

!
Define done

Write down what “finished” means before you begin: every node on the new version, all system pods healthy, smoke tests green, error rates normal for a set time. This stops you from declaring victory too early.

Rollback and Failure Recovery

Hope for a smooth upgrade, and plan for a rough one. The most important question is what you will do when a step fails.

The uncomfortable truth about downgrades

Kubernetes does not offer a supported, general way to downgrade a control plane to an earlier minor version. After the upgrade, data in etcd may be written in newer forms, and older components may not understand it. So “rollback” in Kubernetes rarely means flipping a switch back. It means one of a few different recovery paths, depending on what failed.

flowchart TD
    P["Problem seen during upgrade"] --> Q1{"Is the control plane healthy?"}
    Q1 -->|"No"| R1["Stop, diagnose, use the tool's own recovery or restore the etcd snapshot"]
    Q1 -->|"Yes"| Q2{"Are nodes or workloads failing?"}
    Q2 -->|"Yes"| R2["Pause the rollout, keep or restore the old node pool, move workloads back"]
    Q2 -->|"No"| R3["Continue with the next small batch and keep watching"]
    
Figure 6 — A simple decision path when something looks wrong mid-upgrade

Recovery paths by failure type

What failedRealistic recoveryNotes
A control plane step fails part wayFix the cause and re-run. Tools like kubeadm back up the control plane manifests and attempt to roll back automatically on failure.Remaining healthy control plane machines keep serving meanwhile
Control plane is broken beyond repairRestore etcd from the snapshot taken before the upgrade and rebuild the control plane at the old versionChanges made after the snapshot are lost, so move quickly and freeze other changes
A batch of nodes misbehavesStop the rollout. Replace those nodes with ones built from the previous known-good image, or move workloads back to the old node poolKeeping the old pool alive makes this fast
An add-on breaksRoll the add-on back to its previous version, as add-ons are normal workloadsThis is usually possible even after the control plane moved
An application breaks because of an API changeFix the manifest or roll the application back to a previous releaseThe cluster stays on the new version
Managed control plane upgrade has a problemOpen a provider support case and work around the issue on the node and application sideThe provider cannot usually downgrade it
Everyday analogy

A pilot cannot turn a plane around once it has passed the point of no return. So before takeoff a pilot knows exactly where the last safe turn-back point is, what to do if an engine fails before it and what to do after it. An upgrade plan has the same kind of point of no return: the control plane upgrade. Everything before it is easy to reverse, and everything after needs a different recovery plan.

Practice the restore

Restoring etcd is a rare operation with many fine details, such as restoring every member consistently and re-pointing components at the restored data. The worst time to learn those details is during an outage. Rehearse the restore on a throwaway cluster at least once a year, write the steps down, and time how long it takes. You will then know your real recovery time instead of guessing.

Design for reversible steps

The safest upgrade plans keep the largest number of steps reversible for the longest time. Keep old node pools until the new ones have carried production traffic. Keep old cluster copies until blue/green traffic has fully moved. Delay deleting backups. Make decisions you cannot undo as late in the process as possible, and only after validation passes.

!
Backups age

An etcd snapshot is only useful for the state it captured. If you take it a day before the upgrade and then change things, you will lose those changes on restore. Take the snapshot immediately before you begin and record the time.

Design Patterns and Anti-patterns

Teams with years of upgrade experience share a short list of habits and a longer list of regrets.

Patterns that work

Pattern 1

Small and often

Upgrade every minor version soon after it stabilizes, instead of waiting a year. Each step is small and practiced.

Pattern 2

Promote through environments

Dev first, then staging, then a canary slice of production, then the rest. Every stage uses the same automation.

Pattern 3

Canary node first

Upgrade one node, watch it carry real work, then continue in growing batches.

Pattern 4

Everything as code

Cluster definitions, add-ons and policies live in version control, so an upgrade is a reviewed change with history.

Pattern 5

Immutable, replaceable nodes

Build new node images for each version and replace old nodes, instead of patching them one by one.

Pattern 6

Automated pre-flight checks

Pipelines that scan for deprecated APIs and check add-on compatibility fail early, long before upgrade day.

Anti-patterns to avoid

ANTI-PATTERN 01 Avoid
The mistake

Postponing upgrades until the version is about to leave support, then doing several in a row.

Why it hurts

Changes pile up, nobody remembers the process, and a single mistake affects a large number of skipped versions.

Better approach

Adopt a regular cadence, such as one minor upgrade per quarter, so the work is routine.

ANTI-PATTERN 02 Avoid
The mistake

Testing only on an empty development cluster that looks nothing like production.

Why it hurts

Real problems come from real add-ons, real policies, real load and real quirks, none of which an empty cluster has.

Better approach

Keep a staging cluster that mirrors production’s add-ons, policies and workload types, and run realistic tests there.

ANTI-PATTERN 03 Avoid
The mistake

Forcing drains with flags that ignore disruption budgets to “get it done faster”.

Why it hurts

You bypass the very protection that keeps services up, and may remove every replica of an application at once.

Better approach

Fix the budget or the application, then drain normally. Treat forced drains as an exceptional action with approval.

ANTI-PATTERN 04 Avoid
The mistake

Upgrading the cluster and an application platform change on the same day.

Why it hurts

If something breaks, you cannot tell which change caused it, and the rollback of one may not fix the other.

Better approach

Freeze unrelated changes around upgrade windows so that cause and effect stay clear.

ANTI-PATTERN 05 Avoid
The mistake

Treating nodes as pets: logging in, patching by hand and keeping different versions on different machines.

Why it hurts

Each machine becomes unique, which makes upgrades unpredictable and hard to repeat.

Better approach

Build nodes from images and automation, and replace them rather than repair them.

Troubleshooting and Common Mistakes

When an upgrade stalls, the cause is nearly always on a short and familiar list.

What you seeLikely reasonWhat to do
Drain hangs foreverA PodDisruptionBudget allows zero disruptions, or a pod refuses to stopReview budgets, check which pod is blocking, fix the application or budget
Replacement pods stay PendingNot enough capacity, or volumes tied to a zone with no available nodeAdd surge capacity in the correct zones
Deployments or tools suddenly failA removed API version is still used in manifests or pipelinesUpdate manifests, use scanners and re-run
Nodes stay NotReadyNetwork plugin, runtime or kubelet configuration is incompatible with the new versionCheck kubelet logs and the add-on compatibility notes
Pod creation fails cluster-wideAn admission webhook is unavailable and set to fail closedRestore the webhook service or adjust its failure policy carefully
DNS lookups failCoreDNS pods not running or mismatched configurationCheck CoreDNS pods and configuration, restart if needed
Certificates rejected after upgradeExpired or unrenewed certificates, or clock differencesRenew certificates and check the time on all machines
kubectl warns about version differencesYour client is more than one minor version from the serverInstall a matching kubectl
Workloads behave oddly but everything is “green”A changed default, such as scheduling or security behaviorCompare against the release notes and test the affected feature

A useful order of investigation

1

Look at the control plane

Is the API server answering, and are its logs showing errors? Is etcd healthy with all members present?

2

Look at the nodes

Which nodes are NotReady or cordoned? What do the kubelet and runtime logs on those nodes say?

3

Look at system pods

Check the network plugin, DNS, proxy and storage drivers. A broken add-on often looks like a broken cluster.

4

Look at events

Cluster events state, in plain language, why pods fail to schedule or start.

5

Look at applications

Only after the platform is understood, check specific application symptoms and compare them with the timeline of node drains.

!
Keep a timeline

Write down what you did and when, as you do it. A simple running log makes it far easier to link a symptom to a step and to write a clear report afterwards.

Real-World and Industry Examples

Real incidents and real platforms show how these ideas play out in practice.

Reddit’s Pi Day outage

In March 2023, Reddit suffered a long outage and later published a detailed account. As they described it, the trigger was an upgrade from Kubernetes 1.23 to 1.24, in which a node label that their networking setup relied on had been renamed. Components that selected nodes by the old label no longer matched, and the network configuration broke. It is a perfect lesson in reading release notes closely, testing against production-like settings, and keeping a way back.

The Kubernetes project and the dockershim removal

The removal of dockershim in 1.24 was announced and discussed for a long time, with deprecation warnings and community guides on migrating to containerd and CRI-O. Teams that heeded the warning moved quietly, while teams that ignored it discovered the change on upgrade day. It shows how the deprecation policy rewards those who read the notices.

Google Kubernetes Engine: automation with guardrails

GKE gives teams release channels, automatic upgrades, maintenance windows and exclusions, and both surge and blue/green node pool upgrades. This is a good model of what a mature upgrade system looks like: automatic by default, controlled by policy, and easy to pause for important events.

Amazon EKS and Azure AKS: shared responsibility

Both services take over the control plane, and both leave the nodes and many add-ons in the customer’s hands. Their documentation stresses the same duties covered in this guide: check removed APIs, update add-ons, and roll node groups with controlled surge settings.

Cluster API users: upgrades as code reviews

Platform teams that run many clusters use Cluster API so that a version number change in a reviewed file triggers a rolling replacement of machines. The same pull request process that applies to application code now applies to infrastructure upgrades.

Realistic scenarios

The next stories are teaching illustrations. They are not descriptions of the internal systems of the companies named.

A streaming company before a big premiere

A video service like Netflix does not want a cluster change in the days before a major release. The platform team therefore keeps an upgrade calendar with freeze windows around big events, and runs its upgrades in quieter periods, one region at a time, with the first region acting as the canary.

An online marketplace with many clusters

A company like Amazon or Uber runs many clusters across regions. It upgrades a small internal cluster first, then a low-traffic region, then the rest in waves. Automated checks stop the rollout if error rates rise, so a single bad version never reaches every region.

A small team with one cluster

A startup with one production cluster on a managed service uses a staging cluster created from the same code. They upgrade staging on a Tuesday, let it run for a week, then upgrade production on the following Tuesday morning with the full team online. Simple, boring and effective.

Building an Upgrade Program

The goal is not to survive one upgrade. It is to make upgrades so routine that nobody dreads them.

A sample cadence

Let us imagine a team that follows a calm rhythm. The Kubernetes project releases a new minor version. The team waits a few weeks for early patches, since the first patch release often fixes early bugs, then begins its internal process.

W1

Week 1: Read and scan

Read the release notes, list removed APIs and breaking changes, run scanners against all manifests and Helm releases, and open tickets for each fix. Check every add-on for compatible versions.

W2

Week 2: Development cluster

Upgrade the development cluster using the same automation planned for production. Fix whatever breaks, and update the runbook.

W3

Week 3: Staging cluster and soak

Upgrade staging, which mirrors production. Run load tests and the full smoke suite, and let it run for several days to find slow problems.

W4

Week 4: Production in waves

Take an etcd snapshot, upgrade the control plane, then add-ons, then one canary node, then node batches. Keep an engineer watching dashboards, and keep the old node pool until the end of the day.

W5

Week 5: Review

Hold a short review. What went well, what was slow, what surprised us? Update the runbook and automation, and retire old resources.

Automation is the multiplier

Every step above should be turned into automation over time: scanning for deprecated APIs in pipelines, checking add-on versions, creating snapshots, rolling node pools, running smoke tests and posting progress to a team channel. Automation does not replace judgment, but it removes tedious mistakes and makes the process repeatable by anyone on the team, not just the one person who remembers the steps.

Everyday analogy

Airlines do not rely on a pilot’s memory for pre-flight safety. They use checklists, practiced until automatic. A mature upgrade program is a checklist with tooling around it: the process holds the knowledge, and people use their attention for the unusual parts.

Measure your program

Lag
How many minor versions behind latest your clusters are
Duration
Time from starting to finishing an upgrade
Incidents
Customer-visible problems caused by upgrades

Track these three numbers over time. If lag keeps growing, you need more time or automation. If duration is very long, find the slowest step. If incidents appear, review which part of your preparation missed them. Over a few cycles, all three should trend in the right direction.

i
Share ownership

Upgrades work best when platform teams own the cluster and application teams own their applications’ readiness. Give application teams clear dates and a checklist for their side, such as removing deprecated APIs, setting budgets and handling shutdown signals.

Frequently Asked Questions

Quick answers to the questions that come up most often.

Q1Can I skip a minor version, for example go from 1.29 to 1.31?

Not for the control plane in place. Upgrade one minor version at a time. If you want to leap further, a blue/green approach that builds a fresh cluster at the target version can do so, as long as your applications and data work with it.

Q2Will my applications go down during an upgrade?

Not if they are built for it. With a highly available control plane, multiple replicas, sensible disruption budgets and graceful shutdown, applications keep serving while nodes are drained and replaced. Single-replica applications will see a brief interruption.

Q3What happens to running pods when the control plane is being upgraded?

They keep running. The kubelet on each node continues to manage existing containers. What pauses is change: scheduling, scaling and replacing failed pods.

Q4Which should I upgrade first, the control plane or the nodes?

Always the control plane. Nodes must never run a newer kubelet than the API server.

Q5How long can nodes lag behind the control plane?

The skew policy allows kubelets to be several minor versions older than the API server, but it is best to upgrade nodes soon after the control plane. Check the current policy for the exact limit.

Q6Can I downgrade if the upgrade fails?

Not in the usual sense. Your recovery options are fixing forward, restoring from an etcd snapshot, rolling nodes or add-ons back, or moving traffic to an older cluster in a blue/green setup.

Q7How do I find deprecated API usage?

Use the API server’s deprecated request metrics and warnings, and scan manifests and Helm releases with tools such as Pluto or kube-no-trouble. Add schema validation to your pipelines.

Q8Do I need to upgrade add-ons?

Yes. Each add-on supports specific Kubernetes versions. Check the compatibility table for every one, and follow its upgrade guide for the proper order.

Q9Should I enable auto-upgrade on a managed service?

It is a good default for patch updates and for non-production clusters. For production, many teams use auto-upgrade with maintenance windows, an early-channel staging cluster, and the ability to pause around busy events.

Q10Is a blue/green cluster better than an in-place upgrade?

It is safer to roll back, but it costs more and needs your platform to be fully reproducible from code. Many teams use in-place or surge upgrades for most clusters and reserve blue/green for the most critical ones.

Q11How often should I upgrade?

A common rhythm is one minor upgrade per quarter or so, plus prompt patch upgrades. This keeps you well inside the support window without constant disruption.

Q12What is the single best thing I can do to make upgrades safer?

Practice them often on a realistic staging cluster, with automation and a written runbook. Familiarity removes most of the risk.

Summary and Key Takeaways

The shortest possible version of everything above.

A Kubernetes cluster upgrade is a carefully ordered replacement of many cooperating parts, performed while applications keep running. The rules are not mysterious: version numbers tell you the risk, the skew policy tells you the order, deprecation notices tell you what to fix first, and disruption budgets and graceful shutdown tell you whether your applications can survive the move. With backups, small steps, staged environments and good dashboards, even large upgrades become uneventful.

The best upgrade is the one so well rehearsed that nobody notices it happened.

Key Takeaways

  • Upgrade often and in small steps. Move one minor version at a time, on a regular cadence, to stay within the supported window and keep each change small.
  • Follow the order. Back up etcd, upgrade the control plane first, then add-ons, then nodes, because components must never be newer than the API server.
  • Hunt deprecated APIs early. Scan manifests, Helm releases and live clusters, and fix them while the old versions still work.
  • Make workloads upgrade-friendly. Use multiple replicas, sensible disruption budgets, accurate readiness checks, topology spread and graceful shutdown.
  • Choose the right node strategy. In-place, rolling with surge, or blue/green node pools each trade cost, speed and safety, and managed services or Cluster API can automate them.
  • Plan the way back before you begin. Downgrades are not generally supported, so rely on fresh snapshots, retained old node pools and practiced restores.
  • Validate and learn. Watch dashboards, run smoke tests, record what happened, and improve the runbook and automation after every upgrade.