Canary deployment
Ce este canary?
Canary este strategia de deploy unde o mică parte din trafic merge către noua versiune, iar restul către versiunea stabilă.
Diagrama:
[Trafic]
↓
┌─────┴─────┐
↓ ↓
[Stable 90%] [Canary 10%]
↓ ↓
Monitor Monitor
Metodologie: testezi noua versiune în producție cu utilizatori reali, dar cu expunere minimă.
Canary în Kubernetes
Kubernetes nu oferă suport nativ pentru canary. Trebuie implementat manual folosind Labels + Selectors.
Task
Aici veți face un canary manual, folosind fișierele și comenzile de mai jos.
stable-app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: stable-app
labels:
app: web-app
track: stable
spec:
replicas: 9 # 90% din trafic
selector:
matchLabels:
app: web-app
track: stable
template:
metadata:
labels:
app: web-app
track: stable
version: "1"
spec:
containers:
- name: web
image: nginx:1.21
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: web-app-v1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: web-app-v1
data:
index.html: |
<html><head><title>Stable V1</title></head>
<body style="background:#f0f0f0">
<h1>🔵 Stable Version 1.0</h1>
<p>90% of traffic here</p>
</body></html>
---
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
selector:
app: web-app # Selects BOTH stable AND canary!
ports:
- port: 80
targetPort: 80
type: LoadBalancer
canary-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary-app
labels:
app: web-app
track: canary
spec:
replicas: 1 # 10% din trafic (1 din 10 pod-uri)
selector:
matchLabels:
app: web-app
track: canary
template:
metadata:
labels:
app: web-app
track: canary
version: "2"
spec:
containers:
- name: web
image: nginx:1.21
ports:
- containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: web-app-v2
---
apiVersion: v1
kind: ConfigMap
metadata:
name: web-app-v2
data:
index.html: |
<html><head><title>Canary V2</title></head>
<body style="background:#ffeb3b">
<h1>🟡 Canary Version 2.0</h1>
<p>10% of traffic here - testing!</p>
</body></html>
- executați comenzile de mai jos:
# STEP 1: Deploy versiunea stabilă
kubectl apply -f stable-app.yaml
# Observă:
kubectl get pods -l track=stable
# Ar trebui să vedem 9 pod-uri (90% din trafic).
# STEP 2: Testează traficul
for i in {1..10}; do
curl -s localhost | grep Version;
done
# Ar trebui să vezi numai "Stable Version 1.0".
# STEP 3: Deploy canary (10% din trafic)
kubectl apply -f canary-app.yaml
# Verificam toate podurile cu labelul nostru:
kubectl get pods -l app=web-app
# Ar trebui să vedem: 9 stable + 1 canary = 10 total (10% canary)
# STEP 4: Testăm distribuția traficului
for i in {1..20}; do
curl -s localhost | grep Version;
done
# Observăm output-ul (10% răspuns de la canary și 90% de la stable)
# STEP 5: Mărește canary la 50%
kubectl scale deployment/stable-app --replicas=5
kubectl scale deployment/canary-app --replicas=5
# Verifică:
kubectl get pods -l app=web-app
# Ar trebui să vedem: 5 stable + 5 canary = 50/50
# STEP 6: Testăm din nou
for i in {1..20}; do
curl -s localhost | grep Version;
done
# Acum ar trebui să vedem ~50% canary.
# STEP 7: Rollout complet (100% canary)
kubectl scale deployment/stable-app --replicas=0
kubectl scale deployment/canary-app --replicas=10
# Acum 100% din trafic merge la canary.
# Rollback dacă canary eșuează
# Eliminăm aplicația canary:
kubectl delete deployment canary-app
# Sau reduce distribuția:
kubectl scale deployment/canary-app --replicas=0
kubectl delete deployment stable-app canary-app
kubectl delete service web-app-service
kubectl delete configmap web-app-v1 web-app-v2