Skip to content

Progressive Delivery Strategies — Canary & Blue-Green

Tại sao Progressive Delivery Quan Trọng

Deploy thẳng tất cả traffic lên version mới (rolling update mặc định của Kubernetes) có rủi ro: nếu version mới có bug, 100% users bị ảnh hưởng ngay khi rollout hoàn thành. Progressive delivery giải quyết bằng cách kiểm soát tốc độ rollout: chỉ expose một phần nhỏ traffic lên version mới trước, validate, rồi mới expand.

Cloud Deploy hỗ trợ hai chiến lược: canary (tăng dần traffic percentage) và blue-green (parallel environments, atomic cutover). Hiểu cơ chế bên trong của từng chiến lược là điều kiện để thiết kế đúng và debug khi vấn đề xảy ra.


Canary Deployment — Cơ Chế Bên Trong

Ba loại canary configuration

Theo tài liệu Cloud Deploy, có ba cấu hình canary:

1. Automated canary: Cloud Deploy tự động tạo infrastructure cho traffic splitting. Người dùng chỉ cần chỉ định percentages.

2. Custom-automated canary: Người dùng chỉ định chi tiết phase, nhưng Cloud Deploy vẫn tự động manage infrastructure.

3. Custom canary: Full control — người dùng define tất cả, kể cả cách traffic splitting được thực hiện. Hoạt động với mọi target type.

Traffic Splitting Mechanics — GKE

Trên GKE, Cloud Deploy hỗ trợ hai cơ chế traffic splitting:

Service Networking (Kubernetes Services):

yaml
strategy:
  canary:
    runtimeConfig:
      kubernetes:
        serviceNetworking:
          deployment: my-app
          service: my-app-svc

Cơ chế này dùng replica count manipulation. Giả sử canary percentage là 10% và total replicas là 10:

  • Cloud Deploy duy trì stable Deployment (version cũ): 9 replicas
  • Tạo canary Deployment (version mới): 1 replica
  • Cả hai Deployments dùng chung Service selector → traffic được phân phối theo tỷ lệ số replicas

Giới hạn của cơ chế này: Tỷ lệ traffic phụ thuộc replica count, không phải request-based weights. Với replicas nhỏ (ví dụ 3 replicas), không thể đạt chính xác 10% — bạn chỉ có thể làm 33% (1/3) hay 0%. Đây là fundamental constraint của Service-based routing.

Gateway API (Kubernetes Gateway):

yaml
strategy:
  canary:
    runtimeConfig:
      kubernetes:
        gatewayServiceMesh:
          httpRoute: my-app-route
          service: my-app-svc
          deployment: my-app

Với Kubernetes Gateway API (HTTPRoute), traffic splitting được thực hiện ở tầng load balancer:

yaml
# Cloud Deploy tự động tạo/update HTTPRoute với weights:
spec:
  rules:
  - backendRefs:
    - name: my-app-stable-svc
      weight: 90    # Version cũ: 90%
    - name: my-app-canary-svc
      weight: 10    # Version mới: 10%

Đây là request-based weight, không phụ thuộc replica count. Bạn có thể đạt chính xác bất kỳ percentage nào với bất kỳ số replicas nào. Tuy nhiên yêu cầu:

  • GKE Dataplane V2 (Cilium) hoặc Cloud Service Mesh (Istio) để xử lý HTTPRoute
  • Gateway controller được cài đặt trong cluster

Traffic Splitting trên Cloud Run

Cloud Run có cơ chế traffic splitting native — không cần Service Networking hay Gateway API:

yaml
strategy:
  canary:
    runtimeConfig:
      cloudRun:
        automaticTrafficControl: true
    canaryDeployment:
      percentages: [25, 50, 75]

Cloud Deploy deploy revision mới của Cloud Run service, sau đó update traffic split config:

my-service:
  revision-stable: 75%  # Version cũ
  revision-canary: 25%  # Version mới (phase canary-25)

Cloud Run native traffic splitting là request-based và rất chính xác. Đây là lý do Cloud Run canary đơn giản hơn GKE canary về mặt cơ chế.

