Deployments, rolling updates and rollbacks

How a Deployment drives ReplicaSets, how to shape a rollout with maxSurge and maxUnavailable, and how to undo one that went wrong.

Workloads · 15%35 min2 tasks

After this lesson

  • 01You can create a Deployment imperatively, dump it to YAML and change its update strategy before applying it.
  • 02You can update an image, watch the rollout, read its history and roll back to a named revision.
  • 03You can recognize a stuck rollout from the Deployment's conditions and recover it in under two minutes.

Deployments appear in almost every CKA sitting, either directly (create, scale, update, roll back) or inside a troubleshooting task where a rollout has stalled. The commands are short. What costs people time is not knowing exactly which field the grader will read, so this lesson names the fields as it goes.

What a Deployment actually manages

A Deployment does not own Pods. It owns ReplicaSets, and each ReplicaSet owns Pods that match its selector. Every change to spec.template creates a new ReplicaSet with a new pod-template hash; the Deployment then scales the new set up and the old set down according to its strategy. Old ReplicaSets are kept (ten by default, spec.revisionHistoryLimit) and those are your rollback points.

Create one, then look at what it createdbash
kubectl create deployment web --image=nginx:1.27 --replicas=3
kubectl get deploy,rs,pods -l app=web
# The ReplicaSet name is <deployment>-<pod-template-hash>; the hash also lands on every Pod.

Changing something that is not in the template, such as spec.replicas, scales the current ReplicaSet in place and does not create a revision. That matters when a question says "roll back to the previous version": a scale-up is not a version.

Shaping the rollout

The default strategy is RollingUpdate with both knobs at 25%. maxSurge is how many extra Pods may exist above replicas during the update; maxUnavailable is how many may be missing. Both accept an absolute number or a percentage. Recreate kills every old Pod first and only then starts the new ones, which is the right answer when two versions must never run at the same time.

SettingMeaning during an updateTypical exam ask
maxSurge: 1, maxUnavailable: 0Always at full capacity; one extra Pod at a time"no downtime", "never fewer than N pods"
maxSurge: 0, maxUnavailable: 1Never above capacity; one Pod replaced at a time"the cluster has no spare resources"
maxSurge: 25%, maxUnavailable: 25%Defaults; rounds surge up and unavailable downLeft unspecified
type: RecreateAll old Pods stop before any new Pod starts"versions must not overlap"
A Deployment with an explicit strategyyaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: wl-rollout
spec:
  replicas: 3
  revisionHistoryLimit: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80

Driving a rollout

The commands you will actually typebash
# Change the image (container name is "nginx" when created with kubectl create deployment --image=nginx:…)
kubectl -n wl-rollout set image deploy/api nginx=nginx:1.26

# Block until the rollout finishes or fails. Always run this before moving to the next question.
kubectl -n wl-rollout rollout status deploy/api --timeout=120s

# Revisions, and the template of one revision
kubectl -n wl-rollout rollout history deploy/api
kubectl -n wl-rollout rollout history deploy/api --revision=2

# Undo to the previous revision, or to a specific one
kubectl -n wl-rollout rollout undo deploy/api
kubectl -n wl-rollout rollout undo deploy/api --to-revision=1

# Pause so several edits become one revision, then resume
kubectl -n wl-rollout rollout pause deploy/api
kubectl -n wl-rollout set resources deploy/api -c nginx --limits=cpu=200m
kubectl -n wl-rollout rollout resume deploy/api

# Scale (not a revision)
kubectl -n wl-rollout scale deploy/api --replicas=5

The CHANGE-CAUSE column in rollout history is just the annotation kubernetes.io/change-cause on the Deployment, copied onto the ReplicaSet at rollout time. The old --record flag no longer exists in current kubectl, so if a task wants a recorded cause, set it yourself: kubectl annotate deploy/api kubernetes.io/change-cause="image to 1.26" right after the change.

When a rollout gets stuck

A rollout that cannot make progress for spec.progressDeadlineSeconds (600 by default) flips the Progressing condition to False with reason ProgressDeadlineExceeded. Nothing is rolled back automatically; the Deployment simply waits. Read the conditions with kubectl describe deploy, find the new ReplicaSet's Pods, and the Pod events will usually name the cause: a typo in the image tag, a Secret that does not exist, a readiness probe that never passes, or no node with enough resources.

Diagnose, then decide: fix forward or undobash
kubectl -n wl-rollout describe deploy api | sed -n '/Conditions/,/OldReplicaSets/p'
kubectl -n wl-rollout get rs -l app=api
kubectl -n wl-rollout get pods -l app=api
kubectl -n wl-rollout describe pod <new-pod> | tail -20

# Undo is almost always the exam answer when the question says "the previous version worked".
kubectl -n wl-rollout rollout undo deploy/api
kubectl -n wl-rollout rollout status deploy/api --timeout=120s

In the docs · the tab you get on exam day

Taskwl-rollout-1
Workloads4%~6 min

context · kubectl config use-context kind-cka

Create a Deployment with a zero-downtime strategy

In namespace wl-rollout create a Deployment named api with 3 replicas using image nginx:1.27. The Deployment must use a RollingUpdate strategy that never reduces capacity below 3 Pods and adds at most one extra Pod during an update. Keep no more than 5 old ReplicaSets.
  1. 01

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-1/setup | bash
  2. 02

    Solve it in your terminal

    Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under /tmp/cka/.

  3. 03

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-1/verify | bash
    Counts toward your readiness score.
  4. 04

    Clean up

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-1/cleanup | bash
Taskwl-rollout-2
Workloads5%~6 min

context · kubectl config use-context kind-cka

Recover a stuck rollout and scale

The Deployment web in namespace wl-rollout was updated a few minutes ago and the new Pods are not starting. Roll the Deployment back to the last working version, then scale it to 4 replicas. All 4 Pods must be available when you are done.
  1. 01

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-2/setup | bash
  2. 02

    Solve it in your terminal

    Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under /tmp/cka/.

  3. 03

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-2/verify | bash
    Counts toward your readiness score.
  4. 04

    Clean up

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-2/cleanup | bash

Finished reading?

0 of 2 tasks passed. Readiness counts tasks, so run them before you move on.