What You'll Learn
Kubernetes Deployments — how to create, configure, and manage rolling updates, rollbacks, scaling, and update strategies with real-world production YAML examples.
Deployment vs ReplicaSet vs Pod
A Deployment is the recommended way to run stateless applications in Kubernetes. It manages ReplicaSets (which manage Pods), enabling declarative updates and easy rollbacks.
Complete Production Deployment YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
labels:
app: my-app
version: "2.1.0"
annotations:
kubernetes.io/change-cause: "Release 2.1.0: Added payment module"
spec:
replicas: 3
# Pod selector — NEVER change this after creation!
selector:
matchLabels:
app: my-app
# Update strategy
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # How many extra pods during update
maxUnavailable: 0 # Keep all replicas available (zero-downtime)
# Wait before declaring pod ready (avoids flapping)
minReadySeconds: 10
# Keep last 5 ReplicaSets for rollback
revisionHistoryLimit: 5
template:
metadata:
labels:
app: my-app
version: "2.1.0"
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
spec:
terminationGracePeriodSeconds: 60 # Time to drain connections
# Anti-affinity: spread pods across nodes
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: my-app
containers:
- name: app
image: registry.example.com/my-app:2.1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
name: http
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
env:
- name: NODE_ENV
value: "production"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db-password
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
livenessProbe:
httpGet:
path: /health/live
port: 3000
initialDelaySeconds: 30
periodSeconds: 20
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"] # Allow LB to drain
imagePullSecrets:
- name: registry-credentials
Update & Rollback Commands
# ─── Deploy / Update ───
kubectl apply -f deployment.yaml
kubectl set image deployment/my-app app=registry.example.com/my-app:2.2.0
# Monitor rollout progress
kubectl rollout status deployment/my-app
kubectl rollout status deployment/my-app --timeout=5m
# ─── Rollback ───
kubectl rollout history deployment/my-app # View history
kubectl rollout history deployment/my-app --revision=3 # Specific revision
kubectl rollout undo deployment/my-app # Rollback to previous
kubectl rollout undo deployment/my-app --to-revision=2 # Rollback to specific
# ─── Scaling ───
kubectl scale deployment my-app --replicas=5
kubectl autoscale deployment my-app --min=2 --max=10 --cpu-percent=70
# ─── Pause / Resume rollout ───
kubectl rollout pause deployment/my-app # Pause (for canary)
kubectl rollout resume deployment/my-app # Resume
# ─── Restart all pods (without image change) ───
kubectl rollout restart deployment/my-app
# ─── Debugging deployments ───
kubectl get deployment my-app -o yaml
kubectl describe deployment my-app # Events + conditions
kubectl get rs -l app=my-app # ReplicaSets
kubectl get pods -l app=my-app -o wide # Pod distribution
Update Strategies Compared
RollingUpdate (Default)
Gradually replaces old pods with new ones. Zero downtime if configured correctly.
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Recreate
Kills all old pods, then creates new ones. Causes downtime but ensures no version mixing.
strategy:
type: Recreate
# Use for: DB schema migrations,
# single-instance apps that can't
# run multiple versions
Zero-Downtime Deployment Checklist
- ✅ Set
maxUnavailable: 0to never lose capacity during rollout - ✅ Add
readinessProbeso traffic only routes to ready pods - ✅ Set
minReadySecondsto catch issues before proceeding - ✅ Add
lifecycle.preStopsleep to let load balancer drain connections - ✅ Set
terminationGracePeriodSeconds> your longest request duration - ✅ Add
--change-causeannotation to track deployment reasons