Canary Phases

Với configuration percentages: [10, 50], Cloud Deploy tạo 3 phases:

Rollout phases:
1. canary-10     → Deploy version mới lên 10% traffic
2. canary-50     → Advance lên 50% traffic
3. stable        → Deploy version mới lên 100%, version cũ bị xóa

Mỗi phase là một independent job có thể:

  • Succeed → advance tự động hoặc manual promotion
  • Fail → trigger repair automation hoặc manual intervention
  • Timeout → treated as fail

Giữa các phases có thể có verify job: test suite chạy sau khi traffic đạt percentage mới, kiểm tra metrics, errors, latency. Nếu verify fail, rollout không advance.

Stable Phase — End State

Phase stable là khi canary "graduates" thành full deployment:

  • Version mới được deploy như full Deployment (thay thế stable Deployment cũ)
  • Canary Deployment bị xóa
  • Traffic split resource (HTTPRoute/Service) được cleanup

Sau phase stable, cluster ở cùng trạng thái như một rolling update thông thường — không còn parallel Deployments, không còn traffic split configuration.


Blue-Green Deployment — Cơ Chế Bên Trong

Khái niệm cốt lõi

Blue-green deployment duy trì hai environments song song (blue = version cũ, green = version mới):

  • Cả hai environments hoàn toàn functional và ready để serve traffic
  • Tại một thời điểm cụ thể (cutover), traffic được chuyển từ blue sang green atomically (nhanh, không progressive)
  • Blue environment được giữ lại sau cutover để phục vụ rollback nhanh

Khác canary ở điểm quan trọng: trong canary, users thật nhận version mới ở mỗi bước. Trong blue-green, không có users nào nhận version mới cho đến khi cutover hoàn tất.

Blue-Green trên GKE

yaml
strategy:
  blueGreen:
    serviceNetworking:
      deployment: my-app
      service: my-app-svc
    autoUpdateServices: true
    stableCutbackDuration: 60s   # Thời gian giữ blue sau khi green rollout
    predeploy:
      phases: [predeploy]
    postdeploy:
      phases: [postdeploy]

Flow của một blue-green rollout trên GKE:

Phase 1: predeploy (hooks chạy trước deploy)
Phase 2: deploy-green
  → Cloud Deploy tạo Deployment mới: {original-name}-green
  → Deployment mới rollout hoàn toàn (all replicas ready)
  → Service KHÔNG được update → traffic vẫn đến blue (version cũ)
Phase 3: verify (optional — test green trực tiếp qua canary endpoint)
Phase 4: postdeploy (hooks)
Cutover (manual advance hoặc automatic):
  → Service selector được update để trỏ sang green Deployment
  → stableCutbackDuration: giữ blue Deployment trong N seconds
  → Sau stableCutbackDuration: blue Deployment bị xóa

Stable cutback duration là thời gian sau khi cutover mà blue Deployment còn tồn tại. Trong khoảng thời gian này, rollback là instant (chỉ cần update Service selector trở lại). Sau khi hết thời gian, rollback yêu cầu deploy lại từ stable Rollout.

Blue-Green trên Cloud Run

yaml
strategy:
  blueGreen:
    trafficSplit: 100   # 100% traffic đến version mới sau cutover
    disablePodOverprovisioning: false

Cloud Run blue-green đơn giản hơn:

  • Cloud Deploy deploy revision mới (green) nhưng set traffic = 0%
  • Sau verify (nếu có), update traffic split: green 100%, blue 0%
  • Blue revision được giữ lại (Cloud Run không tự xóa revision)

Khi nào dùng Blue-Green

Blue-green phù hợp khi:

  • Database schema changes: Version mới cần schema mới, version cũ không tương thích ngược. Bạn muốn test version mới với 0 traffic thực trước khi cutover.
  • Breaking API changes: Không thể có cả hai versions cùng serve traffic vì chúng không compatible.
  • Batch jobs/workers: Không muốn partial traffic split — muốn atomic switch.

