Small batches are the whole trick: a wave stops an old pod only after the replacement is already healthy. Instead of flipping the entire fleet at once — the all-or-nothing gamble of a recreate deployment — the controller keeps most of the old version serving while it proves the new one, pod by pod. A bad image then stalls the rollout with the old version still up, rather than replacing a working fleet with a broken one in seconds.
The pace of those waves is set by two numbers, and understanding them is the difference between deploys that feel boring and deploys that feel brave. Deliberate values come from knowing your headroom, not from copying defaults.
The surge and the gap
maxSurge reserves room for extra pods during the roll, while maxUnavailable sets how many old ones the controller may stop at once. With ten replicas, maxSurge 2 and maxUnavailable 1, the fleet breathes between eleven and nine pods: at most two replacements boot early, at most one old pod is missing at any moment. Pick the pair to trade speed against peak capacity — higher numbers finish faster but demand more cluster headroom and tolerate a bigger hole if the new version misbehaves.
Surge overspends resources: set it high on a tight cluster and replacement pods sit Pending for lack of room, stalling the roll on capacity rather than health. Unavailable overspends risk: set it high and half the fleet can be down simultaneously, so a bad image plus an unlucky timing takes the service with it.
Health gates the switch
A replacement reaches the ready state only after its readiness check is green, so the controller waits between waves. A readiness probe that actually exercises the app — an HTTP endpoint that checks database connectivity, not just a TCP open on the port — is what stands between a broken release and your users.
A failing new pod stalls the rollout rather than replacing healthy traffic, and that stall is a signal, not a nuisance. The deployment freezes with old pods still serving, giving you time to inspect logs, fix the image, and resume — or roll back with a single command.
Choose a deliberate strategy
Raise maxSurge and maxUnavailable to roll faster, or lower them to shrink the blast radius. A common production shape is maxSurge at one and maxUnavailable at zero for small fleets — always full capacity, one extra pod at a time — and percentages like 25 percent for large ones, so the wave size scales with the fleet. There is no universal right answer, only the answer that matches your headroom and your error budget.
A manual strategy leaves the deployment paused at a halfway point for canary checks before you continue. Pause after the first wave, run smoke tests and watch error rates against the new pods specifically, then resume when the numbers agree — or abort while the blast radius is still one pod. This pause-and-verify pattern gives most of canary deployment’s safety with none of its extra machinery, and it works with plain Deployments on any cluster.
When it breaks
The signature failure is the rollout that never finishes: new pods CrashLoop, the deployment sits at half-old half-new for an hour, and nobody notices because the service technically still answers. Causes cluster into three buckets — image problems (wrong tag, missing env), probe problems (probe stricter than reality), and capacity problems (surge pods unschedulable). kubectl rollout status plus pod events distinguishes them in under a minute, and the fix matches the bucket: fix the image, relax the probe, or free capacity.
The sneakier failure is the rollout that finishes too well: every pod replaced, and then the new version’s slow memory leak or connection exhaustion surfaces under full traffic. Rolling updates validate startup, not soak. For risky releases, follow the rollout with a bake period on dashboards — error rate, p99, restarts — before calling it done, and keep the previous ReplicaSet available until the bake passes.
Check it quickly
Watch a rollout the way the controller sees it:
kubectl rollout status deployment/api --timeout=120s
kubectl get pods -l app=api -w
kubectl describe deployment api | grep -E "Strategy|Max (Surge|Unavailable)"
The first blocks until the waves finish or fail, the watch shows old and new pods trading places, and the last confirms the strategy values actually in effect.
Sources
- Kubernetes Deployment controllers, Official doc covering maxSurge and maxUnavailable in rolling updates, checked 2026-06-01.
- Kubernetes updating a Deployment, documents rollout behavior and rollback, checked 2026-09-05.