13: Update Strategies

13: Update Strategies

Objective

Learn the two Deployment update strategies in Kubernetes — Recreate and RollingUpdate — and understand how to control the rollout behavior using maxSurge and maxUnavailable. Practice updating Deployments and using rollout commands.


Theory

Update Strategies

When you change the Pod template in a Deployment (e.g., update the container image), Kubernetes needs to replace the old Pods with new ones. The strategy field controls how this replacement happens.

Strategy Behavior Downtime
Recreate Terminates all existing Pods before creating new ones Yes — all Pods are down between termination and creation
RollingUpdate Gradually replaces old Pods with new ones No — traffic is served throughout the rollout (if configured correctly)

Recreate vs RollingUpdate

graph TB
    subgraph RecreateStrategy["Recreate Strategy"]
        direction TB
        R1["3 Pods v1 running"] --> R2["All 3 Pods v1 terminated"]
        R2 --> R3["DOWNTIME"]
        R3 --> R4["3 Pods v2 starting"]
        R4 --> R5["3 Pods v2 running"]
    end

    subgraph RollingStrategy["RollingUpdate Strategy"]
        direction TB
        U1["3 Pods v1 running"] --> U2["1 Pod v2 created<br/>3 Pods v1 still running"]
        U2 --> U3["1 Pod v1 terminated<br/>1 Pod v2 ready"]
        U3 --> U4["2nd Pod v2 created<br/>2 Pods v1 still running"]
        U4 --> U5["Continues until<br/>3 Pods v2 running"]
    end

    style R3 fill:#ffcdd2,stroke:#c62828,stroke-width:2px
    style U1 fill:#c8e6c9,stroke:#2e7d32,stroke-width:1px
    style U5 fill:#c8e6c9,stroke:#2e7d32,stroke-width:1px
    style R1 fill:#c8e6c9,stroke:#2e7d32,stroke-width:1px
    style R5 fill:#c8e6c9,stroke:#2e7d32,stroke-width:1px

maxSurge and maxUnavailable

For the RollingUpdate strategy, two parameters control the speed and safety of the rollout:

Parameter Description Default
maxSurge Maximum number of Pods that can be created above the desired replica count during the update 25%
maxUnavailable Maximum number of Pods that can be unavailable during the update 25%

Both values can be an absolute number or a percentage of the desired replicas.

maxSurge and maxUnavailable Examples

For a Deployment with 3 replicas:

maxSurge maxUnavailable Total Pods During Update Min Available Behavior
1 0 Up to 4 (3 + 1) 3 (all must be available) Safest — no Pod is removed until the new one is ready
0 1 Up to 3 2 (1 can be down) No extra capacity — removes 1 old Pod before creating a new one
1 1 Up to 4 2 Balanced — faster than the safest option
2 1 Up to 5 2 Fast — creates 2 extra Pods at once, allows 1 down
100% 0 Up to 6 (3 + 3) 3 Blue-green style — all new Pods created before old ones removed

When to Use Each Strategy

Use Case Recommended Strategy
Application cannot run multiple versions simultaneously Recreate
Database schema migrations that require exclusive access Recreate
Zero-downtime web services RollingUpdate (maxSurge=1, maxUnavailable=0)
Fast rollout where brief capacity reduction is acceptable RollingUpdate (maxSurge=2, maxUnavailable=1)

Practical Tasks

Task 1: Recreate Strategy

Deploy kuard v1 with 3 replicas using the Recreate strategy, then update to v2 and observe all Pods terminating before new ones start.

Create a file called deployment-recreate.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuard-recreate
  namespace: student-XX
  labels:
    app: kuard-recreate
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: kuard-recreate
  template:
    metadata:
      labels:
        app: kuard-recreate
    spec:
      containers:
        - name: kuard
          image: <ACR_NAME>.azurecr.io/kuard:1
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "100m"
              memory: "64Mi"

