Deployments, rolling updates and rollbacks

How a Deployment runs your Pods through ReplicaSets, how to control a rolling update, and how to undo one that went wrong.

35 min 2 hands-on tasksWorkloads · 15% of the exam

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Create a Deployment with one command, save it as YAML, and change its update strategy before you apply it.
  • Change an image, watch the rollout, read its history and roll back to a chosen revision.
  • Spot a stuck rollout from the Deployment's conditions and fix it in under two minutes.

A keeps a set number of copies of your app running, and lets you update them without downtime. Say you run a Django app as 3 . To ship version 2, you change the image, and the Deployment swaps the Pods a few at a time.

Deployments show up in almost every CKA exam. Sometimes the task is direct: create, scale, update, roll back. Sometimes it is a troubleshooting task where an update got stuck. The commands are short. What costs time is not knowing which field the grader reads, so this lesson names those fields as it goes.

What a Deployment actually manages

A Deployment does not manage Pods directly. It works through a middle layer, the . A ReplicaSet keeps an exact number of identical Pods running.

Deployment, ReplicaSets and Pods

Deployment

what you create and edit

ReplicaSets

one per version

Version 2

current: 3 Pods

Version 1

old: 0 Pods, kept for rollback

Pods

3 running copies of version 2

You create and edit the Deployment. It creates one ReplicaSet per version of the Pod template, and each ReplicaSet runs the Pods.

  • Every change to the Pod template (spec.template), such as a new image, creates a new ReplicaSet.
  • The Deployment then scales the new ReplicaSet up and the old one down, following its strategy.
  • Old ReplicaSets are kept, scaled to zero. They are your rollback points. A Deployment keeps 10 by default, and spec.revisionHistoryLimit changes that number.
Create one, then look at what it created
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 outside the template, such as spec.replicas, does not create a new ReplicaSet. The current one just grows or shrinks, and no new revision is made. This matters when a task says "roll back to the previous version": scaling up is not a version.

Shaping the rollout

A rolling update replaces old Pods with new ones a few at a time, so the app keeps serving. It is the default strategy, RollingUpdate. Two settings control its pace:

  • maxSurge: how many extra Pods may exist above replicas during the update.
  • maxUnavailable: how many Pods may be missing below replicas during the update.

Both take a number or a percentage, and both default to 25%. Example: with 4 replicas, maxSurge: 1 and maxUnavailable: 0, you never have fewer than 4 ready Pods and never more than 5 Pods in total.

The other strategy is Recreate. It stops every old Pod first, and only then starts the new ones. Use it when two versions must never run at the same time, for example an app whose old and new versions cannot share one database.

SettingWhat happens during an updateTypical exam wording
maxSurge: 1, maxUnavailable: 0Always at full size. One extra Pod is added at a time"no downtime", "never fewer than N Pods"
maxSurge: 0, maxUnavailable: 1Never above full size. One Pod is replaced at a time"the cluster has no spare resources"
maxSurge: 25%, maxUnavailable: 25%The defaults. Surge rounds up, unavailable rounds downNothing said about the strategy
type: RecreateAll old Pods stop before any new Pod starts"versions must not overlap"
Rolling update, step by step4 replicas, image v1 → v2.

ReplicaSet web-v1old image

v1ready
v1ready
v1ready
v1ready

ReplicaSet web-v2new image

no Pods
Available 4 · minimum 3Total 4 · maximum 5
4 replicas run v1. You change the image, so the Deployment creates a new ReplicaSet for v2. Press Step or Play.
maxSurgemaxUnavailable
A Deployment with an explicit strategy
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

These are the commands you will use most. Each one names the Deployment as deploy/api: the type, a slash, then the name.

The commands you will actually type
# 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 image deploy/api nginx=nginx:1.27
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 comes from the annotation kubernetes.io/change-cause on the Deployment. If a task wants a cause recorded, set it yourself right after the change: kubectl annotate deploy/api kubernetes.io/change-cause="image to 1.26".

When a rollout gets stuck

A is stuck when the new Pods never become ready. The usual causes are a wrong image tag, a missing , a that never passes, or no with room.

Kubernetes does not roll back by itself. It waits for spec.progressDeadlineSeconds (600 seconds by default). Then it sets the Progressing condition to False, with reason ProgressDeadlineExceeded, and keeps waiting.

  1. 1.Read the Deployment's conditions with kubectl describe deploy.
  2. 2.Find the new ReplicaSet and its Pods.
  3. 3.Read those Pods' events. They usually name the cause.
  4. 4.Decide: fix the problem, or undo to the version that worked.
Diagnose, then decide: fix forward or undo
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 official docs· open on exam day too

Hands-on task 1 of 2wl-rollout-1
~6 min4% weightWorkloads

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.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

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

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-1/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-1/cleanup | bash
Hands-on task 2 of 2wl-rollout-2
~6 min5% weightWorkloads

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.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

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

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-rollout-2/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

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

Finished this lesson?

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