How Rolling Updates Actually Work
Summary
- A rolling update replaces old Pods with new ones incrementally by creating a second ReplicaSet and shifting replicas from old to new, so the app stays available throughout.
- Insight: the Deployment never edits a running Pod. It changes the balance of two ReplicaSets, and readiness gates each step.
- Key Concepts: the new/old ReplicaSet swap, readiness gating, and the maxSurge / maxUnavailable window.
- When to Use: the default for any stateless service where brief coexistence of two versions is acceptable.
- Limitations/Trade-offs: two versions run at once mid-rollout, so your app and its schema must tolerate version skew.
- Related Topics: rolling update parameters, rollback, and blue/green and canary strategies.
Foundations
When you change a Deployment's Pod template, Kubernetes does not mutate existing Pods.
Instead the Deployment controller creates a new ReplicaSet whose template hash differs from the old one.
Each ReplicaSet is identified by a hash of its Pod template, stored in the pod-template-hash label.
The rollout is the process of scaling the new ReplicaSet up while scaling the old ReplicaSet down.
At the start you have old ReplicaSet at N, new at 0. At the end you have new at N, old at 0.
The old ReplicaSet is not deleted. It lingers at zero replicas so you can roll back to it instantly.
Mechanics & Interactions
The controller moves in small, bounded steps governed by two knobs on spec.strategy.rollingUpdate.
maxSurge is how many Pods above the desired count may exist during the rollout.
maxUnavailable is how many Pods below the desired count may be unavailable during the rollout.
Both accept an absolute number or a percentage, and both default to 25%.
Here is the strategy block that most Deployments carry, explicitly or by default.
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%With replicas: 4 and 25% each, maxSurge rounds up to 1 and maxUnavailable rounds down to 1.
That means the controller may run up to 5 Pods total and must keep at least 3 available at any moment.
A single step looks like this. The controller scales the new ReplicaSet up by the surge allowance, waits for those Pods to become ready, then scales the old ReplicaSet down.
The crucial word is ready. A new Pod counts toward availability only after it passes its readiness probe.
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5Without a readiness probe, Kubernetes treats a Pod as available the moment its container starts, which lets a rollout race ahead of an app that is not actually serving yet.
This is why a missing readiness probe is the single most common cause of a rollout that "worked" but dropped traffic.
The controller repeats the surge-wait-retire step until the new ReplicaSet holds all N replicas and the old one holds zero.
Because the observed availability is checked every step, a rollout that cannot make new Pods ready simply stalls rather than tearing down the healthy old version.
Advanced Considerations & Applications
The surge/unavailable math sets your worst-case capacity.
During the rollout, guaranteed available Pods equal replicas - maxUnavailable, and peak Pods equal replicas + maxSurge.
If you set maxUnavailable: 0, the rollout never dips below full capacity but requires surge headroom and cluster room to schedule extra Pods.
If you set maxSurge: 0, no extra Pods are created, so the rollout must remove old Pods before adding new ones, dipping below full capacity.
You cannot set both to zero; the controller would have no room to make progress and the API rejects it.
progressDeadlineSeconds bounds a stuck rollout.
spec:
progressDeadlineSeconds: 600
minReadySeconds: 10If no progress happens within the deadline, the Deployment is marked Progressing=False with reason ProgressDeadlineExceeded, which your CI or GitOps controller can detect and act on.
minReadySeconds makes a Pod prove it stays healthy for a grace window before it counts as available, which smooths out Pods that pass readiness then immediately crash.
Version skew is real during every rollout. For the duration, both the old and new image serve live traffic behind the same Service.
Your rollout is only safe if both versions can coexist: backward-compatible API contracts, additive database migrations, and no removal of a field the old version still reads.
Connection draining depends on the preStop hook and termination grace. When an old Pod is retired, it receives SIGTERM and is removed from Service endpoints, but in-flight requests need a preStop sleep or graceful shutdown to finish cleanly.
Common Misconceptions
"A rolling update edits my Pods in place." It never does. It creates a new ReplicaSet and shifts replica counts between two ReplicaSets.
"Both versions never run at the same time." They always do, briefly. Managing that overlap safely is the core discipline of rolling updates.
"maxSurge and maxUnavailable are percentages of remaining Pods." They are computed against the desired replica count, with surge rounded up and unavailable rounded down.
"A rollout with no readiness probe is fine." Without it, Pods count as available on container start, so traffic can hit a Pod before it can serve.
"A failed rollout rolls back automatically." It does not. It stalls and reports ProgressDeadlineExceeded; you or your tooling must run the rollback.
FAQs
Where does the old version go after a rollout?
Its ReplicaSet is scaled to zero and kept for history, capped by revisionHistoryLimit, so you can roll back to it.
Why is my rollout stuck at a partial state? New Pods are not becoming ready. Check the readiness probe, image pull, and resource requests against available node capacity.
Does scaling a Deployment create a new revision? No. Only changes to the Pod template create a new ReplicaSet and revision; scaling adjusts the current ReplicaSet.
How do I make a rollout zero-downtime?
Set a real readiness probe, maxUnavailable: 0 with surge headroom, and a preStop hook plus adequate termination grace for draining.
What triggers a rollout?
Any change to spec.template, including image, env, labels, or resource fields. Changing only spec.replicas does not.
Related
- Rolling Update Parameters
- Rollback
- Blue/Green & Canary
- How Kubernetes Keeps N Copies Running
- Deployments Best Practices
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).