Lab 12 — Image Automation với ArgoCD
🎯 Mục tiêu
Sau Lab này, bạn sẽ:
- Hiểu tại sao GitOps vẫn cần Image Automation.
- Hiểu cách tự động phát hiện Docker Image mới.
- Biết Argo CD Image Updater hoạt động như thế nào.
- Tự động cập nhật image tag trong GitOps repository.
- Hiểu cách kiểm soát version image an toàn trong production.
🤔 1. Vấn đề thực tế
Ở các Lab trước, chúng ta đã có flow:
Developer
│
│ git push
▼
GitHub
│
▼
CI/CD
│
│ docker build
▼
Container Registry
│
│ image: todo-api:v2
▼
GitOps Repository
│
▼
ArgoCD
│
▼
Kubernetes
Ví dụ hôm nay bạn sửa code:
todo-api
v1
│
│ Developer sửa code
▼
v2
CI build image:
todo-api:v2
Nhưng Kubernetes vẫn đang sử dụng:
image: ghcr.io/example/todo-api:v1
Vấn đề là:
Ai sẽ nói cho ArgoCD biết rằng
v2đã tồn tại?
Nếu làm thủ công, Developer/DevOps phải sửa GitOps repository:
image: ghcr.io/example/todo-api:v2
Sau đó:
git commit
git push
ArgoCD mới phát hiện thay đổi.
Với một team lớn, việc này nhanh chóng trở thành công việc lặp đi lặp lại.
Image Automation giải quyết vấn đề này
Thay vì:
Build Image
↓
DevOps sửa YAML
↓
git commit
↓
ArgoCD deploy
Ta muốn:
Build Image
↓
Registry
↓
Image Updater phát hiện version mới
↓
GitOps Repository được cập nhật
↓
ArgoCD
↓
Kubernetes
Đó chính là Image Automation.
🧠 2. Hiểu nhanh
2.1. Image Automation là gì?
Image Automation là quá trình tự động:
phát hiện Docker Image mới → cập nhật version image trong GitOps → để ArgoCD deploy version mới.
Ví dụ:
GitOps Repository
image: todo-api:v1
Registry xuất hiện:
todo-api:v2
Image Updater phát hiện:
v1 → v2
Sau đó cập nhật Git:
image: todo-api:v2
ArgoCD nhìn thấy Git thay đổi và deploy:
Kubernetes
↓
todo-api:v2
2.2. ArgoCD có tự làm việc này không?
Không.
Đây là điểm rất quan trọng.
ArgoCD chủ yếu làm nhiệm vụ:
Git
↓
Compare
↓
Sync
↓
Kubernetes
Nó không mặc định đi tìm Docker Image mới.
Chúng ta cần thêm một thành phần:
Argo CD Image Updater
Nó chịu trách nhiệm theo dõi image trong Container Registry.
🏗️ 3. Architecture
Architecture của Lab này:
┌──────────────────┐
│ Developer │
└────────┬─────────┘
│
git push
│
▼
┌──────────────────┐
│ GitHub CI │
└────────┬─────────┘
│
docker build
│
▼
┌──────────────────┐
│ Container │
│ Registry │
│ │
│ todo-api:v1 │
│ todo-api:v2 │
└────────┬─────────┘
│
detect new image
│
▼
┌──────────────────┐
│ Argo CD Image │
│ Updater │
└────────┬─────────┘
│
update Git
│
▼
┌──────────────────┐
│ GitOps Repository│
│ │
│ image: v2 │
└────────┬─────────┘
│
Git change
│
▼
┌──────────────────┐
│ ArgoCD │
└────────┬─────────┘
│
Sync
│
▼
┌──────────────────┐
│ Kubernetes │
│ │
│ todo-api:v2 │
└──────────────────┘
Hãy nhớ 3 vai trò:
| Thành phần | Nhiệm vụ |
|---|---|
| CI/CD | Build & push Image |
| Image Updater | Phát hiện Image mới và cập nhật Git |
| ArgoCD | Đồng bộ Git → Kubernetes |
🧪 4. Chuẩn bị môi trường
Trong Lab này, chúng ta sử dụng:
Kubernetes
ArgoCD
Argo CD Image Updater
GitHub
GitHub Container Registry (GHCR)
Giả sử GitOps repository có cấu trúc:
gitops-repo/
└── apps/
└── todo-api/
├── deployment.yaml
└── service.yaml
🚀 5. Cài đặt Argo CD Image Updater
5.1. Tại sao cần cài thêm Image Updater?
ArgoCD không tự theo dõi Container Registry.
Image Updater sẽ đứng giữa:
Container Registry
│
▼
Image Updater
│
▼
Git
│
▼
ArgoCD
Cài đặt:
kubectl create namespace argocd-image-updater
Sau đó cài Image Updater bằng manifest chính thức phù hợp với phiên bản bạn đang sử dụng.
Kiểm tra:
kubectl get pods -n argocd-image-updater
Kết quả mong đợi:
NAME READY STATUS
argocd-image-updater-xxxxx 1/1 Running
👀 See Result
Nếu Pod ở trạng thái:
Running
thì Image Updater đã chạy.
🧩 6. Chuẩn bị Application
Trước tiên, ArgoCD cần quản lý application của chúng ta.
Ví dụ:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: todo-api
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/example/gitops-repo.git
targetRevision: main
path: apps/todo-api
destination:
server: https://kubernetes.default.svc
namespace: todo-app
syncPolicy:
automated:
prune: true
selfHeal: true
Application này nói với ArgoCD:
"Hãy lấy configuration từ Git repository và deploy vào Kubernetes."
🔖 7. Khai báo Image cần theo dõi
Đây là phần quan trọng nhất của Lab.
Argo CD Image Updater cần biết:
Application nào và Image nào cần được tự động cập nhật?
Chúng ta khai báo image cần theo dõi bằng annotation trên ArgoCD Application.
Ví dụ:
metadata:
name: todo-api
namespace: argocd
annotations:
argocd-image-updater.argoproj.io/image-list: todo=ghcr.io/example/todo-api
Bây giờ Image Updater biết:
ArgoCD Application: todo-api
↓
Theo dõi:
ghcr.io/example/todo-api
🔄 8. Chọn Strategy cập nhật Image
Không phải cứ thấy image mới là update.
Ví dụ Registry có:
v1.0.0
v1.1.0
v1.2.0
v2.0.0
Chúng ta cần quy định:
"Version nào được phép tự động deploy?"
Đây chính là Update Strategy.
Ví dụ:
latest
↓
digest
↓
semver
↓
name
Trong production, SemVer thường dễ kiểm soát hơn.
Ví dụ:
v1.0.0
v1.1.0
v1.2.0
Cho phép:
v1.x.x
nhưng không tự động nhảy sang:
v2.x.x
Đây là một nguyên tắc rất quan trọng:
Automation tốt không có nghĩa là update tất cả mọi thứ. Automation tốt là automation có giới hạn.
🛠️ 9. Cấu hình Image Updater
Ví dụ:
metadata:
annotations:
argocd-image-updater.argoproj.io/image-list: |
todo=ghcr.io/example/todo-api
argocd-image-updater.argoproj.io/todo.update-strategy: semver
Bây giờ:
Registry
v1.0.0
v1.1.0
v1.2.0
v2.0.0
Image Updater có thể chọn:
v1.2.0
thay vì tự động nhảy lên:
v2.0.0
📦 10. Deploy Version đầu tiên
Giả sử GitOps repository đang chứa:
containers:
- name: todo-api
image: ghcr.io/example/todo-api:v1.0.0
ArgoCD deploy:
todo-api:v1.0.0
Kiểm tra:
kubectl get pods -n todo-app
Bạn sẽ thấy:
todo-api-xxxxx 1/1 Running
Kiểm tra image:
kubectl get pod -n todo-app -o jsonpath="{.items[0].spec.containers[0].image}"
Kết quả:
ghcr.io/example/todo-api:v1.0.0
🧪 11. Tạo Image Version mới
Bây giờ giả lập Developer release version mới.
Build:
docker build -t ghcr.io/example/todo-api:v1.1.0 .
Push:
docker push ghcr.io/example/todo-api:v1.1.0
Registry lúc này:
ghcr.io/example/todo-api
v1.0.0
v1.1.0 ← NEW
👀 12. Image Updater phát hiện Version mới
Image Updater sẽ định kỳ kiểm tra Registry.
Flow:
Image Updater
│
│ Check Registry
▼
Registry
│
├── v1.0.0
└── v1.1.0 ← New
│
▼
Select v1.1.0
Kiểm tra log:
kubectl logs -n argocd-image-updater \
deployment/argocd-image-updater
Bạn sẽ thấy các log liên quan tới việc kiểm tra và cập nhật image.
📝 13. Image Updater cập nhật Git
Đây là điểm quan trọng nhất cần hiểu.
Image Updater không đơn giản chỉ chạy:
kubectl set image ...
Thay vào đó, trong GitOps workflow, chúng ta muốn:
Git
↓
Change
↓
ArgoCD
↓
Kubernetes
Ví dụ ban đầu:
image: ghcr.io/example/todo-api:v1.0.0
Sau automation:
image: ghcr.io/example/todo-api:v1.1.0
GitOps repository trở thành:
main
│
├── Deployment
│ image: v1.1.0
│
└── Service
💡 Tại sao phải cập nhật Git?
Vì Git vẫn phải là:
Source of Truth
Nếu Image Updater chỉ sửa trực tiếp Kubernetes:
Registry
↓
Image Updater
↓
Kubernetes
thì Git không biết Kubernetes đang chạy version nào.
Đó là điều chúng ta không muốn trong GitOps.
🔄 14. ArgoCD tự động Deploy
Git thay đổi:
v1.0.0
↓
v1.1.0
ArgoCD phát hiện:
Git
│
│ Diff
▼
ArgoCD
│
│ Sync
▼
Kubernetes
Kiểm tra:
kubectl get pods -n todo-app
Sau đó:
kubectl get pod -n todo-app \
-o jsonpath="{.items[0].spec.containers[0].image}"
Kết quả:
ghcr.io/example/todo-api:v1.1.0
🎉 Image đã được cập nhật tự động.
🔍 15. Nhìn lại toàn bộ Flow
Bây giờ hãy nhìn lại toàn bộ quá trình:
① Developer
│
│ git push
▼
② GitHub Actions
│
│ docker build
│ docker push
▼
③ Container Registry
│
│ v1.1.0
▼
④ Image Updater
│
│ update Git
▼
⑤ GitOps Repository
│
│ Git change
▼
⑥ ArgoCD
│
│ Sync
▼
⑦ Kubernetes
│
▼
v1.1.0
Đây chính là:
Automated GitOps Deployment
🧠 16. Điều quan trọng cần hiểu
16.1. CI và Image Updater có vai trò khác nhau
Rất dễ nhầm hai thành phần này.
CI/CD
Source Code
↓
Build
↓
Test
↓
Docker Image
↓
Registry
CI trả lời:
"Image mới đã được tạo chưa?"
Image Updater
Registry
↓
Detect new version
↓
Update Git
Image Updater trả lời:
"Có version mới, GitOps repository có cần cập nhật không?"
ArgoCD
Git
↓
Sync
↓
Kubernetes
ArgoCD trả lời:
"Git đang muốn Kubernetes chạy version nào?"
🔐 17. Production: Đừng Auto Update mọi Image
Đây là kinh nghiệm rất quan trọng.
Không nên:
latest
↓
Auto Deploy
Vì:
latest
↓
Có thể thay đổi bất kỳ lúc nào
↓
Production thay đổi ngoài dự kiến
Thay vào đó nên dùng version cụ thể:
v1.2.3
v1.2.4
v1.2.5
hoặc digest:
sha256:xxxxxxxx
⚠️ 18. Một số lỗi thường gặp
❌ Image mới nhưng không được update
Kiểm tra:
kubectl logs -n argocd-image-updater \
deployment/argocd-image-updater
Các nguyên nhân phổ biến:
- Image Updater không truy cập được Registry.
- Image private nhưng chưa cấu hình credentials.
- Annotation sai.
- Strategy không phù hợp.
- Tag mới không thỏa điều kiện SemVer.
❌ Image đã update nhưng Kubernetes chưa thay đổi
Kiểm tra ArgoCD:
Application
↓
Sync Status
↓
Health Status
Có thể Git đã thay đổi nhưng ArgoCD chưa Sync.
Nếu sử dụng:
syncPolicy:
automated:
ArgoCD có thể tự Sync.
❌ Production tự nhiên chạy version mới
Nguyên nhân thường là policy quá rộng.
Ví dụ:
semver
nhưng không giới hạn version phù hợp.
Production nên có policy rõ ràng:
v1.x.x
↓
Auto Update
v2.x.x
↓
Manual Approval
🧪 19. Bài tập thực hành
Exercise 1 — Auto Update
- [ ] Deploy
todo-api:v1.0.0. - [ ] Cấu hình Image Updater.
- [ ] Push
v1.1.0. - [ ] Kiểm tra Image Updater.
- [ ] Kiểm tra Git.
- [ ] Kiểm tra ArgoCD.
- [ ] Kiểm tra Kubernetes.
Flow cần đạt:
v1.0.0
↓
Push v1.1.0
↓
Image Updater
↓
Git
↓
ArgoCD
↓
Kubernetes v1.1.0
Exercise 2 — Test SemVer
Tạo:
v1.2.0
v2.0.0
Cấu hình policy chỉ cho phép:
v1.x.x
Kiểm tra Kubernetes.
Bạn cần chứng minh rằng:
v1.1.0
↓
v1.2.0 ✅ Auto Update
v2.0.0 ❌ Không Auto Update
Exercise 3 — Debug
Cố tình tạo một lỗi:
Image tag không tồn tại
Ví dụ:
image: ghcr.io/example/todo-api:v99.99.99
Sau đó tìm hiểu:
Git
↓
ArgoCD
↓
Kubernetes
đang báo lỗi ở đâu.
Mục tiêu không phải chỉ sửa lỗi, mà phải trả lời được:
"Lỗi xảy ra ở layer nào?"
🏆 20. Production Pattern
Một workflow thực tế có thể giống:
Developer
│
│ Pull Request
▼
GitHub
│
▼
CI
┌──┴─────────────┐
│ Test │
│ Build │
│ Security Scan │
└──────┬─────────┘
│
▼
Container Registry
│
│ New Image
▼
Image Updater
│
│ Git Commit / PR
▼
GitOps Repository
│
▼
ArgoCD
│
▼
Kubernetes
Với production, mình khuyên không nhất thiết cho Image Updater tự commit thẳng vào main.
Một mô hình an toàn hơn:
New Image
↓
Image Updater
↓
Pull Request
↓
Review
↓
Merge
↓
ArgoCD
↓
Production
Như vậy vẫn tự động hóa phần lớn công việc nhưng giữ lại human approval trước Production.
🎯 21. Tổng kết
Sau Lab này, bạn cần nhớ 3 thành phần có 3 nhiệm vụ khác nhau:
┌────────────────────┐
│ CI/CD │
│ Build Image │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ Container Registry │
│ Store Image │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ Image Updater │
│ Detect + Update Git│
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ GitOps Repository │
│ Source of Truth │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ ArgoCD │
│ Sync Git → K8s │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ Kubernetes │
│ Run Application │
└────────────────────┘
Một câu cần nhớ:
🚀 CI tạo Image → Image Updater cập nhật Git → ArgoCD đưa Git vào Kubernetes.
Đó chính là mảnh ghép giúp GitOps chuyển từ "deploy tự động" sang "quản lý version application một cách tự động và có kiểm soát".
All rights reserved