KubernetesXVI · Deployment StrategiesDeployment strategies
Rolling Update — maxSurge, maxUnavailable, and the math of a safe rollout
What you'll learn
- Describe how RollingUpdate replaces Pods in a Deployment with a new template
- Reason about maxSurge and maxUnavailable as integer or percentage values, and the trade-off they encode
- Calculate the worst-case Pod count during a rollout for a given replica count and burst settings
- Identify the failure modes that turn a rolling update into an outage (failed readiness, image pull, shared dependencies)
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
RollingUpdate is the default Deployment strategy and the one you
will use most often. It replaces Pods in batches — scaling the old
ReplicaSet down and the new ReplicaSet up at the same time — while
the Service slowly shifts traffic to the new Pods as they pass
readiness. The strategy is safe by default but not free; it
requires spare cluster capacity and a readiness probe the
application actually answers.
What the strategy does
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 0
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27.2
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
When you change the Pod template (image, env, resources), the Deployment controller creates a new ReplicaSet and walks the old and new in parallel:
- Scale up the new ReplicaSet by
maxSurge(or untilmaxUnavailableold Pods are missing). - Wait for the new Pods to pass readiness.
- Scale down the old ReplicaSet by the number of new Pods now Ready.
- Repeat until the old ReplicaSet has zero replicas.
- Record the rollout in the Deployment’s
status.
flowchart LR
A["Old ReplicaSet<br/>6 ready"] -->|step 1| B["Old: 4 ready<br/>New: 2 surge"]
B -->|readiness| C["Old: 4 ready<br/>New: 2 ready"]
C -->|step 2| D["Old: 2 ready<br/>New: 4 ready"]
D -->|readiness| E["Old: 2 ready<br/>New: 4 ready"]
E -->|step 3| F["Old: 0 ready<br/>New: 6 ready"]
maxSurge and maxUnavailable
Two knobs control the rollout. They are independent and each
takes an integer or a percentage of replicas.
| Field | Meaning | Default |
|---|---|---|
maxSurge | Maximum Pods above the desired count the rollout is allowed to create | 25% |
maxUnavailable | Maximum Pods below the desired count the rollout is allowed to remove | 25% |
Constraints the API server enforces:
- At least one of
maxSurgeormaxUnavailablemust be non-zero. - A value of
0for one of them is allowed and means “do not violate that side” of the budget.
The trade-off
| Configuration | Spare capacity needed | Tolerable downtime per batch |
|---|---|---|
maxSurge: 0, maxUnavailable: 1 | None (0 surge) | 1 old Pod missing |
maxSurge: 1, maxUnavailable: 0 | 1 extra Pod | 0 missing |
maxSurge: 25%, maxUnavailable: 0 (defaults on large Deployments) | 25% extra Pods | 0 missing |
maxSurge: 25%, maxUnavailable: 25% (legacy default) | Up to 25% extra | Up to 25% missing |
maxUnavailable: 0 is the safest setting for capacity-tight
workloads because no old Pod is removed until a new Pod is Ready.
It costs maxSurge extra Pods of headroom.
flowchart TB
subgraph "maxSurge: 2, maxUnavailable: 0"
S1["Old RS: 6 of 6"] -->|create 2 new| S2["Old RS: 6 of 6<br/>New RS: 0 of 2"]
S2 -->|wait readiness| S3["Old RS: 6 of 6<br/>New RS: 2 of 2 ready"]
S3 -->|drain 2 old| S4["Old RS: 4 of 6<br/>New RS: 2 of 2"]
end
The math of a rollout
For a Deployment with replicas: R and burst settings
maxSurge: S and maxUnavailable: U:
- Peak live Pod count:
R + S - Worst-case missing Pod count:
R - U(only if readiness on the new side lags)
The Deployment controller rounds S and U per step based on
R. A maxSurge: 25% Deployment with replicas: 5 allows 1.25
extra Pods, which the controller rounds to 1 (or 2, depending on
the implementation).
A rollout that does not converge past the same step for more
than progressDeadlineSeconds (default 600) is marked
ProgressDeadlineExceeded. The Deployment is not rolled back
automatically; the operator must intervene.
kubectl rollout status deployment/web -n prod
# error: error timed out waiting for the condition
kubectl describe deployment web -n prod | sed -n '/Conditions/,/Events/p'
Readiness is the gate
The RollingUpdate is only as safe as the readiness probe. The controller only counts a Pod as “new and Ready” once the readiness probe has passed. If readiness never passes:
- The new ReplicaSet never reaches
maxSurgeold Pods worth of replacements. - The old ReplicaSet is not scaled down.
- The rollout stalls until
progressDeadlineSecondsand the Deployment becomes unhealthy.
Capacity and HPA interactions
A RollingUpdate assumes the cluster has maxSurge worth of
extra capacity above the steady state. With maxSurge: 25%,
rolling out a 100-replica Deployment briefly needs 125 Pods
scheduled. On a cluster running at 95% utilisation, those 25
extra Pods may not fit. The rollout will not fail outright — it
will throttle. The new Pods sit Pending until old Pods free
capacity.
Common production settings
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
This is the standard “no-downtime” setting when capacity is modest. It allows 1 extra Pod and never removes an old Pod until a new one is Ready.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
Legacy default; only used when the new template is known-safe and the cluster can absorb a temporary drop. Faster rollouts, riskier rollbacks.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
Used when the cluster cannot accept any surge (e.g., the Deployment runs on a node with no spare capacity). It does a small-batch rollout with no extra Pods. Will incur brief in-under-capacity periods.
Inspecting a rollout
$ kubectl rollout status deployment/web -n proddeployment "web" successfully rolled out$ kubectl rollout history deployment/web -n proddeployment.apps/web
REVISION CHANGE-CAUSE
1 Initial deploy
2 Image bump to nginx:1.27.2
3 Resource limits tune$ kubectl get replicasets -l app=web -n prod -o wideNAME DESIRED CURRENT READY AGE
web-7c8d9b1f8 6 6 6 2d
web-6b3d5a7e9 0 0 0 45mThe old ReplicaSet stays around with 0 replicas so that
kubectl rollout undo can resurrect it instantly without
re-pulling the image.
Quiz
Knowledge check · 4 questions
Q1. A Deployment has `replicas: 6` with `maxSurge: 2` and `maxUnavailable: 0`. What is the maximum number of Pods that can exist at any moment during a rollout?
Q2. A Deployment rollout stalls when new Pods never become Ready; the Deployment controller will automatically roll back to the previous ReplicaSet when `progressDeadlineSeconds` is exceeded.
Q3. Your team changed a Deployment's image to a new version. The rollout is in progress; old Pods are being replaced. 5 minutes in, the new Pods are Running but never Ready. What happens and how do you recover?
Deployment web with replicas 6, maxSurge 1, maxUnavailable 0. New image has a broken readiness probe returning 500. After 10 minutes the rollout is stuck.
Q4. Name the two burst settings that control a RollingUpdate and explain the trade-off they encode.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Always set explicit
maxSurgeandmaxUnavailable. Production rollouts should not rely on a 25%/25% legacy default. - A readiness probe that matches the production liveness
criterion is mandatory.
tcpSocket: portonly is not sufficient — it does not detect a process that accepts connections but cannot serve traffic. - Set
progressDeadlineSecondslower than the alerting threshold so the Deployment fails-fast and pages on-call. - Pre-pull the new image onto the nodes (
DaemonSetwith the image, ornode-pullinit scripts) so image-pull latency does not become the rollout bottleneck. - Treat every
kubectl rollout undoas a code change in reverse. Test it in staging with the same surge settings.
The RollingUpdate strategy is the workhorse of every Kubernetes Deployments course and of most production rollouts. Its safety properties are entirely determined by the readiness probe, the burst budget, and the cluster’s capacity headroom. None of these are Kubernetes’ job to verify — they are the operator’s.