Nâng cao
8 phút đọc5 tháng 6, 20261

GitOps Promoter: Promote môi trường không còn là cơn ác mộng

Tool mới từ argoproj-labs giúp tự động hóa việc promote code qua các môi trường theo đúng tinh thần GitOps không fragile scripts, không manual mess.

N

Nguyễn Nhật Long

@nguyennhatlong1303

GitOps Promoter: Promote môi trường không còn là cơn ác mộng

Nếu bạn đang dùng ArgoCD hay bất kỳ GitOps tool nào, chắc chắn bạn đã từng đau đầu với bài toán này: làm sao để promote một commit từ dev lên staging, rồi từ staging lên prod một cách tự động, an toàn, và có kiểm soát?

Mình đã trải qua đủ kiểu giải pháp từ shell script chạy git cherry-pick rồi push lên, đến dùng CI pipeline tự merge branch, rồi cả kiểu dùng Kustomize overlays với GitHub Actions tự động update image tag. Cái nào cũng có vấn đề. Không phải fragile thì cũng thiếu visibility, hoặc khó maintain khi team lớn dần.

Rồi mình tìm thấy gitops-promoter từ argoproj-labs. Cái project này giải quyết đúng cái pain point đó và theo một cách khá thú vị.

Vấn đề thực sự của environment promotion trong GitOps

Trước khi nói về tool, mình muốn nói rõ vấn đề một chút, vì nhiều người hay bỏ qua phần này.

Trong GitOps, Git là source of truth. Mỗi môi trường thường map với một branch hoặc một thư mục trong repo. Khi bạn muốn promote tức là đưa một thay đổi từ môi trường này sang môi trường khác về cơ bản bạn đang merge hoặc copy một commit từ branch này sang branch khác.

Nghe đơn giản. Nhưng thực tế thì không:

  • Bạn cần đảm bảo commit đó đã thực sự healthy ở môi trường nguồn trước khi promote lên
  • Bạn cần có cơ chế gate ví dụ: security scan phải pass, performance test phải xanh, không có deployment freeze
  • Bạn cần audit trail ai promote cái gì, khi nào, tại sao
  • Bạn cần tránh drift không phải cứ merge là xong, bạn cần đảm bảo trạng thái thực tế khớp với những gì trong Git

Các giải pháp tự chế thường handle được 1-2 điểm trong số này. gitops-promoter nhắm đến việc giải quyết tất cả.

Cách gitops-promoter hoạt động

Project này chạy như một Kubernetes controller (theo đúng pattern của Argo ecosystem). Bạn define promotion strategy bằng CRD, và controller sẽ lo phần còn lại.

Core concept có 3 phần chính:

1. Branch-based environments Mỗi môi trường là một branch trong Git repo của bạn, ví dụ environment/dev, environment/staging, environment/prod.

2. Commit Statuses Đây là cơ chế gate. Thay vì hardcode điều kiện promote, bạn dùng commit status (giống như CI status trên GitHub/GitLab) để signal rằng một commit đã sẵn sàng. Controller sẽ watch các status này và chỉ promote khi đủ điều kiện.

3. Pull Request-based promotion Thay vì tự động push thẳng vào branch đích, tool tạo PR. Điều này cho phép bạn có review process, audit trail, và integrate với các SCM workflow sẵn có.

Mình thấy cái approach dùng PR này khá hay. Nó không phải là "automated changes to user-facing files" bạn vẫn thấy được chính xác cái gì đang được promote, và có thể can thiệp nếu cần.

Setup cơ bản

Project hiện đang ở trạng thái experimental, nhưng cấu trúc CRD khá rõ ràng. Đây là một ví dụ PromotionStrategy đầy đủ:

YAML
1apiVersion: promoter.argoproj.io/v1alpha1
2kind: PromotionStrategy
3metadata:
4 name: my-app-promotion
5 namespace: gitops-promoter
6spec:
7 gitRepositoryRef:
8 name: my-app-repo
9 # Commit statuses phải có trên commit đang active (đã deploy)
10 activeCommitStatuses:
11 - key: argocd-app-health
12 # Commit statuses phải có trên commit đang proposed (chưa deploy)
13 proposedCommitStatuses:
14 - key: security-scan
15 environments:
16 - branch: environment/dev
17 - branch: environment/staging
18 - branch: environment/prod
19 autoMerge: false # prod thì require manual approval
20 activeCommitStatuses:
21 - key: performance-test
22 proposedCommitStatuses:
23 - key: deployment-freeze

Bạn cũng cần define GitRepository để controller biết repo nào cần watch:

YAML
1apiVersion: promoter.argoproj.io/v1alpha1
2kind: GitRepository
3metadata:
4 name: my-app-repo
5 namespace: gitops-promoter
6spec:
7 github:
8 domain: github.com
9 owner: my-org
10 name: my-app-config
11 secretRef:
12 name: github-token

Và secret chứa GitHub token:

YAML
1apiVersion: v1
2kind: Secret
3metadata:
4 name: github-token
5 namespace: gitops-promoter
6type: Opaque
7stringData:
8 token: ghp_xxxxxxxxxxxx

Commit Status là trái tim của hệ thống

Phần này mình muốn đi sâu hơn vì nó là điểm khác biệt lớn nhất so với các approach khác.

gitops-promoter phân biệt hai loại commit status:

Sự phân biệt này rất quan trọng. Ví dụ: bạn muốn đảm bảo commit ở dev đã thực sự healthy (active status) trước khi promote lên staging. Đồng thời, commit sắp được đưa vào staging cũng phải pass security scan (proposed status).

LoạiÝ nghĩaVí dụ use case
`activeCommitStatuses`Check trên commit đang **chạy thực tế** ở môi trườngArgoCD app health, smoke test sau deploy
`proposedCommitStatuses`Check trên commit **sắp được promote**Security scan, lint, unit test, deployment freeze check

