Phần 46 đo Helm và thấy nó không chống được trôi cấu hình. Bài này cài Argo CD lên cụm thật, dựng một kho Git trong cụm, rồi đo hai độ trễ khác hẳn nhau.
Hai độ trễ, chênh nhau gần trăm lần
| Sự kiện | Thời gian tới lúc cụm đổi |
|---|---|
| Commit mới trong Git | 159 giây |
| Ai đó sửa trực tiếp trên cụm | 2,1 / 1,1 / 17,0 giây |
| Xoá hẳn một Deployment Argo quản lý | 2,1 giây |
Chênh lệch này không phải ngẫu nhiên, và nó là toàn bộ mô hình gói trong một câu: Argo CD theo dõi cụm, nhưng quét Git.
Cụm được theo dõi bằng watch — mọi thay đổi đẩy tới ngay lập tức. Git thì không có watch, nên Argo phải hỏi lại theo chu kỳ, mặc định 180 giây.
Kết quả đo 159 giây khớp với con số đó: commit của tôi rơi vào khoảng giữa một chu kỳ.
Hệ quả cho công việc hằng ngày
Người ta hay gặp chuyện này ở lần dùng Argo đầu tiên: đẩy commit, mở giao diện, không thấy gì, tưởng cấu hình sai. Không có gì sai cả — chỉ là chu kỳ 180 giây, và con số đó không hiện ở đâu trong giao diện.
Ba cách xử lý, theo thứ tự nên chọn:
# 1. Webhook từ Git — cách đúng, áp ngay trong vài giây
# Git đẩy POST /api/webhook mỗi khi có commit
# 2. Ép làm mới một ứng dụng
kubectl annotate app <ten> -n argocd argocd.argoproj.io/refresh=hard --overwrite
# 3. Rút ngắn chu kỳ quét — cẩn thận
kubectl patch cm argocd-cm -n argocd --type=merge \
-p '{"data":{"timeout.reconciliation":"60s"}}'
Cách 3 nghe hấp dẫn nhất nhưng đáng cân nhắc nhất: mỗi chu kỳ là một lần Argo clone lại mọi kho của mọi ứng dụng. Với hai chục ứng dụng thì hạ xuống 30 giây là bắt đầu nện vào máy chủ Git. Webhook giải quyết đúng vấn đề đó mà không tốn gì.
selfHeal: nhanh, nhưng có giải lui
Tôi kubectl scale lên 7 bản, và Argo đưa về 3 sau 2,1 giây. Lần hai: 1,1 giây. Lần ba: 17,0 giây.
Lần thứ ba không phải nhiễu. Argo CD có cơ chế giải lui khi phải sửa cùng một thứ nhiều lần liên tiếp — để không đánh nhau vô tận với một bộ điều khiển khác cũng đang ghi vào đối tượng đó.
Đây là hành vi đúng và đáng biết trước, vì nó tạo ra một triệu chứng khó hiểu: selfHeal "chậm dần" ở đúng ứng dụng có xung đột, tức là đúng ứng dụng bạn đang cần nó nhanh nhất.
Xung đột hay gặp nhất là HPA: HPA đặt replicas, Argo đặt lại theo Git, HPA đặt lại. Cách chữa là bảo Argo bỏ qua trường đó:
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers: ["/spec/replicas"]
Xoá một đối tượng thì nó quay lại sau 2 giây
kubectl delete deploy -n dich-vu web
# 2,1 giây sau
web 3/3 3 3 2s
Đây là điều Helm không làm được, đã đo ở phần 46: xoá tay một Service do Helm tạo thì helm status vẫn báo deployed và chẳng có gì dựng lại.
Khác biệt nằm ở chỗ Argo CD là một bộ điều khiển chạy thường trực trong cụm, còn Helm là một lệnh chạy rồi thoát. Đó là toàn bộ lý do người ta ghép Helm với Argo thay vì chọn một trong hai.
Mặt trái, và nó thật: gỡ rối bằng tay không còn hoạt động. Sửa nhanh một tham số để thử nghiệm sẽ bị hoàn tác trong hai giây. Muốn thử thì phải tắt selfHeal, hoặc sửa trong Git — và đó chính là điều GitOps muốn ép bạn làm.
Trạng thái Argo giữ
sync = Synced
health = Healthy
rev = d8db9b097814d3a51a5e59d094dd55ea67ff9c56
rev là mã băm commit thật. Đây là thứ Helm không có: Argo luôn biết cụm đang chạy đúng phiên bản nào của kho mã.
Hai trường sync và health cố ý tách nhau, và phân biệt này đáng nhớ:
Synced= cụm khớp với Git.Healthy= thứ đang chạy thật sự khoẻ.
Chúng độc lập. Một ứng dụng có thể Synced mà Degraded — bạn đã triển khai đúng thứ trong Git, và thứ đó hỏng. Đọc nhầm hai cột này dẫn tới kết luận sai về chỗ cần sửa.
Ba điều nên quyết trước khi bắt đầu
prune: true hay không. Bật thì bỏ tệp khỏi Git là đối tượng bị xoá khỏi cụm — đây chính là thứ Kustomize thiếu ở phần 47. Nhưng nó cũng nghĩa là một lần xoá tệp nhầm sẽ xoá thật. Bật, nhưng dùng Application riêng cho những thứ không được phép mất.
Một kho hay nhiều kho. Một kho cho tất cả thì dễ tìm; nhiều kho thì phân quyền rõ. Argo không ép, nhưng đổi về sau tốn công.
Ai được sửa Git. Sau khi có GitOps, quyền ghi vào kho chính là quyền ghi vào cụm. Phân quyền RBAC trên cụm không còn là chốt chặn duy nhất — và người ta hay quên siết chỗ mới.
Thử ba mươi giây
Xem ứng dụng nào đang lệch khỏi Git, và lệch bao lâu rồi:
kubectl get applications -A -o json | python3 -c '
import sys, json
for a in json.load(sys.stdin)["items"]:
s = a.get("status", {})
sy = s.get("sync", {}).get("status")
he = s.get("health", {}).get("status")
rev = (s.get("sync", {}).get("revision") or "")[:8]
if sy != "Synced" or he != "Healthy":
print("%-28s sync=%-12s health=%-12s rev=%s" % (
a["metadata"]["name"], sy, he, rev))
'
OutOfSync kéo dài nghĩa là có ai đó sửa tay mà selfHeal chưa bật, hoặc có xung đột với một bộ điều khiển khác. Synced nhưng Degraded thì Git đúng còn ứng dụng hỏng — hai chỗ sửa hoàn toàn khác nhau.
Phần sau: các mẫu triển khai — blue/green, canary, và đo cái giá thật của mỗi cách.