Canary Deployments with kubectl
Canary deployments release a new version to a small subset of users before rolling it out fully. This limits the blast radius of bugs and allows real-world validation.
Setting Up a Canary
Create a separate deployment for the canary version alongside the stable deployment. Both use the same pod label so the service routes to both:
# Scale the stable deployment
kubectl scale deployment myapp-stable --replicas=9
# Create a canary deployment with 1 replica (10% traffic)
kubectl create deployment myapp-canary \
--image=myregistry/myapp:v2.0.0 \
--replicas=1
# Ensure canary pods have the same app label
kubectl label deployment myapp-canary app=myapp
Percentage-Based Routing
Control traffic distribution by adjusting replica counts. The service load-balances evenly across all matching pods:
# 10% canary traffic: 9 stable + 1 canary
kubectl scale deployment myapp-stable --replicas=9
kubectl scale deployment myapp-canary --replicas=1
# Increase to 50%: 5 stable + 5 canary
kubectl scale deployment myapp-stable --replicas=5
kubectl scale deployment myapp-canary --replicas=5
# Full rollout: scale down stable, scale up canary
kubectl scale deployment myapp-stable --replicas=0
kubectl scale deployment myapp-canary --replicas=10
Manual Validation
Before increasing canary traffic, verify health manually:
# Check canary pod status
kubectl get pods -l app=myapp,track=canary
# Watch canary logs for errors
kubectl logs -l app=myapp,track=canary --tail=100 -f
# Compare error rates between versions
kubectl top pods -l app=myapp
# If the canary fails, roll back immediately
kubectl scale deployment myapp-canary --replicas=0
kubectl scale deployment myapp-stable --replicas=10
For more sophisticated traffic splitting, consider a service mesh like Istio, which supports weighted routing independent of replica count.