Skip to main content

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