TL;DR (Quick Summary)#
- Hierarchy:
DeploymentcontrolsReplicaSet, which controlsPods. - Self-Healing: If a Pod crashes, is killed, or its host node dies, the ReplicaSet controller detects the drift and immediately launches a replacement Pod.
- Horizontal Scaling: Scale application capacity effortlessly via
kubectl scaleor by editingspec.replicasin your YAML manifest. - Declarative Updates: Modifying a Deployment’s container image triggers a rolling update by spawning a new ReplicaSet while gracefully terminating the old one.
1. The Controller Hierarchy: Deployment vs ReplicaSet vs Pod#
graph TD
D["Deployment: web-app-deployment
(Strategy: RollingUpdate)"] --> RS1["ReplicaSet: web-app-7d4f9b8c (v1)
(Desired: 3, Ready: 3)"]
RS1 --> P1["Pod: web-app-7d4f9b8c-1a"]
RS1 --> P2["Pod: web-app-7d4f9b8c-2b"]
RS1 --> P3["Pod: web-app-7d4f9b8c-3c"]
- Deployment: Manages declarative updates for application specifications, version history, and rollbacks.
- ReplicaSet: Ensures that a specified number of identical Pod replicas (
spec.replicas) are running at any given time using label selectors (spec.selector.matchLabels). - Pod: The running container instance.
2. Declarative Deployment Manifest#
Create deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
namespace: default
labels:
app: frontend
tier: web
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
version: v1
spec:
containers:
- name: web-app
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"Apply the deployment manifest:
kubectl apply -f deployment.yamlExpected Terminal Output:
deployment.apps/frontend-deployment created3. Verifying Deployment & ReplicaSet State#
Check the Deployment status:
kubectl get deploymentsNAME READY UP-TO-DATE AVAILABLE AGE
frontend-deployment 3/3 3 3 25sInspect the underlying ReplicaSet created automatically by K8s:
kubectl get replicasetsNAME DESIRED CURRENT READY AGE
frontend-deployment-75b69bd654 3 3 3 40sList the 3 running Pod instances:
kubectl get pods -l app=frontendNAME READY STATUS RESTARTS AGE
frontend-deployment-75b69bd654-2x9lq 1/1 Running 0 55s
frontend-deployment-75b69bd654-8k4mn 1/1 Running 0 55s
frontend-deployment-75b69bd654-m9z12 1/1 Running 0 55s4. Testing Self-Healing Capabilities#
To demonstrate self-healing, let’s manually delete one of the Pods:
kubectl delete pod frontend-deployment-75b69bd654-2x9lqExpected Behavior:
pod "frontend-deployment-75b69bd654-2x9lq" deletedNow list the Pods immediately:
kubectl get pods -l app=frontendNAME READY STATUS RESTARTS AGE
frontend-deployment-75b69bd654-8k4mn 1/1 Running 0 2m
frontend-deployment-75b69bd654-m9z12 1/1 Running 0 2m
frontend-deployment-75b69bd654-p4vws 1/1 Running 0 4sNotice how the ReplicaSet detected that active replicas dropped from 3 to 2 and instantly spawned frontend-deployment-75b69bd654-p4vws (age 4 seconds) to restore the desired state!
5. Horizontal Scaling#
Imperative Scaling#
Scale up to 5 replicas:
kubectl scale deployment frontend-deployment --replicas=5Verify scaled replicas:
kubectl get pods -l app=frontendDeclarative Scaling#
In production, update replicas: 5 inside deployment.yaml and re-apply:
kubectl apply -f deployment.yaml6. Summary & Next Steps#
Deployments provide high availability and self-healing. However, Pod IP addresses are ephemeral—when a Pod dies and is replaced, its IP address changes. How do client applications communicate with a changing set of Pod IPs?
In Episode 05: Networking Services (ClusterIP, NodePort, LoadBalancer), we will explore Kubernetes Services to provide stable virtual IPs, DNS names, and load balancing across active replicas!

