Môi trường Preview trong Kubernetes: Cách chúng tôi giải quyết cuộc khủng hoảng ‘Ai làm hỏng staging?’ bằng Argo CD

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

Nút thắt cổ chai từ Server Staging

Cách đây vài năm, đội ngũ của tôi dùng chung một server staging duy nhất. Cảm giác lúc đó giống như một căn bếp chật chội chỉ có một cái bếp nấu. Một kỹ sư đang thử nghiệm luồng đăng nhập mới trong khi người khác cố gắng debug lỗi thanh toán. Họ chắc chắn sẽ dẫm chân lên nhau, dẫn đến những tin nhắn Slack đầy hoảng loạn lúc 4 giờ chiều: “Ai làm hỏng staging thế?”. Thật hỗn loạn, nó làm chậm tiến độ của đội ngũ 15 người và khiến việc QA giống như trò chơi đập chuột (whack-a-mole).

Các đội ngũ có tốc độ phát triển cao cần một cách tiếp cận tốt hơn: Ephemeral Environments (thường được gọi là Môi trường Preview). Hãy nghĩ theo cách này: mỗi Pull Request (PR) sẽ kích hoạt phiên bản ứng dụng độc lập, tồn tại ngắn hạn của riêng nó trên Kubernetes. Khi PR được merge hoặc đóng lại, môi trường đó sẽ biến mất. Những người review sẽ nhận được một URL sẵn sàng for production để kiểm tra các thay đổi trong một không gian riêng biệt trước khi bất kỳ code nào chạm tới nhánh chính.

Chúng tôi đã đưa thiết lập này vào vận hành thực tế từ năm ngoái, và nó giúp cắt giảm khoảng 12 giờ làm việc thủ công mỗi tuần. Bằng cách sử dụng Argo CD và controller ApplicationSet của nó, chúng tôi đã thay thế một “cơn ác mộng” thủ công bằng một hệ thống hoàn toàn tự động và hoạt động trơn tru.

“Động cơ”: Argo CD ApplicationSet

Trước khi có ApplicationSets, chúng tôi phải định nghĩa thủ công một “Application” của Argo CD cho mỗi nhánh. Cách này không thể mở rộng được. Controller ApplicationSet đã giải quyết vấn đề này bằng cách sử dụng một template để tạo ra nhiều Application dựa trên các trình kích hoạt (trigger) bên ngoài như GitHub PR.

Pull Request Generator chính là ngôi sao ở đây. Nó theo dõi repository của bạn để tìm các PR đang mở. Sau đó, nó thu thập siêu dữ liệu (metadata)—như số PR và commit SHA—để điền vào template triển khai của bạn. Đây chính là trái tim của quy trình làm việc ephemeral (tạm thời).

Tại sao lại chọn bộ công cụ này?

  • Sự cô lập thực sự: Mỗi PR sống trong Namespace riêng biệt của nó.
  • Tự phục hồi (Self-Healing): Nếu một pod bị lỗi trong môi trường preview, Argo CD sẽ tự động khôi phục nó.
  • Hiển thị đầy đủ: Dashboard của Argo CD hiển thị chính xác PR nào đang có môi trường hoạt động chỉ trong nháy mắt.

Thực hành: Thiết lập Pipeline của bạn

Các điều kiện tiên quyết rất đơn giản. Bạn cần một cluster Kubernetes đã cài Argo CD, một Git repository, và một bản ghi DNS wildcard (ví dụ: *.preview.mycompany.com) trỏ đến Ingress Controller của bạn.

Bước 1: Xác thực GitHub

Argo CD cần quyền để theo dõi repo của bạn. Hãy tạo một Personal Access Token (PAT) với phạm vi (scope) repo và lưu nó dưới dạng Secret trong namespace argocd của bạn.

kubectl create secret generic github-token \
  --from-literal=token=TOKEN_GITHUB_CUA_BAN_TAI_DAY \
  -n argocd

Bước 2: Manifest ApplicationSet