Các status này được set từ bên ngoài có thể là CI pipeline, có thể là một custom controller khác, hoặc thậm chí là một script đơn giản gọi GitHub API:

Terminal
1# Ví dụ: CI pipeline set commit status sau khi security scan xong
2curl -X POST \
3 -H "Authorization: token $GITHUB_TOKEN" \
4 -H "Accept: application/vnd.github.v3+json" \
5 https://api.github.com/repos/my-org/my-app-config/statuses/$COMMIT_SHA \
6 -d '{
7 "state": "success",
8 "context": "security-scan",
9 "description": "Trivy scan passed - no critical CVEs"
10 }'

Cái hay ở đây là bạn không bị lock in vào bất kỳ CI tool nào. Miễn là có thể set commit status lên GitHub/GitLab, là integrate được.

So sánh với các approach phổ biến

Mình đã thử qua khá nhiều cách handle promotion, đây là góc nhìn thực tế:

Theo kinh nghiệm của mình, điểm yếu lớn nhất của các CI-based approach là chúng không biết gì về trạng thái thực tế của ứng dụng sau khi deploy. Chúng chỉ biết "pipeline đã chạy xong" chứ không biết "app có thực sự healthy không". gitops-promoter với activeCommitStatuses giải quyết đúng vấn đề này.

ApproachƯu điểmNhược điểm
CI pipeline tự push/mergeĐơn giản setup ban đầuFragile, khó debug khi fail, thiếu audit trail
Kustomize + image updaterTự động update image tagChỉ handle image, không handle config changes
Manual PRAn toàn, có reviewChậm, tốn effort, không scale
Flux Image AutomationTích hợp tốt với FluxChỉ dùng được nếu bạn đang dùng Flux
**gitops-promoter**Drift-free, có gate system, PR-basedCòn experimental, cần Kubernetes để chạy

Promotion flow thực tế trông như thế nào

Để hình dung rõ hơn, đây là một flow điển hình:

  1. Developer merge code vào main
  2. CI build image, push lên registry, rồi update environment/dev branch với image tag mới (bước này vẫn do CI làm)
  3. ArgoCD sync environment/dev, deploy lên cluster dev
  4. ArgoCD set argocd-app-health commit status = success khi app healthy
  5. CI set security-scan commit status = success cho commit sắp được promote lên staging
  6. gitops-promoter phát hiện cả hai status đã green → tự động tạo PR từ environment/dev vào environment/staging
  7. PR được auto-merge (hoặc require manual review tùy config)
  8. Lặp lại cho staging → prod, nhưng prod có autoMerge: false nên cần người approve

Anh em lưu ý: bước 2 vẫn cần một cơ chế nào đó để update branch environment/dev gitops-promoter không handle phần "đưa code vào môi trường đầu tiên", nó chỉ handle phần "promote từ môi trường này sang môi trường khác".

Điểm cần cân nhắc trước khi adopt

Mình muốn thành thật: project này vẫn đang ở trạng thái experimental. Đây không phải lý do để bỏ qua, nhưng cần biết để set expectation đúng.

Một số thứ cần cân nhắc:

  • Dependency: Bạn cần một Kubernetes cluster để chạy controller. Nếu team bạn không dùng Kubernetes thì đây không phải lựa chọn phù hợp.
  • Git repo structure: Bạn cần adopt branch-per-environment pattern. Nếu hiện tại bạn đang dùng folder-per-environment trong cùng một branch, sẽ cần refactor.
  • SCM integration: Hiện tại support GitHub và GitLab. Nếu bạn dùng Bitbucket hay Azure DevOps thì cần check lại docs.
  • Learning curve: Concept của activeCommitStatuses vs proposedCommitStatuses cần thời gian để team hiểu và setup đúng.

Mình thấy cái này hay ở chỗ nó không cố gắng làm tất cả mọi thứ. Nó focus vào đúng một bài toán promotion và làm tốt bài toán đó. Các concern khác như "làm sao update image tag", "làm sao chạy test" vẫn là việc của CI pipeline bạn, gitops-promoter chỉ đọc kết quả từ commit status.

Thử local với Tilt

Nếu bạn muốn experiment trước khi commit vào production, project có sẵn Tiltfile để dev locally:

Terminal
1# Clone repo
2git clone https://github.com/argoproj-labs/gitops-promoter
3cd gitops-promoter
4
5# Cần có kind cluster hoặc local k8s
6kind create cluster
7
8# Chạy với Tilt
9tilt up

Repo cũng có webrequestsimulator một tool để simulate các webhook event từ GitHub/GitLab, rất tiện cho việc test mà không cần setup real webhook.

Nhìn tổng thể, gitops-promoter đang giải quyết một bài toán thực sự quan trọng theo một cách có tư duy rõ ràng. Cái concept dùng commit status như một universal gate bất kể status đó đến từ ArgoCD, CI pipeline, hay custom check là một design decision khá elegant. Nó giữ cho controller đơn giản trong khi vẫn flexible với mọi use case.

Nếu team bạn đang dùng ArgoCD và đang đau đầu với promotion workflow, đây là một project đáng để bỏ thời gian evaluate. Mình sẽ tiếp tục theo dõi và có thể sẽ viết thêm khi project stable hơn.

NN

Nguyễn Nhật Long

@nguyennhatlong1303

Nguyễn Nhật Long is a Senior Frontend Engineer and Frontend Team Leader with 7 years of experience building real-time fintech platforms. Specializing in React, Next.js, TypeScript, and React Native, shipping 10+ products across Web, Mobile, Telegram Mini-Apps, and Web3.

Thấy hay? Chia sẻ cho bạn bè!