Deploy and wait for all 3 Pods to be running:

kubectl apply -f deployment-recreate.yaml
kubectl get pods -n student-XX -l app=kuard-recreate -w

Once all 3 Pods are running, open a second terminal and start watching:

kubectl get pods -n student-XX -l app=kuard-recreate -w

In the first terminal, update the image to kuard:2:

kubectl set image deployment/kuard-recreate kuard=<ACR_NAME>.azurecr.io/kuard:2 -n student-XX

In the watch terminal, observe the behavior:

NAME                              READY   STATUS        RESTARTS   AGE
kuard-recreate-6b8c9d7f6-abc12   1/1     Terminating   0          2m
kuard-recreate-6b8c9d7f6-def34   1/1     Terminating   0          2m
kuard-recreate-6b8c9d7f6-ghi56   1/1     Terminating   0          2m
kuard-recreate-6b8c9d7f6-abc12   0/1     Terminating   0          2m
kuard-recreate-6b8c9d7f6-def34   0/1     Terminating   0          2m
kuard-recreate-6b8c9d7f6-ghi56   0/1     Terminating   0          2m
kuard-recreate-8f4a2e1b3-jkl78   0/1     Pending       0          0s
kuard-recreate-8f4a2e1b3-mno90   0/1     Pending       0          0s
kuard-recreate-8f4a2e1b3-pqr12   0/1     Pending       0          0s
kuard-recreate-8f4a2e1b3-jkl78   1/1     Running       0          5s
kuard-recreate-8f4a2e1b3-mno90   1/1     Running       0          5s
kuard-recreate-8f4a2e1b3-pqr12   1/1     Running       0          5s

Notice that all old Pods are terminated before any new Pods are created. There is a period of complete downtime.


Task 2: Safe RollingUpdate (maxSurge=1, maxUnavailable=0)

Deploy kuard v2 with the safest rolling update configuration — no Pod is removed until the replacement is ready.

Create a file called deployment-rolling-safe.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuard-rolling-safe
  namespace: student-XX
  labels:
    app: kuard-rolling-safe
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: kuard-rolling-safe
  template:
    metadata:
      labels:
        app: kuard-rolling-safe
    spec:
      containers:
        - name: kuard
          image: <ACR_NAME>.azurecr.io/kuard:2
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "100m"
              memory: "64Mi"
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5

Deploy and wait for all 3 Pods to be running:

kubectl apply -f deployment-rolling-safe.yaml
kubectl rollout status deployment/kuard-rolling-safe -n student-XX

Start watching in a second terminal:

kubectl get pods -n student-XX -l app=kuard-rolling-safe -w

Trigger the rolling update by changing the image to kuard:3:

kubectl set image deployment/kuard-rolling-safe kuard=<ACR_NAME>.azurecr.io/kuard:3 -n student-XX

Observe the gradual replacement. With maxUnavailable: 0, you should always see at least 3 ready Pods during the rollout:

NAME                                  READY   STATUS              RESTARTS   AGE
kuard-rolling-safe-6b8c9d7f6-abc12    1/1     Running             0          2m
kuard-rolling-safe-6b8c9d7f6-def34    1/1     Running             0          2m
kuard-rolling-safe-6b8c9d7f6-ghi56    1/1     Running             0          2m
kuard-rolling-safe-8f4a2e1b3-jkl78    0/1     ContainerCreating   0          1s
kuard-rolling-safe-8f4a2e1b3-jkl78    1/1     Running             0          5s
kuard-rolling-safe-6b8c9d7f6-abc12    1/1     Terminating         0          2m

Check the rollout status:

kubectl rollout status deployment/kuard-rolling-safe -n student-XX
deployment "kuard-rolling-safe" successfully rolled out

Task 3: Fast RollingUpdate (maxSurge=2, maxUnavailable=1)

Deploy a faster rolling update configuration that trades some safety for speed.

