Progressive Delivery trên Kubernetes với Argo Rollouts: Hướng dẫn Canary và Blue/Green Deployment

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Bắt đầu nhanh — Chạy Argo Rollouts trong 5 phút

2 giờ sáng. Team vừa đẩy hotfix lên và chiến lược kubectl rollout thông thường đang khiến bạn toát mồ hôi lạnh — một pod lỗi là traffic sập ngay. Tôi đã trải qua điều đó. Và đó chính xác là đêm tôi bắt đầu nghiêm túc với Argo Rollouts.

Argo Rollouts là một Kubernetes controller cho phép bạn kiểm soát chính xác cách traffic dịch chuyển trong quá trình release: phân tách canary, chuyển đổi blue/green, phân tích metric tự động và rollback khi có lỗi. Các đối tượng Deployment tiêu chuẩn của Kubernetes không thể làm bất kỳ điều nào trong số này theo cách tự nhiên.

Cài đặt controller và plugin kubectl trước:

# Cài đặt Argo Rollouts controller
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts \
  -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

# Cài đặt kubectl plugin (macOS/Linux)
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x kubectl-argo-rollouts-linux-amd64
sudo mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

# Kiểm tra
kubectl argo rollouts version

Tiếp theo, thay manifest Deployment của bạn bằng đối tượng Rollout. Pod spec giữ nguyên — bạn chủ yếu chỉ đổi kind và thêm block strategy:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
spec:
  replicas: 5
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-registry/my-app:v1.0.0
        ports:
        - containerPort: 8080
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 2m}
      - setWeight: 50
      - pause: {duration: 5m}
      - setWeight: 100

Apply lên cluster:

kubectl apply -f rollout.yaml
kubectl argo rollouts get rollout my-app --watch

Bạn đã có một canary rollout hoạt động. 20% traffic đến phiên bản mới, chờ 2 phút, tăng lên 50%, chờ 5 phút, rồi chuyển toàn bộ. Tất cả mà không cần viết một dòng logic tùy chỉnh nào.

Tìm hiểu sâu hơn — Argo Rollouts thực sự hoạt động như thế nào

Chiến lược Canary

Bên dưới, Argo Rollouts quản lý hai ReplicaSet: tập stable (phiên bản hiện tại) và tập canary (phiên bản mới). Phân bổ traffic hoạt động bằng cách điều chỉnh số lượng replica — ở mức weight 20% với tổng 5 replica, bạn có 1 canary pod và 4 stable pod.

Để thực sự tách traffic ở cấp HTTP (không chỉ dựa trên replica), bạn cần tích hợp ingress controller hoặc service mesh. Với NGINX Ingress:

strategy:
  canary:
    canaryService: my-app-canary
    stableService: my-app-stable
    trafficRouting:
      nginx:
        stableIngress: my-app-ingress
    steps:
    - setWeight: 10
    - pause: {duration: 10m}
    - setWeight: 30
    - pause: {duration: 10m}
    - setWeight: 100

Tạo hai service mà Argo Rollouts sẽ quản lý:

---
apiVersion: v1
kind: Service
metadata:
  name: my-app-stable
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-canary
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080

Argo Rollouts tự động inject annotation NGINX để tách traffic ở cấp proxy — không phải ở cấp số lượng pod. Đây là sự khác biệt giữa “khoảng 10%” và “chính xác 10%”.

Chiến lược Blue/Green

Blue/green đơn giản hơn về mặt khái niệm: chạy phiên bản mới (green) song song với phiên bản cũ (blue), rồi bật công tắc. Không có ramp traffic dần dần — tất cả hoặc không có gì, nhưng bạn có thể kiểm tra green trước khi chuyển đổi.

strategy:
  blueGreen:
    activeService: my-app-active
    previewService: my-app-preview
    autoPromotionEnabled: false   # Yêu cầu promote thủ công
    scaleDownDelaySeconds: 30     # Giữ blue chạy 30 giây sau khi promote

Sau khi deploy image mới, các green pod khởi động sau my-app-preview. Team QA có thể truy cập trực tiếp endpoint preview để kiểm tra. Khi bạn tự tin:

# Promote green lên active (bật công tắc)
kubectl argo rollouts promote my-app

# Hoặc hủy và rollback về blue
kubectl argo rollouts abort my-app

Hãy chú ý đến scaleDownDelaySeconds lúc 2 giờ sáng. Nó giữ các pod cũ sống thêm một chút sau khi promote — đủ lâu để các request đang xử lý được drain hết. Khoảng đệm đó cũng cho bạn thời gian phát hiện vấn đề ngay lập tức và hủy trước khi các blue pod biến mất.

Nâng cao — Phân tích tự động và Rollback

Promote thủ công hoạt động tốt với team nhỏ. Nhưng khi bạn deploy nhiều lần mỗi ngày, bạn cần quy trình tự kiểm tra metric thay bạn. Argo Rollouts có AnalysisTemplate có thể truy vấn Prometheus, Datadog, New Relic hoặc bất kỳ HTTP endpoint nào và tự động quyết định tiếp tục hay rollback.

