Kubernetes Day 3: Deployments & ReplicaSets — Auto Healing Explained with Demo

☸️ Day 3 of 30 — Deployments & ReplicaSets

Kubernetes Day 3: Deployments & ReplicaSets

Deployment vs ReplicaSet vs Pod, Auto Healing, and a full hands-on demo

📅 March 2026  ·  ☸️ Kubernetes Preparation Series  ·  Day 3 of 30

#Kubernetes #KubernetesDeployment #ReplicaSet #AutoHealing #DevOps #CloudNative #CKAPrep #LearnK8s

1. Deployment vs ReplicaSet vs Pod — The Hierarchy

On Day 2 we learned that a Pod is the smallest deployable unit in Kubernetes. But in real production systems, you never create bare Pods. You create a Deployment, which creates a ReplicaSet, which creates and manages your Pods. These three objects form a hierarchy — each layer adds a responsibility the one below it cannot handle.

🚀 Deployment
Manages updates, rollbacks & history
↓ creates & owns
📦 ReplicaSet
Ensures N replicas are always running
↓ creates & owns
🟡 Pod (×3)
Runs your containers on a node
↓ contains
🐳 Container
Your actual application process

When you create a Deployment with replicas: 3, here is the exact chain of events:

  1. You apply the Deployment YAML → API Server stores it in etcd.
  2. The Deployment Controller sees the new Deployment → creates a ReplicaSet matching the Pod template.
  3. The ReplicaSet Controller sees it needs 3 Pods → creates 3 Pod objects.
  4. The Scheduler assigns each Pod to the best available node.
  5. The kubelet on each node pulls the image and starts the containers.
🔑 One Deployment, one ReplicaSet, many Pods. When you do a rolling update, the Deployment creates a second ReplicaSet with the new version and gradually scales it up while scaling the old one down. This is how zero-downtime updates work.

Side-by-side comparison

FeaturePodReplicaSetDeployment
PurposeRun containersKeep N Pods aliveManage RS + updates
Self-healing✗ None✓ Yes✓ Yes
Scaling✗ Manual only✓ Via replicas field✓ Via replicas field
Rolling updates✗ No✗ No✓ Yes
Rollback✗ No✗ No✓ Yes — full history
Update history✗ No✗ No✓ Revision tracking
Used directly?Debugging onlyRarely — prefer Deployment✓ Always in production
✅ Simple rule to remember: Pod = what runs. ReplicaSet = how many run. Deployment = how they change over time.

2. What is a ReplicaSet?

A ReplicaSet has one job and it does it obsessively: make sure the desired number of Pod replicas are always running. It watches the cluster continuously. If a Pod dies, it creates a new one. If there are too many Pods (say, you manually created an extra one with the same labels), it deletes the excess.

How a ReplicaSet identifies its Pods — the selector

A ReplicaSet does not track Pods by name. It uses a label selector. Any Pod in the cluster that matches the selector is considered "owned" by the ReplicaSet. This is powerful — and it is a common source of confusion for beginners.

⚠️ The label trap: If you manually create a Pod with the same labels as a ReplicaSet's selector, the ReplicaSet will immediately delete one of its existing Pods because it now sees too many matching Pods. Labels are ownership, not just metadata.

ReplicaSet YAML

 nginx-replicaset.yaml
apiVersion: apps/v1 # Note: apps/v1, not v1 kind: ReplicaSet metadata: name: nginx-rs spec: replicas: 3 # Keep 3 Pods running at all times selector: matchLabels: app: nginx # Own any Pod with this label template: # Blueprint for new Pods metadata: labels: app: nginx # MUST match selector above spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80

Why not use ReplicaSet directly?

You could — but you would lose the most important feature: rolling updates. When you change the image in a ReplicaSet, it does NOT automatically update running Pods. You have to delete and recreate them manually, which means downtime. A Deployment wraps the ReplicaSet and handles this for you automatically. That is why in practice, you always use Deployments.

💡 Quick check: Run kubectl get rs after creating a Deployment — you will see a ReplicaSet with an auto-generated name like nginx-deployment-7d4b8c9f6. The suffix is the hash of the Pod template, which is how Kubernetes tracks which RS belongs to which version of the Deployment.

3. What is a Deployment?

A Deployment is the standard way to run stateless applications in Kubernetes. It is a higher-level object that manages ReplicaSets on your behalf and adds three critical capabilities that ReplicaSets lack: rolling updates, rollbacks, and revision history.

Think of a Deployment as a contract with Kubernetes: "I want this application running at this image version, with this many replicas, updated this way." Kubernetes honours that contract continuously — not just at creation time, but forever.

Deployment YAML — the production standard

 nginx-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx strategy: # How to replace old Pods with new ones type: RollingUpdate # Default — zero downtime rollingUpdate: maxSurge: 1 # Max extra Pods above desired during update maxUnavailable: 0 # Never let replicas drop below desired revisionHistoryLimit: 5 # Keep last 5 ReplicaSets for rollback template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "100m" limits: memory: "128Mi" cpu: "250m" livenessProbe: # Is the app alive? httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 10 readinessProbe: # Is the app ready for traffic? httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5

Update strategies — RollingUpdate vs Recreate

✅ Recommended

RollingUpdate

Replaces old Pods with new ones gradually. At no point does your app go fully offline. Use maxSurge and maxUnavailable to control the pace. Default strategy — always use this for web apps.

⚠️ Use with caution

Recreate

Kills ALL old Pods first, then creates new ones. Causes downtime. Only use when your app cannot run two versions simultaneously — for example, apps that hold an exclusive DB lock.


4. Auto Healing — How Kubernetes Keeps Your App Alive

Auto healing is one of the most powerful features of Kubernetes and the main reason teams move from bare Docker to K8s for production. The idea is simple: you tell Kubernetes your desired state, and Kubernetes continuously works to maintain it — no matter what happens.

This is not magic. It is the reconciliation loop running inside the Controller Manager on the Control Plane, every few seconds, forever:

# The reconciliation loop (simplified): loop every few seconds: desired = read from etcd # e.g. replicas: 3 actual = count running Pods # e.g. 2 (one crashed) if actual < desired: create (desired - actual) new Pods elif actual > desired: delete (actual - desired) excess Pods else: nothing to do — all good ✅

What triggers auto healing?

Failure scenarioWhat Kubernetes doesTime to heal
Container process crashes (exit code ≠ 0)kubelet restarts the container on the same Pod immediatelySeconds
Liveness probe fails repeatedlykubelet kills and restarts the containerSeconds
Pod is manually deletedReplicaSet creates a replacement Pod5–10 seconds
Node goes offline / crashesNode Controller marks node NotReady → Pods rescheduled on healthy nodes~5 minutes
Pod evicted (node running low on memory)ReplicaSet creates replacement on another node10–30 seconds
Accidental kubectl delete deploymentNothing — Deployment is gone. Always use RBAC to prevent this!N/A

Auto healing in action — visualised

🔄 Auto Healing Sequence — nginx-deployment (replicas: 3)
1
Initial state — 3 Pods running
nginx-abc
Running ✅
nginx-def
Running ✅
nginx-ghi
Running ✅
2
nginx-def crashes — process exits with error
nginx-abc
Running ✅
nginx-def
Dead ❌
nginx-ghi
Running ✅
3
ReplicaSet detects: desired=3, actual=2 → creates new Pod
nginx-abc
Running ✅
nginx-ghi
Running ✅
nginx-xyz
Creating... 🔄
4
Healed — back to 3 running replicas. No human action needed.
nginx-abc
Running ✅
nginx-ghi
Running ✅
nginx-xyz
Running ✅
✅ This is the "no 3 AM pager alert" feature. A container crash used to mean an on-call engineer waking up at 3 AM to ssh into a server and restart a process. With Kubernetes auto healing, minor crashes heal automatically before any human even notices.

5. Rolling Updates and Rollbacks

Updating a running application without downtime is one of the hardest problems in operations. Kubernetes Deployments solve it with rolling updates — the most important daily operation you will perform.