Create a file called deployment-rolling-fast.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuard-rolling-fast
  namespace: student-XX
  labels:
    app: kuard-rolling-fast
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  selector:
    matchLabels:
      app: kuard-rolling-fast
  template:
    metadata:
      labels:
        app: kuard-rolling-fast
    spec:
      containers:
        - name: kuard
          image: <ACR_NAME>.azurecr.io/kuard:2
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "100m"
              memory: "64Mi"
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5

Deploy and wait for all Pods to be running:

kubectl apply -f deployment-rolling-fast.yaml
kubectl rollout status deployment/kuard-rolling-fast -n student-XX

Start watching and trigger the update:

kubectl get pods -n student-XX -l app=kuard-rolling-fast -w
kubectl set image deployment/kuard-rolling-fast kuard=<ACR_NAME>.azurecr.io/kuard:3 -n student-XX

With maxSurge: 2 and maxUnavailable: 1, you may see up to 5 Pods total (3 + 2) and as few as 2 available at once. The rollout completes faster because multiple Pods are replaced simultaneously.

Compare the rollout speed with the safe strategy from Task 2.


Clean Up

kubectl delete deployment kuard-recreate kuard-rolling-safe kuard-rolling-fast -n student-XX

Useful Commands

Command Description
kubectl rollout status deployment <name> -n student-XX Watch the progress of a rollout
kubectl rollout history deployment <name> -n student-XX View the revision history of a Deployment
kubectl rollout undo deployment <name> -n student-XX Roll back to the previous revision
kubectl rollout undo deployment <name> --to-revision=N -n student-XX Roll back to a specific revision
kubectl rollout pause deployment <name> -n student-XX Pause a rollout (useful for canary-style testing)
kubectl rollout resume deployment <name> -n student-XX Resume a paused rollout
kubectl set image deployment <name> <container>=<image> -n student-XX Update the image of a Deployment

Common Problems

Problem Possible Cause Solution
Rollout stuck, new Pods not becoming ready Readiness probe failing on new Pods Check logs and describe the new Pods; fix the issue or rollback
Old Pods not terminating maxUnavailable: 0 and new Pods never become ready Check readiness probe; the rollout waits for new Pods to be ready before removing old ones
All Pods down after update with Recreate Expected behavior for Recreate strategy Use RollingUpdate for zero-downtime deployments
kubectl rollout undo has no effect Only one revision in history Check kubectl rollout history — you need at least 2 revisions to undo
Rollout too slow Conservative maxSurge/maxUnavailable settings Increase maxSurge or maxUnavailable for faster rollouts

Best Practices

  1. Use RollingUpdate for production workloads — Recreate causes downtime and should only be used when the application cannot tolerate running multiple versions simultaneously.
  2. Start with maxSurge=1, maxUnavailable=0 — This is the safest configuration. Only relax these settings when you need faster rollouts and can tolerate brief capacity reduction.
  3. Always configure readiness probes — Without readiness probes, Kubernetes considers a Pod ready as soon as the container starts. This can route traffic to Pods that are not yet fully initialized.
  4. Record the cause of changes — Use kubectl apply -f with version-controlled YAML files so you have a history of changes in your source control.
  5. Test rollbacks — Regularly practice kubectl rollout undo so you are prepared for production incidents.
  6. Use kubectl rollout pause for canary testing — Pause a rollout after the first new Pod is ready, verify it works correctly, then resume.

Summary

In this exercise you learned:

  • The difference between Recreate (downtime) and RollingUpdate (zero-downtime) strategies
  • How maxSurge controls the number of extra Pods created during a rollout
  • How maxUnavailable controls the minimum number of available Pods during a rollout
  • How to observe rollout behavior in real time with kubectl get pods -w
  • How to use rollout commands: status, history, undo, pause, and resume
  • The trade-off between rollout safety (maxSurge=1, maxUnavailable=0) and speed (higher values)

results matching ""

    No results matching ""