6 min readDe Kicked Team
Deploy-uri fără downtime: strategiile blue-green, canary și rolling, comparate
Utilizatorii tăi n-ar trebui să știe că faci deploy. Comparăm strategiile de deploy blue-green, canary și rolling — când s-o folosești pe fiecare, cum le implementezi și compromisurile despre care nu vorbește nimeni.
- DevOps
- Kubernetes
- Reliability
- Deployments
„Facem deploy în ferestre de mentenanță, sâmbătă noaptea."
Dacă asta e strategia ta de deploy, livrezi mai încet decât ai nevoie și îți epuizezi echipa. Strategiile moderne de deploy îți permit să livrezi în producție în timpul programului, de mai multe ori pe zi, cu zero impact asupra clienților.
Dar contează să alegi strategia potrivită. Fiecare are compromisuri despre care rareori se discută.
Problema cu deploy-urile simple
Abordarea naivă — oprești versiunea veche, pornești versiunea nouă — creează downtime:
v1 running → v1 stopped → v2 starting → v2 ready
↑ ↑
downtime starts downtime ends
Chiar dacă sunt doar 30 de secunde, la scară asta înseamnă mii de request-uri eșuate, conexiuni WebSocket întrerupte și clienți nervoși.
Strategia 1: Rolling deployment
Cea mai simplă strategie fără downtime. Înlocuiești instanțele una câte una.
Time 0: [v1] [v1] [v1] [v1] ← all v1
Time 1: [v2] [v1] [v1] [v1] ← first pod updated
Time 2: [v2] [v2] [v1] [v1] ← second pod updated
Time 3: [v2] [v2] [v2] [v1] ← third pod updated
Time 4: [v2] [v2] [v2] [v2] ← all v2, done
În Kubernetes, asta este comportamentul implicit:
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # One extra pod during update
maxUnavailable: 0 # Never reduce below desired count
Avantaje:
- Simplu de implementat (implicit în Kubernetes)
- Eficient ca resurse — doar un pod în plus la un moment dat
- Funcționează din prima pentru servicii stateless
Dezavantaje:
- v1 și v2 rulează simultan — Aplicația ta trebuie să facă față. Migrările de bază de date, schimbările de API și starea partajată se pot strica.
- Rollback lent — Rollback-ul este un alt rolling update. Dacă v2 crapă, aștepți minute bune până revii complet.
- Greu de testat în producție — Nu poți ruta anumiți utilizatori către v2 pentru testare.
Potrivit pentru: Servicii stateless cu modificări compatibile înapoi. Majoritatea aplicațiilor web.
Strategia 2: Blue-green deployment
Rulezi două medii identice. Comuți traficul atomic.
Blue (v1): [v1] [v1] [v1] [v1] ← serving traffic
Green (v2): [v2] [v2] [v2] [v2] ← ready, not serving
Load Balancer
│
┌─────────┴─────────┐
│ Switch: Blue→Green │
└─────────────────────┘
Blue (v1): [v1] [v1] [v1] [v1] ← idle (rollback target)
Green (v2): [v2] [v2] [v2] [v2] ← serving traffic
# Kubernetes: switch Service selector
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
version: green # Flip this: blue ↔ green
ports:
- port: 80
targetPort: 8080
Avantaje:
- Rollback instant — Comuți selectorul înapoi pe blue. Gata în câteva secunde.
- Fără amestec de versiuni — Tot traficul lovește v1 SAU v2, niciodată ambele.
- Testare completă — Mediul green poate fi testat în întregime înainte de comutare.
Dezavantaje:
- Resurse duble — Ai nevoie de două medii complete care rulează simultan.
- Migrările de bază de date sunt delicate — Ambele versiuni trebuie să funcționeze cu aceeași schemă de bază de date în timpul comutării.
- Connection draining — Request-urile lungi de pe blue vor fi omorâte dacă nu faci drain corect.
Potrivit pentru: Servicii critice unde rollback-ul instant e esențial. Servicii cu cerințe stricte de compatibilitate între versiuni.
Strategia 3: Canary deployment
Rutezi un procent mic din trafic către versiunea nouă. Crești treptat dacă e sănătoasă.
Time 0: v1: 100% | v2: 0% ← deploy v2 canary
Time 1: v1: 95% | v2: 5% ← watch error rates
Time 2: v1: 80% | v2: 20% ← still healthy, increase
Time 3: v1: 50% | v2: 50% ← looking good
Time 4: v1: 0% | v2: 100% ← full promotion
Cu un VirtualService Istio:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api
spec:
hosts:
- api
http:
- route:
- destination:
host: api
subset: stable
weight: 95
- destination:
host: api
subset: canary
weight: 5
Avantaje:
- Blast radius minim — Dacă v2 e stricat, doar 5% dintre utilizatori sunt afectați.
- Testare reală în producție — Vezi cum se comportă v2 cu trafic real, date reale, încărcare reală.
- Promovare bazată pe date — Promovezi pe baza metricilor (rată de erori, latență), nu după instinct.
Dezavantaje:
- Necesită traffic splitting — Ai nevoie de un service mesh (Istio, Linkerd) sau de un load balancer inteligent.
- Lent — Promovarea completă ia timp (intenționat). Nu e grozav pentru fix-uri urgente.
- Granularitatea metricilor — Ai nevoie de metrici per versiune ca să compari v1 cu v2. Observabilitatea ta trebuie să fie solidă.
Potrivit pentru: Servicii cu trafic mare, unde vrei siguranță maximă. Servicii cu comportament complex, greu de testat în staging.
Recomandarea noastră: Argo Rollouts
Folosim Argo Rollouts pentru majoritatea deploy-urilor. Este un controller Kubernetes care adaugă strategiile canary și blue-green ca CRD-uri native:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 5m }
- setWeight: 20
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
analysis:
templates:
- templateName: success-rate
startingStep: 2 # Start analysis at 20%
args:
- name: service-name
value: api
Blocul analysis verifică automat metricile în timpul promovării. Dacă rata de erori depășește pragul, rollout-ul se oprește automat și face rollback. Nu e nevoie de intervenție umană la 3 dimineața.
Migrările de bază de date: partea grea
Fiecare strategie are același călcâi al lui Ahile: migrările de bază de date. Dacă v2 are nevoie de o coloană nouă, îți trebuie înainte ca v2 să înceapă să servească. Dar v1 încă rulează.
Soluția: migrări expand-contract.
Step 1: Add new column (nullable) ← v1 still works, ignores new column
Step 2: Deploy v2 (writes to both) ← v2 uses new column, v1 still works
Step 3: Backfill old data ← new column fully populated
Step 4: Deploy v3 (reads from new) ← fully migrated
Step 5: Drop old column ← cleanup
Nu face niciodată schimbări de schemă incompatibile într-un singur deploy. Întotdeauna extinde mai întâi, migrează datele, apoi contractă.
Referință rapidă
| Rolling | Blue-Green | Canary | |
|---|---|---|---|
| Cost în resurse | Mic | 2x | Mic-Mediu |
| Viteza de rollback | Minute | Secunde | Secunde |
| Amestec de versiuni | Da | Nu | Da (controlat) |
| Blast radius | Gradual | Totul sau nimic | Controlabil |
| Complexitate | Mică | Medie | Mare |
| Infrastructură necesară | Kubernetes | Kubernetes + mediu suplimentar | Service mesh sau Argo |
Începe să livrezi mai repede
Dacă încă faci deploy-uri în ferestre de mentenanță, începe cu rolling update-uri — sunt implicite în Kubernetes și nu necesită niciun tooling suplimentar. Odată ce te simți confortabil, treci la canary cu Argo Rollouts.
Ai nevoie de ajutor ca să configurezi deploy-uri fără downtime? Am făcut asta de sute de ori.