How a rolling update works under the hood

Before update (v1)
nginx:1.25 — Pod 1 ✅
nginx:1.25 — Pod 2 ✅
nginx:1.25 — Pod 3 ✅
During update (v1 → v2)
nginx:1.25 — Pod 2 ✅
nginx:1.25 — Pod 3 ✅
nginx:1.26 — Pod 4 🔄

Kubernetes creates a new ReplicaSet for the new version, gradually increases its replica count, and decreases the old ReplicaSet's count — until the old RS has 0 Pods and the new RS has all 3. At every step, your app stays available.

Rolling update commands

# Update the image to a new version kubectl set image deployment/nginx-deployment nginx=nginx:1.26 # Watch the rollout happen in real time kubectl rollout status deployment/nginx-deployment Waiting for deployment "nginx-deployment" rollout to finish... 1 out of 3 new replicas have been updated... 2 out of 3 new replicas have been updated... 3 out of 3 new replicas have been updated... deployment "nginx-deployment" successfully rolled out # See rollout history — all revisions kubectl rollout history deployment/nginx-deployment REVISION CHANGE-CAUSE 1 <none> 2 <none> # Add a change cause note (best practice — helps you recall why each change was made) kubectl annotate deployment/nginx-deployment \ kubernetes.io/change-cause="Updated nginx to 1.26 for security patch"

Rollback — when things go wrong

# Something is broken — roll back to the previous version immediately kubectl rollout undo deployment/nginx-deployment deployment.apps/nginx-deployment rolled back # Roll back to a specific revision number kubectl rollout undo deployment/nginx-deployment --to-revision=1 # Pause a rollout (to inspect mid-way) kubectl rollout pause deployment/nginx-deployment # Resume it kubectl rollout resume deployment/nginx-deployment
🔑 Rollback is instant because Kubernetes kept the old ReplicaSet around (controlled by revisionHistoryLimit). It does not rebuild anything — it just scales the old RS back up and scales the new one down. This is why keeping your revision history is important.

6. Full Hands-on Demo — From Scratch to Auto Healing

Let us now put everything together in a real end-to-end demo. Make sure your Minikube cluster is running (minikube start) before you begin.

Step 1 — Create the Deployment YAML

Save this as nginx-deployment.yaml:

 nginx-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.25 ports: - containerPort: 80

Step 2 — Apply and observe

# Apply the Deployment kubectl apply -f nginx-deployment.yaml deployment.apps/nginx-deployment created # Watch Pods appear in real time (-w = watch mode) kubectl get pods -w NAME READY STATUS RESTARTS AGE nginx-deployment-7d4b8c9f6-2xkpq 0/1 ContainerCreating 0 2s nginx-deployment-7d4b8c9f6-9fvlm 0/1 ContainerCreating 0 2s nginx-deployment-7d4b8c9f6-rnbtp 0/1 ContainerCreating 0 2s nginx-deployment-7d4b8c9f6-2xkpq 1/1 Running 0 8s nginx-deployment-7d4b8c9f6-9fvlm 1/1 Running 0 9s nginx-deployment-7d4b8c9f6-rnbtp 1/1 Running 0 10s # See the Deployment status kubectl get deployment nginx-deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 30s # See the ReplicaSet that was auto-created kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-7d4b8c9f6 3 3 3 30s

Step 3 — Test auto healing (the fun part)

# Open a second terminal and watch Pods continuously kubectl get pods -w # In your first terminal — delete one Pod manually kubectl delete pod nginx-deployment-7d4b8c9f6-2xkpq # Watch what happens in terminal 2: nginx-deployment-7d4b8c9f6-2xkpq 1/1 Terminating 0 2m nginx-deployment-7d4b8c9f6-hj9kp 0/1 Pending 0 0s # ← NEW Pod! nginx-deployment-7d4b8c9f6-hj9kp 0/1 ContainerCreating 0 1s nginx-deployment-7d4b8c9f6-hj9kp 1/1 Running 0 6s # ← Healed ✅ # Still 3 Pods running — ReplicaSet replaced the deleted one kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-7d4b8c9f6-9fvlm 1/1 Running 0 3m nginx-deployment-7d4b8c9f6-rnbtp 1/1 Running 0 3m nginx-deployment-7d4b8c9f6-hj9kp 1/1 Running 0 15s

