15 - Deployments & Rolling Updates
What Is a Deployment?
A Deployment manages ReplicaSets which manage Pods. It provides:
- Declarative updates (change spec → K8s handles the rest)
- Rolling updates (zero-downtime deployments)
- Rollback capability
- Scaling
- Pause/resume rollouts
Deployment
│
├── ReplicaSet (v2) ← current (3 pods)
│ ├── Pod (v2)
│ ├── Pod (v2)
│ └── Pod (v2)
│
└── ReplicaSet (v1) ← old (0 pods, kept for rollback)
Deployment Manifest
yamlapiVersion: apps/v1 kind: Deployment metadata: name: web-app labels: app: web-app spec: replicas: 3 # How to find pods this Deployment manages selector: matchLabels: app: web-app # Rolling update strategy strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # Max pods over desired count during update maxUnavailable: 0 # Max pods unavailable during update # How long to wait before considering a new pod available minReadySeconds: 10 # How many old ReplicaSets to keep (for rollback) revisionHistoryLimit: 10 # Pod template (same as Pod spec) template: metadata: labels: app: web-app version: v2 spec: containers: - name: app image: myapp:v2 ports: - containerPort: 8080 resources: requests: cpu: 250m memory: 256Mi limits: cpu: 500m memory: 512Mi readinessProbe: httpGet: path: /ready port: 8080 periodSeconds: 5 livenessProbe: httpGet: path: /health port: 8080 periodSeconds: 10
Deployment Strategies
1. Rolling Update (Default)
Gradually replaces old pods with new ones:
yamlstrategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # Create 1 extra pod at a time maxUnavailable: 0 # Always maintain full capacity
Step 1: 3 old pods running
[v1] [v1] [v1]
Step 2: Create 1 new pod (maxSurge=1)
[v1] [v1] [v1] [v2]
Step 3: New pod ready → terminate 1 old pod
[v1] [v1] [v2]
Step 4: Create another new pod
[v1] [v1] [v2] [v2]
Step 5: New pod ready → terminate 1 old pod
[v1] [v2] [v2]
Step 6: Create last new pod
[v1] [v2] [v2] [v2]
Step 7: New pod ready → terminate last old pod
[v2] [v2] [v2]
Done! Zero downtime.
2. Recreate
Kill all old pods, then create new ones (has downtime):
yamlstrategy: type: Recreate
Step 1: [v1] [v1] [v1]
Step 2: [ ] [ ] [ ] ← DOWNTIME
Step 3: [v2] [v2] [v2]
Use when: App can't run two versions simultaneously (e.g., database schema incompatibility).
3. Blue-Green (Manual)
Run two full environments, switch traffic:
yaml# Blue deployment (current) apiVersion: apps/v1 kind: Deployment metadata: name: web-blue spec: replicas: 3 selector: matchLabels: app: web version: blue template: metadata: labels: app: web version: blue spec: containers: - name: app image: myapp:v1 --- # Green deployment (new version) apiVersion: apps/v1 kind: Deployment metadata: name: web-green spec: replicas: 3 selector: matchLabels: app: web version: green template: metadata: labels: app: web version: green spec: containers: - name: app image: myapp:v2 --- # Service points to blue apiVersion: v1 kind: Service metadata: name: web spec: selector: app: web version: blue # Switch to "green" to cut over ports: - port: 80 targetPort: 8080
bash# Switch traffic to green kubectl patch svc web -p '{"spec":{"selector":{"version":"green"}}}' # Rollback: switch back to blue kubectl patch svc web -p '{"spec":{"selector":{"version":"blue"}}}'
4. Canary (Manual or with Service Mesh)
Route a small percentage of traffic to the new version:
yaml# Stable deployment (90% traffic) apiVersion: apps/v1 kind: Deployment metadata: name: web-stable spec: replicas: 9 selector: matchLabels: app: web track: stable template: metadata: labels: app: web track: stable spec: containers: - name: app image: myapp:v1 --- # Canary deployment (10% traffic) apiVersion: apps/v1 kind: Deployment metadata: name: web-canary spec: replicas: 1 # 1 out of 10 pods = ~10% traffic selector: matchLabels: app: web track: canary template: metadata: labels: app: web track: canary spec: containers: - name: app image: myapp:v2 --- # Service selects ALL pods with app=web (both stable and canary) apiVersion: v1 kind: Service metadata: name: web spec: selector: app: web # Matches both track=stable and track=canary ports: - port: 80 targetPort: 8080
For precise traffic splitting, use Istio, Linkerd, or Argo Rollouts.
Performing Updates
bash# Update image (triggers rolling update) kubectl set image deployment/web-app app=myapp:v3 # Or edit the YAML kubectl edit deployment web-app # Or apply updated manifest (recommended) kubectl apply -f deployment.yaml # Update with a record (for rollback annotation) kubectl set image deployment/web-app app=myapp:v3 --record
Monitoring Rollouts
bash# Watch rollout status kubectl rollout status deployment/web-app # Waiting for deployment "web-app" rollout to finish: # 2 out of 3 new replicas have been updated... # deployment "web-app" successfully rolled out # See rollout history kubectl rollout history deployment/web-app # REVISION CHANGE-CAUSE # 1 <none> # 2 kubectl set image deployment/web-app app=myapp:v2 # 3 kubectl set image deployment/web-app app=myapp:v3 # See details of a specific revision kubectl rollout history deployment/web-app --revision=2
Rollbacks
bash# Rollback to previous version kubectl rollout undo deployment/web-app # Rollback to specific revision kubectl rollout undo deployment/web-app --to-revision=1 # Check which revision is active kubectl describe deployment web-app | grep "revision"
Pause and Resume
bash# Pause rollout (make multiple changes without triggering multiple rollouts) kubectl rollout pause deployment/web-app # Make changes kubectl set image deployment/web-app app=myapp:v4 kubectl set resources deployment/web-app -c app --limits=cpu=500m,memory=512Mi # Resume (single rollout with all changes) kubectl rollout resume deployment/web-app
Scaling
bash# Manual scaling kubectl scale deployment/web-app --replicas=5 # Or edit the manifest kubectl patch deployment web-app -p '{"spec":{"replicas":5}}'
For auto-scaling, see 21 - Auto-Scaling.
Deployment Conditions
bashkubectl describe deployment web-app
| Condition | Meaning |
|---|---|
| Available | Minimum replicas are available |
| Progressing | Rollout is in progress |
| ReplicaFailure | Failed to create pods |
kubectl Deployment Commands
bash# Create kubectl create deployment web --image=nginx:alpine --replicas=3 # List kubectl get deployments kubectl get deploy # Describe kubectl describe deployment web-app # Delete kubectl delete deployment web-app # Restart all pods (rolling restart) kubectl rollout restart deployment/web-app
FAANG Interview Angle
Common questions:
- "How do you achieve zero-downtime deployments in Kubernetes?"
- "Explain rolling update strategy and its parameters"
- "Compare blue-green, canary, and rolling update strategies"
- "How do you rollback a failed deployment?"
- "What happens if a new pod fails readiness checks during rollout?"
Key answers:
- Rolling updates with readiness probes; maxSurge/maxUnavailable control the pace
- maxSurge: extra pods allowed. maxUnavailable: pods that can be down. Both 0 = impossible
- Rolling: gradual, built-in. Blue-green: instant switch, double resources. Canary: test with subset
kubectl rollout undo; K8s keeps old ReplicaSets for rollback- Rollout stalls; old pods continue serving; deployment shows "Progressing" condition