Blue-green không phù hợp khi:

  • Resources cost là concern: duy trì 2x capacity trong suốt thời gian deploy
  • Stateful applications với local state: chuyển traffic đột ngột có thể lost in-flight requests

Canary vs Blue-Green vs Rolling Update

Tiêu chíRolling UpdateCanaryBlue-Green
Traffic exposure100% ngay khi pod mới upTăng dần (10% → 50% → 100%)0% cho đến cutover
Cost trong deploy1x~1x + overhead nhỏ~2x
Rollback speedChậm (rolling rollback)Nhanh (revert traffic split)Instant (revert Service selector)
Phát hiện lỗiSau khi nhiều users bị ảnh hưởngSớm, trên subset nhỏChỉ trong test phase trước cutover
Database compatCần backward compatCần backward compatCó thể không cần (deploy xong rồi mới switch)
Phức tạpThấpTrung bìnhCao

Canary Analysis — Verify Phase Integration

Cloud Deploy hỗ trợ automated analysis trong canary phases để quyết định có advance hay không:

yaml
strategy:
  canary:
    canaryDeployment:
      percentages: [10, 50]
      verify: true    # Enable verify phase sau mỗi canary step

Verify phase là một Job chạy sau khi traffic đạt percentage target. Nó thực thi analysis logic được định nghĩa trong Skaffold's verify section:

yaml
# skaffold.yaml
verify:
- name: check-error-rate
  container:
    name: error-rate-checker
    image: my-error-checker-image
    command: ["/bin/check-errors.sh"]
    args: ["--threshold=0.01", "--window=5m"]

Analysis job có thể:

  • Query Cloud Monitoring metrics API
  • Call external analysis service (Argo Rollouts analysis template pattern)
  • Run integration test suite
  • Check SLO compliance

Nếu verify job exit với code 0 → rollout advances. Non-zero exit → rollout fails, trigger rollback repair (nếu configured).


Failure Modes và Rollback trong Canary

Failure trong canary phase

Nếu canary-10 phase fail:

  • Traffic vẫn đang split: 10% green, 90% stable
  • Rollout trạng thái: FAILED
  • Cloud Deploy không tự động revert traffic trừ khi Automation repair configured
  • Engineer phải manually cancel rollout (revert traffic) hoặc trigger repair automation

Repair Automation (xem thêm file 04):

yaml
# Automation: tự động rollback khi rollout fail
rules:
- name: rollback-on-failure
  rollbackRule:
    sourceRunId: latest

Tại sao canary rollback không instant bằng blue-green

Trong canary với Service Networking, rollback = xóa canary Deployment và adjust replica counts. Quá trình này mất thời gian (Kubernetes terminate pods, scale down). Trong blue-green, rollback chỉ là update Service selector — milliseconds.


Các Ràng Buộc Kỹ Thuật Quan Trọng

GKE Canary với Service Networking: Minimum Replicas

Như đã phân tích, với serviceNetworking, traffic ratio = replica ratio. Muốn 10% canary với accuracy, cần ít nhất 10 replicas tổng. Nếu chỉ có 3 replicas, canary percentage options thực tế là: 33%, 67%, hoặc không canary.

Giải pháp: dùng Gateway API với HTTPRoute để có exact percentage control không phụ thuộc replica count.

Stateful Session Trong Canary

Nếu application dùng sticky sessions (session affinity), canary có thể không đúng: một user đã "dính" với stable pod có thể never được route sang canary pod. Analyze này sẽ không đại diện cho toàn bộ users.

Giải pháp: tắt session affinity trong thời gian canary, hoặc dùng header-based routing để explicitly route một subset users sang canary.

Database Migration và Canary

Canary ngầm giả định cả hai versions (stable + canary) chạy đồng thời và tương thích với cùng database state. Nếu version mới cần database migration:

  • Migration phải backward-compatible (expand-and-contract pattern)
  • Không drop columns cho đến khi toàn bộ traffic đã chuyển sang version mới
  • Blue-green phù hợp hơn cho scenarios này vì deploy xong rồi mới switch traffic

Official References