Step 4 — Scale up and down

# Scale up to 5 replicas kubectl scale deployment nginx-deployment --replicas=5 kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-7d4b8c9f6-9fvlm 1/1 Running 0 4m nginx-deployment-7d4b8c9f6-rnbtp 1/1 Running 0 4m nginx-deployment-7d4b8c9f6-hj9kp 1/1 Running 0 1m nginx-deployment-7d4b8c9f6-mn3pq 1/1 Running 0 5s # ← new nginx-deployment-7d4b8c9f6-qr7st 1/1 Running 0 5s # ← new # Scale back down to 2 kubectl scale deployment nginx-deployment --replicas=2 # Alternatively, edit the YAML and re-apply (preferred — keeps YAML as source of truth) kubectl apply -f nginx-deployment.yaml

Step 5 — Perform a rolling update

# Update image from nginx:1.25 to nginx:1.26 kubectl set image deployment/nginx-deployment nginx=nginx:1.26 # Watch the rolling update — old Pods terminate as new ones come up kubectl rollout status deployment/nginx-deployment Waiting for deployment "nginx-deployment" rollout to finish... 1 out of 3 new replicas have been updated... 2 out of 3 new replicas have been updated... 3 out of 3 new replicas have been updated... deployment "nginx-deployment" successfully rolled out # Simulate a bad deploy — use an image that does not exist kubectl set image deployment/nginx-deployment nginx=nginx:BROKEN kubectl rollout status deployment/nginx-deployment Waiting for deployment... (1/3 updated) error: deployment "nginx-deployment" exceeded its progress deadline # ROLLBACK immediately — back to nginx:1.26 kubectl rollout undo deployment/nginx-deployment deployment.apps/nginx-deployment rolled back # Verify all Pods are running the good version again kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}' nginx:1.26 nginx:1.26 nginx:1.26

Step 6 — Clean up

# Delete everything created in this demo kubectl delete -f nginx-deployment.yaml deployment.apps "nginx-deployment" deleted # Verify — no Pods should remain kubectl get pods No resources found in default namespace. # Stop Minikube when done for the day (saves laptop resources) minikube stop
✅ Always clean up with kubectl delete -f <file> rather than deleting individual Pods. Deleting the Deployment removes the ReplicaSet and all its Pods in one command — the right way to tear down a workload.

📌 Day 3 Recap — What You Learned

  • The hierarchy: Deployment → ReplicaSet → Pod → Container. Each layer adds a responsibility. Always use Deployments in production — never bare Pods or standalone ReplicaSets.
  • ReplicaSet: Watches the cluster and keeps your desired replica count running at all times using label selectors. Creates new Pods when existing ones die.
  • Deployment: Wraps a ReplicaSet and adds rolling updates, rollback capability, and revision history. The strategy field controls how updates happen — RollingUpdate (zero downtime) or Recreate (with downtime).
  • Auto healing: The reconciliation loop runs continuously. Crashed containers, deleted Pods, and evicted workloads are all replaced automatically without human intervention.
  • Rolling update: kubectl set image triggers a rolling update. New Pods replace old ones gradually — your app stays live throughout. kubectl rollout undo rolls back instantly.
  • Demo: You applied a Deployment, watched auto healing replace a deleted Pod in seconds, scaled replicas up and down, and performed a rolling update with rollback.
🚀 Day 4 preview: Your Pods are running and self-healing — but how do users reach them? Tomorrow we cover Kubernetes Services — ClusterIP, NodePort, and LoadBalancer — and how Kubernetes handles networking and service discovery between Pods.

Comments

Popular posts from this blog

Linux Commands Every DevOps Engineer Must Know (2026 Complete Guide)

Docker Day 1: Containers Explained — VM vs Docker, Lifecycle & Buildah

Kubernetes Day 7: ConfigMaps & Secrets — Managing Config the Right Way