You learned that bare pods die and don't come back. So how do production apps stay running? Enter Deployments.
Imagine you need to print 100 copies of a document. You don't:
- Print one, wait, print another, wait... (too slow)
- Worry if the printer jams (it auto-recovers)
- Manually replace paper or toner (it manages itself)
You just tell the copier: "I need 100 copies of this document, keep them coming."
Deployments are Kubernetes' copy machine. You declare:
- What image to run (the document)
- How many copies you want (replicas)
- How to update them when needed (rolling update strategy)
Kubernetes ensures that many copies are always running, replacing failed ones automatically.
A Deployment is a controller that manages a ReplicaSet, which manages Pods.
Hierarchy:
Deployment
└── ReplicaSet
├── Pod 1
├── Pod 2
└── Pod 3
Deployment provides:
- Desired state management - "I want 3 replicas"
- Self-healing - Pod dies? Deployment creates a new one
- Scaling - Change replica count on the fly
- Rolling updates - Update app version with zero downtime
- Rollback - Oops, new version breaks? Roll back
Let's deploy nginx with 3 replicas.
Create file: nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # We want 3 copies
selector:
matchLabels:
app: nginx # Which pods does this deployment manage?
template: # Pod template
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80Deploy it:
kubectl apply -f nginx-deployment.yaml
# Check deployment
kubectl get deployments
# Output:
# NAME READY UP-TO-DATE AVAILABLE AGE
# nginx-deployment 3/3 3 3 20sCheck the pods it created:
kubectl get pods
# Output: You'll see 3 pods with names like:
# nginx-deployment-7d64c8d7f5-abcde
# nginx-deployment-7d64c8d7f5-fghij
# nginx-deployment-7d64c8d7f5-klmnoNotice the pod names? They're auto-generated: <deployment-name>-<replicaset-hash>-<random-id>
Let's kill a pod and watch Kubernetes bring it back.
# Get pods
kubectl get pods
# Delete one pod (replace with actual pod name)
kubectl delete pod nginx-deployment-7d64c8d7f5-abcde
# Immediately check pods
kubectl get pods
# You'll see:
# - The pod you deleted is Terminating
# - A NEW pod is already being created
# - Total count goes back to 3What happened?
- You deleted a pod
- Deployment noticed: "Hey, I wanted 3, now there's only 2"
- Deployment told ReplicaSet: "Create another pod"
- ReplicaSet created a new pod
- Desired state restored
This is self-healing. In production, if a pod crashes, Deployment auto-recovers.
Need more replicas? Just change the number.
Option 1: Edit YAML and re-apply
# Change replicas: 3 to replicas: 5
spec:
replicas: 5kubectl apply -f nginx-deployment.yaml
kubectl get pods
# Now you see 5 podsOption 2: Scale via kubectl
# Scale to 5 replicas
kubectl scale deployment nginx-deployment --replicas=5
kubectl get pods
# 5 pods running
# Scale down to 2
kubectl scale deployment nginx-deployment --replicas=2
kubectl get pods
# Watch as 3 pods terminate, leaving 2Scaling is instant. Kubernetes just adjusts pod count to match desired state.
Time to update the nginx version without downtime.
Current state: Running nginx:1.25
Goal: Update to nginx:1.26 with zero downtime
Edit YAML:
spec:
template:
spec:
containers:
- name: nginx
image: nginx:1.26 # Changed from 1.25 to 1.26Apply the update:
kubectl apply -f nginx-deployment.yaml
# Watch the rollout
kubectl rollout status deployment nginx-deploymentWatch pods during update:
kubectl get pods --watchYou'll see:
- New pod created with nginx:1.26
- Once it's ready, old pod terminated
- Another new pod created
- Another old pod terminated
- Repeat until all pods are updated
This is rolling update. At no point are all pods down. Traffic keeps flowing.
Check rollout history:
kubectl rollout history deployment nginx-deployment
# Output shows revision history
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>New version has a bug. Roll back instantly.
# Rollback to previous version
kubectl rollout undo deployment nginx-deployment
# Check status
kubectl rollout status deployment nginx-deployment
# Verify image
kubectl describe deployment nginx-deployment | grep Image
# Should show nginx:1.25 againRollback to specific revision:
# See history
kubectl rollout history deployment nginx-deployment
# Rollback to revision 1
kubectl rollout undo deployment nginx-deployment --to-revision=1There are 2 main strategies:
Gradually replace old pods with new ones.
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max extra pods during update
maxUnavailable: 0 # Max unavailable pods during updatemaxSurge: 1 = During update, can have 4 pods instead of 3 temporarily
maxUnavailable: 0 = Never have less than 3 pods running
This ensures zero downtime but uses more resources temporarily.
Kill all old pods, then create new ones.
spec:
strategy:
type: RecreateUse when:
- App can't run multiple versions simultaneously
- Okay with brief downtime
- Want to save resources
apiVersion: apps/v1 # Deployment is in apps/v1 API group
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx # Labels for the deployment itself
spec:
replicas: 3 # How many pod copies
selector:
matchLabels:
app: nginx # MUST match template.metadata.labels
template: # Pod template
metadata:
labels:
app: nginx # Labels for the pods
spec:
containers:
- name: nginx
image: nginx:1.25Critical: selector.matchLabels MUST match template.metadata.labels. This is how Deployment knows which pods it manages.
spec:
selector:
matchLabels:
app: web # Says "web"
template:
metadata:
labels:
app: nginx # But pods labeled "nginx"Result: Deployment won't work. Selector can't find matching pods.
If your cluster doesn't have resources for replicas, pods stay Pending.
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-deployment-xxx 0/1 Pending 0 2mCheck why:
kubectl describe pod nginx-deployment-xxx
# Events: Insufficient memory or CPUFix: Reduce replicas or add more nodes.
image: ngnix:1.25 # Typo: ngnix instead of nginxkubectl get pods
# STATUS: ImagePullBackOffFix: Correct the image name.
Check deployment status:
kubectl get deployment nginx-deployment
# READY column shows: current/desired
# If stuck, something's wrongDetailed info:
kubectl describe deployment nginx-deployment
# Look at:
# - Replicas section
# - Conditions
# - EventsCheck associated ReplicaSet:
kubectl get replicaset
# Shows RS created by deployment
kubectl describe replicaset <rs-name>Check pods:
kubectl get pods -l app=nginx
# -l filters by label
# Shows only pods with label app=nginxDeploy a web application with these requirements:
- Use image
hashicorp/http-echo:1.0 - Run 4 replicas
- Container listens on port 5678
- Pass argument
-text=Version 1 - Update to Version 2 without downtime
- Rollback if needed
Hints:
# Pass args to container:
containers:
- name: app
image: some-image
args:
- "-text=Hello"
- "-listen=:5678"Try it yourself.
Solution (click to expand)
File: echo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-deployment
spec:
replicas: 4
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: hashicorp/http-echo:1.0
args:
- "-text=Version 1"
- "-listen=:5678"
ports:
- containerPort: 5678Deploy:
kubectl apply -f echo-deployment.yaml
kubectl get pods
# Should see 4 pods
# Update to Version 2
# Edit file, change -text=Version 2
kubectl apply -f echo-deployment.yaml
# Watch rollout
kubectl rollout status deployment echo-deployment
# Rollback if needed
kubectl rollout undo deployment echo-deploymentkubectl delete deployment nginx-deployment echo-deployment- Use Deployments, not bare Pods - For any production workload
- Self-healing is automatic - Pods die, Deployment recreates them
- Scaling is trivial - Just change replica count
- Rolling updates = zero downtime - Update apps without service interruption
- Rollback is one command - Recover from bad deploys instantly
- Deploy apps with multiple replicas
- Scale up/down on demand
- Update apps with rolling updates
- Rollback failed deployments
- Understand deployment strategies
You have multiple pod replicas running. But how do you access them? How does traffic get distributed?
Next: Chapter 4: Services - Load balancing and service discovery
Estimated time: 2-3 hours
Difficulty: Intermediate
Key command: kubectl rollout status deployment/<name> - Watch your updates happen