Định nghĩa một phân tích kiểm tra error rate:

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: error-rate-check
spec:
  args:
  - name: service-name
  metrics:
  - name: error-rate
    interval: 1m
    count: 5
    successCondition: result[0] < 0.05   # Dưới 5% lỗi
    failureLimit: 2
    provider:
      prometheus:
        address: http://prometheus.monitoring.svc:9090
        query: |
          sum(rate(http_requests_total{service="{{args.service-name}}",status=~"5.."}[2m]))
          /
          sum(rate(http_requests_total{service="{{args.service-name}}"}[2m]))

Kết nối vào chiến lược canary của bạn:

strategy:
  canary:
    steps:
    - setWeight: 20
    - analysis:
        templates:
        - templateName: error-rate-check
        args:
        - name: service-name
          value: my-app-canary
    - setWeight: 50
    - pause: {duration: 5m}
    - setWeight: 100

Bây giờ rollout dừng ở 20%, chạy 5 truy vấn Prometheus trong 5 phút và tự động hủy nếu error rate vượt 5% trong 2 lần kiểm tra trở lên. Không cần người trực lúc 2 giờ sáng.

Background Analysis cho Blue/Green

Với blue/green, bạn có thể chạy phân tích trên môi trường preview trước khi traffic production chạm đến phiên bản mới:

strategy:
  blueGreen:
    activeService: my-app-active
    previewService: my-app-preview
    autoPromotionEnabled: false
    prePromotionAnalysis:
      templates:
      - templateName: error-rate-check
      args:
      - name: service-name
        value: my-app-preview
    postPromotionAnalysis:
      templates:
      - templateName: error-rate-check
      args:
      - name: service-name
        value: my-app-active

Phân tích pre-promotion chạy trên preview. Phân tích post-promotion chạy trên active như một cửa sổ xác nhận. Nếu post-promotion thất bại, nó sẽ kích hoạt rollback tự động.

Mẹo thực tế từ môi trường production

1. Bắt đầu với promote thủ công

Đừng thêm phân tích tự động ngay từ ngày đầu. Hãy làm quen với cơ chế trước — các lệnh promoteabort thủ công. Những thao tác đó cần trở thành phản xạ tự nhiên trước khi bạn giao quyền kiểm soát cho tự động hóa. Những operator bỏ qua bước này thường đọc sai các lỗi tự động và override các rollback đáng lẽ phải giữ nguyên.

2. Luôn đặt scaleDownDelaySeconds

Mặc định là 30 giây. Với 1.000+ req/s, hãy tăng lên 60–120 giây. Cài đặt này đã cứu tôi một lần khi một canary âm thầm gây memory leak. Spike không xảy ra ngay lập tức. Nhưng thêm hai phút các stable pod vẫn còn warm đã cho phép chúng tôi hủy sạch sẽ — không có request nào bị mất.

strategy:
  blueGreen:
    scaleDownDelaySeconds: 120

3. Sử dụng Dashboard

Argo Rollouts đi kèm UI read-only rất hữu ích trong sự cố:

# Khởi động dashboard (port-forward đến localhost:3100)
kubectl argo rollouts dashboard

Bạn có được timeline trực quan của các bước, kết quả phân tích và số lượng replica. Khi mắt díu lại và đang cố giải thích trạng thái deployment trên một cuộc gọi Slack, một biểu đồ màu sắc còn hơn đọc output thô của kubectl nhiều.

4. Migrate từng bước — đừng viết lại tất cả cùng lúc

Chọn một service. Chạy nó như Rollout trong một sprint, tìm hiểu chỗ nào có thể thất bại, rồi mở rộng ra. Argo Rollouts hoàn toàn tương thích với ArgoCD — nếu bạn đã dùng GitOps, manifest Rollout chỉ cần nằm trong cùng repo với mọi thứ khác.

5. Chú ý hành vi Pause

pause: {} không có duration sẽ dừng vô thời hạn cho đến khi bạn promote thủ công. Hữu ích cho các canary cần người phê duyệt. Cạm bẫy: nếu pipeline CI/CD của bạn gọi kubectl argo rollouts promote mà không kiểm tra trạng thái rollout trước, nó sẽ promote ngay lập tức bất kể metric.

Luôn bảo vệ bước promote:

# Chờ cho đến khi rollout healthy hoặc degraded trước khi promote
kubectl argo rollouts status my-app --timeout 10m

# Sau đó chỉ promote nếu trạng thái là "Paused"
kubectl argo rollouts promote my-app

Argo Rollouts biến các Kubernetes deployment từ một cú bật công tắc nhị phân thành một quy trình có kiểm soát và quan sát được. Lần đầu tiên bạn chứng kiến một canary xấu tự động hủy và rollback lúc 3 giờ sáng — trong khi bạn vẫn đang đọc alert trên Slack — bạn sẽ hiểu tại sao điều này quan trọng.

Share: