Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là kỹ sư vận hành tại một công ty fintech ở TP.HCM. 2 giờ sáng, một dịch vụ thanh toán bị lỗi. Đồng nghiệp của bạn, trong lúc gấp gáp, mở terminal, chạy kubectl edit để sửa trực tiếp cấu hình một service trên cluster production. Dịch vụ hồi phục. Nhưng ba tuần sau, khi cả team deploy phiên bản mới, sự cố tương tự tái diễn — vì bản sửa 2 giờ sáng kia không nằm trong Git, không ai biết nó tồn tại, và nó bị ghi đè. Không có dấu vết, không có lý do, không có ai chịu trách nhiệm rõ ràng.
Đây chính là vấn đề mà GitOps ra đời để giải quyết. Trong các bài trước, bạn đã học về CI/CD (Bài 39) — cách build, test và deploy tự động. Nhưng CI/CD truyền thống thường theo mô hình "push": pipeline chủ động đẩy thay đổi vào cluster bằng lệnh kubectl apply hoặc helm upgrade. Cách này có một điểm yếu chí mạng: không có gì đảm bảo trạng thái thực tế của hệ thống khớp với những gì bạn khai báo trong code. Có ai đó sửa tay? Một pod bị scale thủ công? Một secret bị đổi trực tiếp? Bạn không biết cho đến khi mọi thứ vỡ.
GitOps đảo ngược mô hình đó. Nó biến Git thành nguồn chân lý duy nhất, và để một agent chạy bên trong cluster liên tục so sánh "cái nên có" với "cái đang có", rồi tự động sửa cho khớp. Bài này sẽ giúp bạn hiểu triết lý GitOps, nắm chắc bốn nguyên lý cốt lõi, và biết cách chọn giữa hai công cụ phổ biến nhất: ArgoCD và Flux. Đây là kỹ năng mà hầu hết các đội Platform Engineering hiện đại đều đòi hỏi.
Khái niệm cốt lõi
Định nghĩa GitOps
Thuật ngữ GitOps được Weaveworks đặt ra năm 2017. Định nghĩa kinh điển của họ:
> "Git as the single source of truth for declarative infrastructure and applications." > (Git là nguồn chân lý duy nhất cho hạ tầng và ứng dụng được khai báo theo kiểu declarative.)
Nói cách khác: mọi thứ mô tả hệ thống của bạn — manifests Kubernetes, cấu hình Helm, định nghĩa hạ tầng — đều nằm trong Git. Không ai chạm vào cluster bằng tay. Muốn thay đổi gì, bạn commit vào Git; một agent tự động sẽ áp dụng thay đổi đó.
Bốn nguyên lý của GitOps
Tổ chức OpenGitOps (thuộc CNCF) đã chuẩn hóa GitOps thành bốn nguyên lý. Đây là phần bạn cần thuộc lòng:
1. Declarative (Khai báo). Toàn bộ hệ thống mong muốn được mô tả một cách declarative — nghĩa là bạn khai báo "trạng thái đích", chứ không viết một chuỗi lệnh "làm A rồi làm B". Ví dụ, thay vì viết script "tạo 3 replica", bạn khai báo replicas: 3. Hệ thống tự lo cách đạt được điều đó. Kubernetes vốn được thiết kế theo triết lý này, nên nó và GitOps là một cặp hoàn hảo.
2. Versioned and Immutable (Có phiên bản và bất biến). Trạng thái mong muốn được lưu trong một hệ thống có version — điển hình là Git. Mọi thay đổi đều là một commit mới, có lịch sử đầy đủ, không thể sửa lén quá khứ. Muốn quay lui? Chỉ cần git revert. Toàn bộ lịch sử thay đổi hạ tầng của bạn trở thành một cuốn nhật ký kiểm toán (audit log) miễn phí.
3. Pulled Automatically (Được kéo tự động). Đây là điểm khác biệt lớn nhất so với CI/CD truyền thống. Các software agent tự động kéo (pull) trạng thái mong muốn từ Git về, thay vì được đẩy (push) từ bên ngoài vào. Vì agent chạy bên trong cluster, nó không cần credentials của cluster bị lộ ra ngoài pipeline — an toàn hơn nhiều.
4. Continuously Reconciled (Đối soát liên tục). Agent liên tục quan sát trạng thái thực tế của hệ thống và so sánh với trạng thái mong muốn trong Git. Nếu phát hiện sai lệch (gọi là drift), nó tự động sửa để khớp lại. Đây là vòng lặp đối soát (reconciliation loop) — trái tim của GitOps.
Push model vs Pull model
Hãy làm rõ sự khác biệt này vì nó là bản chất của GitOps.
- Push model (CI/CD truyền thống): Pipeline chạy
kubectl applyđể đẩy thay đổi vào cluster. Vấn đề: pipeline cần giữ credentials của cluster, và không phát hiện được drift sau khi deploy xong. - Pull model (GitOps): Một agent trong cluster tự kéo config từ Git và áp dụng. Credentials không rời khỏi cluster, và agent luôn "canh gác" để sửa mọi sai lệch.
Drift detection và self-healing
Giả sử ai đó chạy kubectl scale deployment payment --replicas=1 trên production. Với GitOps, trong Git bạn vẫn khai báo replicas: 3. Agent phát hiện thực tế (1) khác với mong muốn (3), và tự động scale lại về 3. Đây là self-healing — hệ thống tự chữa lành. Chính cơ chế này ngăn chặn thảm họa "sửa tay 2 giờ sáng" mà chúng ta nói ở đầu bài.
ArgoCD và Flux — hai người khổng lồ
Cả hai đều là dự án tốt nghiệp (graduated) của CNCF, đều triển khai đầy đủ bốn nguyên lý GitOps, nhưng có triết lý thiết kế khác nhau:
ArgoCD (do Intuit và Akuity phát triển) thiên về trải nghiệm người dùng. Nó có một web UI trực quan rất mạnh, cho phép bạn nhìn thấy cây tài nguyên (application tree), trạng thái sync, so sánh diff giữa Git và cluster một cách sinh động. Nó xoay quanh khái niệm Application — một CRD (Custom Resource Definition) mô tả "kéo repo nào, path nào, deploy vào namespace nào". Rất phù hợp cho đội cần nhiều người (kể cả developer không rành hạ tầng) cùng quan sát.
Flux (do Weaveworks tạo ra, nay do cộng đồng duy trì) thiên về kiến trúc mô-đun và "cách làm Kubernetes thuần túy". Flux gồm một bộ controller nhỏ (source-controller, kustomize-controller, helm-controller, notification-controller...) hoạt động theo triết lý Unix "mỗi thứ làm tốt một việc". Flux không có UI mặc định mạnh như ArgoCD, nhưng cực kỳ nhẹ, dễ tích hợp, và được nhiều nền tảng lớn (như bản thân dịch vụ AKS của Azure) tích hợp sẵn. Flux cũng nổi tiếng với khả năng tự động cập nhật image (image automation).
Nguyên tắc chọn đơn giản: cần UI đẹp, nhiều người xem, quản lý tập trung nhiều cluster → ArgoCD; cần nhẹ, mô-đun, GitOps thuần theo phong cách Kubernetes, tự động hóa image → Flux.
Tình huống thực tế
Ví dụ 1: Startup thương mại điện tử ở Hà Nội chuyển sang ArgoCD
Một startup TMĐT khoảng 40 kỹ sư ở Hà Nội chạy 25 microservice trên Kubernetes. Ban đầu họ deploy bằng Jenkins pipeline chạy helm upgrade. Mỗi lần deploy, developer phải nhớ chạy đúng lệnh với đúng tham số, và không ai biết chắc production đang chạy phiên bản nào của mỗi service.
Sự cố xảy ra vào một đợt sale lớn: một service giỏ hàng bị một kỹ sư sửa resources.limits trực tiếp bằng kubectl edit để "cứu" tình thế, quên không commit. Ba ngày sau, một deploy thường lệ ghi đè bản sửa đó, service crash vì thiếu memory ngay giữa giờ cao điểm, gây gián đoạn 18 phút.
Họ chuyển sang ArgoCD. Mỗi service thành một ArgoCD Application trỏ tới một Git repo. Web UI của ArgoCD hiển thị màu xanh (Synced) hoặc vàng (OutOfSync) cho từng service. Khi ai đó sửa tay, UI lập tức hiện "OutOfSync" và ArgoCD tự sync lại về đúng Git. Kết quả sau 3 tháng: số sự cố do config drift giảm về gần như bằng không, và thời gian rollback từ trung bình 15 phút xuống còn khoảng 2 phút (chỉ cần git revert rồi ArgoCD tự áp dụng).
Bài học: ArgoCD tỏa sáng khi bạn cần khả năng quan sát trực quan cho một đội đông, và khi drift do "sửa tay" là nỗi đau chính.
Ví dụ 2: Nền tảng logistics Đông Nam Á dùng Flux cho multi-tenant
Một nền tảng logistics phục vụ nhiều nước Đông Nam Á có mô hình multi-tenant: mỗi quốc gia (Việt Nam, Thái Lan, Indonesia) chạy trên một cluster riêng, cấu hình gần giống nhau nhưng khác vài tham số vùng miền. Đội Platform chỉ có 6 người phải quản lý cả chục cluster.
Họ chọn Flux vì hai lý do. Thứ nhất, Flux kết hợp cực tốt với Kustomize để tái sử dụng cấu hình chung (base) và chỉ overlay phần khác biệt cho từng vùng — tránh copy-paste. Thứ hai, Flux có image automation: khi CI build xong một image mới và push lên registry với tag theo quy ước (ví dụ semver), Flux tự phát hiện, cập nhật manifest trong Git và deploy — không cần con người can thiệp. Với đội chỉ 6 người quản 10+ cluster, mức độ tự động này là sống còn.
Họ tổ chức theo mô hình "hub-and-spoke": một repo trung tâm chứa base config, mỗi cluster có một Flux GitRepository và các Kustomization overlay riêng. Khi cần vá lỗi bảo mật cho toàn bộ, họ chỉ sửa một chỗ ở base; Flux ở tất cả cluster tự kéo về. Một lần vá lỗ hổng nghiêm trọng, họ triển khai đồng loạt lên cả 10 cluster trong vòng chưa đầy 5 phút chỉ bằng một commit.
Bài học: Flux phù hợp cho môi trường nhiều cluster, đội nhỏ, cần tự động hóa cao và kiến trúc mô-đun. UI không phải ưu tiên hàng đầu của họ — họ quan sát qua Grafana và cảnh báo qua Slack.
Ví dụ 3: Cái bẫy "GitOps nhưng vẫn sửa tay"
Một công ty SaaS giả định tên VietCloud đã cài ArgoCD nhưng vẫn cho phép kỹ sư dùng kubectl apply trực tiếp trong tình huống khẩn cấp, và họ tắt tính năng auto-sync để "cho an toàn". Kết quả: họ có ArgoCD nhưng không có GitOps thật sự. Cluster đầy drift, ArgoCD hiển thị hàng loạt service "OutOfSync" mà không ai bấm sync. Sau vài tháng, không ai còn tin vào những gì Git nói nữa — vì Git và thực tế đã lệch nhau quá xa.
Họ phải làm một đợt "reset": khóa quyền kubectl write trên production (chỉ để read), bật auto-sync với selfHeal: true và prune: true, và tạo một quy trình khẩn cấp chính thức là "commit hotfix vào một branch, merge nhanh, để ArgoCD deploy" thay vì sửa tay.
Bài học: GitOps không phải là công cụ, mà là kỷ luật. Cài ArgoCD hay Flux mà vẫn sửa tay thì bạn chỉ có ảo giác GitOps. Nguyên lý "Git là nguồn chân lý duy nhất" phải được thực thi bằng cả quyền hạn (RBAC) lẫn văn hóa đội.
Hướng dẫn từng bước
Dưới đây là quy trình thiết lập GitOps cơ bản với ArgoCD (Flux tương tự về tinh thần, khác về cú pháp):
Bước 1 — Tách repo config khỏi repo code. Đây là thực hành quan trọng nhất. Bạn nên có repo ứng dụng (source code) riêng và repo config (manifests/Helm/Kustomize) riêng. Lý do: khi CI build xong image, nó chỉ cần cập nhật tag image trong repo config, không làm rối lịch sử của repo code. Tách biệt cũng giúp phân quyền rõ ràng hơn.
Bước 2 — Cài đặt agent GitOps vào cluster. Với ArgoCD, bạn tạo namespace argocd và apply manifest cài đặt. Agent này sẽ chạy thường trực trong cluster, đóng vai trò "người canh gác".
Bước 3 — Định nghĩa Application (hoặc Kustomization với Flux). Bạn khai báo một CRD trỏ tới repo config: repo nào, đường dẫn (path) nào, branch nào, deploy vào cluster/namespace nào. Ví dụ với ArgoCD, một Application sẽ chỉ định repoURL, path, targetRevision và destination.
Bước 4 — Bật auto-sync và self-heal. Trong cấu hình syncPolicy, bật automated với selfHeal: true (tự sửa drift) và prune: true (tự xóa tài nguyên đã bị gỡ khỏi Git). Đây là bước biến GitOps từ "thủ công" thành "tự động thật sự".
Bước 5 — Khóa quyền truy cập trực tiếp. Dùng RBAC của Kubernetes để hạn chế quyền write trực tiếp lên cluster production. Con đường duy nhất để thay đổi production phải là qua Git. Đây là bước thực thi kỷ luật.
Bước 6 — Thiết lập vòng lặp thay đổi chuẩn. Từ nay, mọi thay đổi đi theo luồng: developer tạo pull request vào repo config → được review và merge → agent GitOps tự kéo về và áp dụng → quan sát trạng thái sync. Muốn rollback? git revert commit lỗi.
Bước 7 — Cấu hình thông báo và quan sát. Tích hợp cảnh báo (qua Slack, Telegram, email) khi sync thất bại hoặc phát hiện drift kéo dài. Với đội Việt Nam, tích hợp Telegram bot để báo trạng thái sync là một lựa chọn rất phổ biến.
Lỗi thường gặp & mẹo
Lỗi 1 — Để chung code và config trong một repo, gây vòng lặp CI vô tận. Khi CI cập nhật tag image ngay trong repo code, commit đó lại kích hoạt CI chạy tiếp, tạo vòng lặp. Mẹo: tách repo config riêng, và cấu hình CI bỏ qua các commit tự động (dùng [skip ci] hoặc lọc theo path).
Lỗi 2 — Tắt auto-sync vì sợ. Nhiều đội mới bật GitOps nhưng để sync thủ công. Điều này khiến drift tích tụ và mất niềm tin vào Git. Mẹo: bật auto-sync với self-heal ngay từ đầu ở môi trường staging để làm quen, rồi mới đưa lên production.
Lỗi 3 — Lưu secret dạng plaintext trong Git. GitOps đòi mọi thứ nằm trong Git, nhưng bạn TUYỆT ĐỐI không được commit secret dạng thô. Mẹo: dùng công cụ mã hóa như Sealed Secrets hoặc SOPS để commit secret đã mã hóa; agent sẽ giải mã trong cluster. (Bài 33 về Secret Management sẽ đào sâu chủ đề này.)
Lỗi 4 — Không xử lý drift do controller khác gây ra. Một số công cụ (như Horizontal Pod Autoscaler) chủ động thay đổi replicas. Nếu bạn cũng khai báo replicas trong Git, hai bên sẽ "đánh nhau". Mẹo: bỏ trường replicas khỏi manifest và dùng cấu hình ignoreDifferences để agent bỏ qua trường đó.
Lỗi 5 — Đối xử với GitOps như một sản phẩm cài-là-xong. GitOps là văn hóa. Mẹo: viết runbook rõ ràng cho quy trình hotfix khẩn cấp qua Git, và đào tạo cả đội — kể cả trong tình huống 2 giờ sáng, con đường vẫn phải là commit, không phải kubectl.
Mẹo chọn công cụ nhanh: Nếu đội có nhiều developer cần nhìn dashboard và bạn ưu tiên trải nghiệm quan sát → ArgoCD. Nếu bạn quản lý nhiều cluster, đội nhỏ, cần tự động hóa image và kiến trúc mô-đun → Flux. Cả hai đều tốt; đừng tranh cãi vô ích, hãy chọn theo bối cảnh đội bạn.
Bài tập thực hành
- Thiết lập GitOps cơ bản. Dùng một cluster local (minikube hoặc kind), cài ArgoCD, tạo một Git repo chứa manifest cho một ứng dụng đơn giản (ví dụ một web nginx với 3 replica). Tạo một
Applicationtrỏ tới repo đó, bật auto-sync. Xác nhận ứng dụng được deploy tự động.
- Thử nghiệm self-healing. Chạy
kubectl scale deployment <tên> --replicas=1để tạo drift thủ công. Quan sát ArgoCD phát hiện OutOfSync và tự sửa về 3 replica. Ghi lại thời gian từ lúc bạn sửa tay đến lúc agent chữa lành.
- Thực hành rollback. Commit một thay đổi sai (ví dụ đổi image sang một tag không tồn tại) để service lỗi. Sau đó dùng
git revertvà quan sát agent tự khôi phục về phiên bản tốt. So sánh cảm giác này với việc rollback thủ công bằng lệnh.
- So sánh hai công cụ. Cài thêm Flux trên một cluster khác, deploy cùng ứng dụng đó. Viết một ghi chú nửa trang so sánh trải nghiệm: điểm nào ArgoCD tiện hơn, điểm nào Flux gọn hơn, và với bối cảnh đội bạn (số người, số cluster) thì bạn sẽ chọn cái nào và vì sao.
- Thiết kế quy trình khẩn cấp. Viết một runbook ngắn (nửa trang) mô tả cách xử lý sự cố production 2 giờ sáng trong mô hình GitOps mà KHÔNG được sửa tay. Nêu rõ các bước: tạo hotfix branch, merge nhanh, để agent deploy, và cách theo dõi.
Tóm tắt
GitOps là mô hình vận hành trong đó Git là nguồn chân lý duy nhất cho hạ tầng và ứng dụng được khai báo theo kiểu declarative. Nó dựa trên bốn nguyên lý: Declarative (khai báo), Versioned & Immutable (có phiên bản, bất biến), Pulled Automatically (kéo tự động), và Continuously Reconciled (đối soát liên tục).
Điểm khác biệt cốt lõi so với CI/CD truyền thống là mô hình pull thay vì push: một agent chạy trong cluster tự kéo config từ Git, liên tục so sánh trạng thái thực tế với mong muốn, và tự sửa mọi sai lệch (drift) — cơ chế self-healing giúp ngăn thảm họa "sửa tay quên commit".
Hai công cụ hàng đầu là ArgoCD (mạnh về UI, phù hợp đội đông, quan sát trực quan) và Flux (nhẹ, mô-đun, mạnh về tự động hóa image và multi-cluster). Cả hai đều là dự án graduated của CNCF. Chọn theo bối cảnh đội, không theo trào lưu.
Quan trọng nhất: GitOps là kỷ luật, không chỉ là công cụ. Cài ArgoCD hay Flux mà vẫn sửa tay thì bạn chỉ có ảo giác GitOps. Hãy khóa quyền write trực tiếp, bật auto-sync với self-heal, và biến Git thành con đường duy nhất để chạm vào production.