ReplicaSets and Deployments
Topic 06

ReplicaSets and Deployments

ControllerRollout

A Deployment is the object you actually use to run a stateless application. You give it a Pod template and a replica count, and it keeps exactly that many Pods running, replaces the ones that fail, and rolls out new versions without downtime.

Underneath, a Deployment manages ReplicaSets, and a ReplicaSet manages Pods. You rarely touch the ReplicaSet directly — but knowing the layering explains how rolling updates and rollbacks work.

ReplicaSet: Keeping N Pods Alive

What a Deployment manages
Deployment
web · rolling update & rollback
ReplicaSet
web-v2 · keeps 3 Pods
the previous ReplicaSet is kept at 0 replicas for instant rollback
Pods
web-v2-a   web-v2-b   web-v2-c

A ReplicaSet has one job: ensure a specified number of Pods matching a label selector are running. If a Pod dies, it creates a replacement; if there are too many, it deletes some. That is the reconcile loop applied to replica count. On its own a ReplicaSet has no concept of versions or updates — change the Pod template and it will not re-roll existing Pods.

That gap is why you almost never create a ReplicaSet directly. The Deployment sits on top and adds the update machinery.

Deployment: Updates and Rollback

A Deployment manages ReplicaSets over time. When you change the Pod template — a new image, say — the Deployment creates a new ReplicaSet and gradually shifts replicas from the old one to the new one. The old ReplicaSet is kept (scaled to zero) so you can roll back to it instantly. This is how kubectl rollout undo works: it just scales a previous ReplicaSet back up.

A Deployment with a rolling-update strategy
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # at most 1 extra Pod during the roll
      maxUnavailable: 0     # never drop below the desired count
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: my-web-app:2.0

Rolling Update Strategy

The RollingUpdate strategy is controlled by two knobs. maxSurge is how many extra Pods may exist above the desired count during the roll; maxUnavailable is how many may be missing below it. Setting maxUnavailable: 0 with maxSurge: 1 means the new Pod must be ready before an old one is removed — zero-downtime, slightly slower. The alternative strategy, Recreate, kills all old Pods before starting new ones; it causes downtime and is only for apps that cannot run two versions at once.

A rolling update is only as safe as the readiness probe. Without one, Kubernetes considers a Pod available the moment its container starts, and will happily route traffic to a process that has not finished booting — turning a deploy into an outage. Readiness probes are Topic 29.

Scaling

Scaling a Deployment is changing one number: replicas. Do it declaratively in the manifest, or imperatively with kubectl scale for a quick change. For automatic scaling on load, a HorizontalPodAutoscaler adjusts replicas for you based on metrics (Topic 27) — in which case you should not also pin replicas in your manifest, or the two will fight.

Deployment vs StatefulSet vs DaemonSet

Deployment — interchangeable, stateless replicas; any Pod is as good as any other. The default for web and API services.

StatefulSet — Pods with stable identity and their own storage; for databases and clustered systems (Topic 14).

DaemonSet — one Pod per node; for node-level agents (Topic 13).

Common Mistakes
  • Editing or creating ReplicaSets directly instead of letting the Deployment manage them.
  • Rolling out without a readiness probe, so traffic hits Pods that are not ready and the update looks fine while it breaks.
  • Using a mutable tag like latest, which makes rollback meaningless — both ReplicaSets resolve to whatever the tag points at now.
  • Setting maxUnavailable too high and dropping capacity below what the load needs mid-roll.
  • Pinning replicas in the manifest while an HPA also manages it, causing the two to fight on every apply.
Best Practices
  • Manage stateless workloads with Deployments; reserve ReplicaSets as an implementation detail you don't touch.
  • Always define a readiness probe so rolling updates actually wait for Pods to be ready.
  • Pin images by tag-plus-digest so a rollback returns to the exact bytes that worked.
  • Use maxUnavailable: 0 with a small maxSurge for zero-downtime rolls of capacity-sensitive services.
  • When an HPA owns the replica count, omit replicas from the manifest to avoid conflicts.
RelatedStatefulSet / DaemonSet — sibling workload controllers for different shapesHorizontalPodAutoscaler — drives the replica count automatically (Topic 27)Managed rolling deploys — ECS services, Cloud Run revisions as cloud analogs

Knowledge Check

How does a Deployment make rollback to a previous version instant?

  • It keeps the old ReplicaSet scaled to zero and simply scales it back up on undo
  • It stores a local backup of every prior container image on each node's disk
  • It re-pulls the previous image fresh from the registry on demand for every rollback
  • It takes a full snapshot of etcd before applying every spec change

What does maxUnavailable: 0 with maxSurge: 1 achieve during a rolling update?

  • A new Pod must become ready before an old one is removed — zero-downtime
  • All old Pods are torn down and replaced simultaneously for maximum speed
  • The rollout is blocked at each step until an operator manually approves it
  • Only one Pod total runs at any moment for the whole update

Why does using the latest image tag undermine rollback?

  • Both old and new ReplicaSets resolve latest to whatever it points at now, so there is no distinct prior version to return to
  • An image tagged latest cannot be pulled by the kubelet at all, so the rolled-back ReplicaSet can never start its replacement Pods
  • Performing a rollback permanently deletes any image tagged latest from the registry
  • Using the latest tag silently disables the readiness probe on every Pod

You got correct