Sari la conținut
← Perspective

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.