Tài nguyên ApplicationSet cho Argo CD biết cách xử lý các PR mới. Hãy tập trung vào cách các phần generatorstemplate hoạt động cùng nhau.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-app-previews
  namespace: argocd
spec:
  generators:
    - pullRequest:
        github:
          owner: my-organization
          repo: my-cool-app
          tokenRef:
            secretName: github-token
            key: token
        requeueAfterSeconds: 60
  template:
    metadata:
      name: 'preview-pr-{{number}}'
    spec:
      project: default
      source:
        repoURL: 'https://github.com/my-organization/my-cool-app.git'
        targetRevision: '{{head_sha}}'
        path: charts/my-app
        helm:
          parameters:
            - name: "ingress.host"
              value: "pr-{{number}}.preview.mycompany.com"
            - name: "image.tag"
              value: "{{head_sha}}"
      destination:
        server: https://kubernetes.default.svc
        namespace: 'preview-pr-{{number}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true

Đây là những gì đang diễn ra: Argo CD tạo ra một URL duy nhất như pr-123.preview.mycompany.com. Các biến {{number}}{{head_sha}} được đưa vào tự động. Khi bạn push một commit mới, Argo CD sẽ nhận thấy sự thay đổi của SHA và cập nhật môi trường ngay lập tức.

Bước 3: Giải quyết bài toán DNS

DNS thường là điểm gây khó khăn. Bạn không thể tạo thủ công một bản ghi cho từng PR một. Cách khắc phục? Một Bản ghi DNS Wildcard. Hãy trỏ *.preview.mycompany.com tới IP ngoài của Ingress Controller Nginx hoặc Traefik của bạn.

Khi ApplicationSet khởi tạo một Ingress mới, controller sẽ nhận diện host và điều hướng lưu lượng truy cập đến các pod mới. Quá trình này hoàn toàn tự động và đáng tin cậy.

Quản lý tài nguyên

Tài nguyên không miễn phí. Việc chạy một môi trường cho mọi PR có thể trở nên tốn kém nếu không được kiểm soát. May mắn thay, PR generator của ApplicationSet sẽ tự động xóa Application khi một PR được merge. Vì chúng ta đã bật prune: true, Kubernetes sẽ xóa sạch các Pod và Service liên quan ngay lập tức.

Tuy nhiên, bạn vẫn nên thiết lập các giới hạn. Nếu một đội ngũ bận rộn mở 20 PR cùng lúc, bạn sẽ không muốn các node của mình bị hết bộ nhớ. Tôi khuyên bạn nên sử dụng ResourceQuotas để giới hạn namespace preview ở mức khoảng 512Mi RAM và 0.5 CPU core.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: preview-quota
spec:
  hard:
    requests.cpu: "500m"
    requests.memory: "512Mi"
    limits.cpu: "1000m"
    limits.memory: "1Gi"

Quy trình làm việc mới

Khi hệ thống này đi vào hoạt động, một ngày làm việc của bạn sẽ khác biệt:

  1. Dev push một nhánh và mở một PR.
  2. Argo CD phát hiện PR trong vòng 60 giây.
  3. Một namespace preview-pr-X mới xuất hiện.
  4. Ứng dụng được triển khai qua Helm.
  5. Một bot sẽ comment vào PR kèm theo link preview.
  6. Các bên liên quan kiểm tra tính năng trực tiếp và để lại phản hồi.
  7. PR được merge, và Argo CD sẽ dọn dẹp mọi thứ.

Tổng kết

Chuyển sang môi trường ephemeral là một trong những thắng lợi lớn nhất cho bất kỳ pipeline DevOps nào. Nó loại bỏ nút thắt cổ chai ở staging và bắt lỗi trước khi chúng chạm tới production. Mặc dù DNS wildcard và ApplicationSet tốn một chút công sức ban đầu, nhưng tốc độ và sự tự tin mà chúng mang lại cho đội ngũ của bạn hoàn toàn xứng đáng với từng phút thiết lập. Hãy thử xem—các lập trình viên của bạn sẽ cảm ơn bạn đấy.

Share: