Lesson 3 of 6

Deployments & ReplicaSets

A bare pod dies and stays dead. Production needs "keep three of these alive, always, and when I ship a new version, swap them out gradually with a way back." That's exactly what a Deployment is — and it's the object you'll actually write day to day.

💡 The Bottom Line

A Deployment declares "N replicas of this pod template." Under the hood it manages a ReplicaSet, whose only job is keeping exactly N matching pods alive. Change the template (a new image version) and the Deployment performs a rolling update — new ReplicaSet up, old one down, step by step — with one-command rollback.

The manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: myapp:1.0
          ports:
            - containerPort: 3000

Notice the structure: everything under template: is just a pod manifest (compare Lesson 2), embedded inside the Deployment. The selector tells the Deployment which pods are "its" pods — it must match the template's labels. Labels doing real work, as promised.

Self-healing, demonstrated

kubectl apply -f deployment.yaml
kubectl get pods            # three pods, names like web-7f9b...-x2k4p
kubectl delete pod web-7f9b...-x2k4p
kubectl get pods            # ...and there are three again, one brand new

You didn't restart anything — the ReplicaSet noticed actual (2) ≠ desired (3) and fixed it. This is the reconciliation loop from Lesson 1, now working for you.

Rolling updates and rollbacks

Edit the manifest's image to myapp:1.1 and re-apply — or imperatively:

kubectl set image deployment/web web=myapp:1.1
kubectl rollout status deployment/web   # watch it happen
kubectl rollout history deployment/web
kubectl rollout undo deployment/web     # bad release? one command back

The rollout replaces pods gradually — by default keeping the app available the whole time (a few old pods keep serving until enough new ones are ready). A failed new version doesn't take the site down, and undo returns to the previous ReplicaSet, which was never deleted — just scaled to zero.

🙋 There Are No Dumb Questions

Q: Do I ever write a ReplicaSet myself?
A: Practically never. The Deployment creates and manages ReplicaSets for you — one per version of your pod template — and uses them to orchestrate rollouts. You'll see them in kubectl get rs output (that's where the hash in pod names comes from), but you write Deployments. Same relationship as images and containers: one is the thing you author, the other is machinery.

⚠️ Watch Out

A rolling update only helps if Kubernetes can tell a new pod is actually ready. Without a readiness probe (a URL Kubernetes polls, e.g. readinessProbe: httpGet: path: /healthz), a pod counts as ready the moment its process starts — even if the app inside takes 20 more seconds to boot, meaning traffic hits pods that can't answer yet. Add readiness probes to anything user-facing; it's the single highest-value line in a production manifest.

🔧 Try It Yourself

Use a public image so there's nothing to build: set the image to nginx:1.26 in the manifest above, apply it, then roll it forward and back:

kubectl set image deployment/web web=nginx:1.27
kubectl rollout status deployment/web
kubectl get rs                     # two ReplicaSets: new scaled up, old at 0
kubectl rollout undo deployment/web

Watch kubectl get pods -w in a second terminal during the rollout — you'll see the old pods terminate one by one as new ones become ready.

✅ Quick Check

You delete one of a Deployment's three pods. What happens?


Next up: your pods are alive and healing — but their IPs change with every replacement. Services give that moving crowd one stable address.

← Back to
Next →