Giao diện
Introduction to GitOps với ArgoCD
🏛️ Góc nhìn Lead Platform Engineer - HPN
Module này được viết với tầm nhìn kiến trúc và chiến lược. Mục tiêu: Biến Git thành nguồn sự thật duy nhất cho toàn bộ hạ tầng Kubernetes.
🎯 Triết Lý: "Git is the Single Source of Truth"
Nguyên tắc cốt lõi
text
📜 GITOPS MANIFESTO
1. Nếu nó không có trong Git → Nó không tồn tại
2. Nếu ai đó sửa trực tiếp trên Cluster → Git sẽ hoàn tác ngay lập tức
3. Mọi thay đổi phải qua Pull Request → Review, Approve, Merge
4. Cluster tự động sync với Git → No manual intervention🚫 ANTI-PATTERN: "ClickOps"
bash
# ❌ SAI: SSH vào server rồi sửa trực tiếp
kubectl edit deployment myapp
kubectl set image deployment/myapp app=myapp:v2
# Hậu quả:
# - Không ai biết ai đã sửa gì
# - Không có audit trail
# - Không thể rollback dễ dàng
# - "Production drift" - Cluster khác với GitSelf-Healing: Sức mạnh của GitOps
Self-Healing: Sức mạnh của GitOps
Git Repository
manifests/
replicas: 3
replicas: 3
ArgoCD monitors
Kubernetes Cluster
Deployment
replicas: 3
replicas: 3
Human (Incident)
kubectl scale --replicas=5
Manual change
ArgoCD
⚠️ Drift detected!
Auto-sync: replicas=3
Kịch bản:
- Git định nghĩa
replicas: 3 - Developer lỡ tay chạy
kubectl scale --replicas=5 - ArgoCD phát hiện drift (Live ≠ Desired)
- ArgoCD tự động sync về
replicas: 3 - Developer: "Tại sao nó cứ quay về 3?" → That's the point!
🔐 Push vs Pull Model: Security Deep Dive
Push Model (Cách cũ - Jenkins, GitLab CI)
Xem diagram so sánh bên dưới
⚠️ RỦI RO CỦA PUSH MODEL
| Vấn đề | Mô tả |
|---|---|
| Credentials exposure | CI Server cần lưu kubeconfig với quyền admin |
| Blast radius | Nếu CI bị hack → Attacker có toàn quyền cluster |
| Network exposure | CI phải có network access đến K8s API |
| No self-healing | Chỉ apply khi có pipeline chạy |
Pull Model (GitOps - ArgoCD, Flux)
Xem diagram so sánh bên dưới
✅ ƯU ĐIỂM CỦA PULL MODEL
| Lợi ích | Mô tả |
|---|---|
| No credentials leak | Không có secret nào rời khỏi cluster |
| Minimal exposure | ArgoCD chỉ cần READ access đến Git |
| Continuous sync | Tự động detect và apply changes |
| Self-healing | Drift được correct ngay lập tức |
| Audit trail | Mọi thay đổi đều có Git commit history |
So sánh trực quan
Push vs Pull Model: Security Comparison
❌ Push Model (Rủi ro cao)
Developer
CI Server
Jenkins/GitLab
kubectl apply
(needs admin creds)
(needs admin creds)
K8s API Server
VS
✅ Pull Model (An toàn)
Developer
Git Repository
Poll every 3m
ArgoCD
Inside Cluster
| Tiêu chí | Push Model | Pull Model |
|---|---|---|
| Credentials | CI cần admin access | Agent trong cluster |
| Direction | CI → Cluster | Cluster ← Git |
| Self-healing | ❌ Không | ✅ Có |
| Audit | CI logs (dễ mất) | Git history (vĩnh viễn) |
| Security | ⚠️ High risk | ✅ Minimal attack surface |
⚙️ ArgoCD: How It Works
Core Concept: Desired State vs Live State
ArgoCD Sync Cycle
Desired State (Git)
/manifests/production/
1Fetch
ArgoCD Controller
2Compare
✅ In Sync
⚠️ Out of Sync
3Sync
Live State (Cluster)
Application Custom Resource
ArgoCD quản lý deployments qua Application CRD:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp-production
namespace: argocd
spec:
project: default
# SOURCE: Lấy manifests từ đâu?
source:
repoURL: https://github.com/hpn/k8s-manifests.git
targetRevision: main
path: apps/myapp/overlays/production
# DESTINATION: Deploy đến đâu?
destination:
server: https://kubernetes.default.svc
namespace: production
# SYNC POLICY: Tự động hay manual?
syncPolicy:
automated:
prune: true # Xóa resources không còn trong Git
selfHeal: true # Tự động fix drift
syncOptions:
- CreateNamespace=trueSync Status
| Status | Ý nghĩa | Action |
|---|---|---|
| Synced ✅ | Live = Desired | Không cần làm gì |
| OutOfSync ⚠️ | Live ≠ Desired | Sync để apply changes |
| Unknown ❓ | Không thể fetch Git | Kiểm tra credentials/network |
| Progressing 🔄 | Đang sync | Chờ hoàn tất |
| Degraded ❌ | Resources unhealthy | Debug application |
🔄 GitOps Workflow
Developer Flow
Developer GitOps Workflow
👨💻
Developer
Developer
📂
Git
Git
🔄
ArgoCD
ArgoCD
☸️
K8s
K8s
1Git commit (Update image tag)
2PR Review & Merge
3Poll for changes (every 3m)
4Detect OutOfSync
5kubectl apply
6Report health status
7Mark as Synced ✅
CI/CD Pipeline Integration
CI/CD Pipeline with GitOps
CI Pipeline
App Code Repo
Build & Test
Push Image
myapp:v1.2.3
CD via GitOps
Update Manifests
Git Manifests
ArgoCD
Kubernetes
Quy trình:
- CI: Build app → Run tests → Push image
myapp:v1.2.3 - CI: Update
values.yamltrong manifests repo với tag mới - GitOps: ArgoCD detect change → Sync → Deploy
🛡️ HPN Production Standard
🚨 QUY ĐỊNH BẮT BUỘC TẠI HPN
text
╔═══════════════════════════════════════════════════════════════╗
║ TỪ NAY, BẠN BỊ CẤM DÙNG `kubectl apply -f` TRONG PRODUCTION ║
║ HÃY ĐỂ ROBOT (ArgoCD) LÀM VIỆC ĐÓ ║
╚═══════════════════════════════════════════════════════════════╝Tại sao?
| Câu hỏi | kubectl apply | GitOps |
|---|---|---|
| "Ai sửa cái này?" | Không biết | Git commit author |
| "Sửa lúc nào?" | Không biết | Git timestamp |
| "Tại sao sửa?" | Không biết | Commit message |
| "Rollback về version trước?" | Tìm file backup đâu? | git revert |
| "Review trước khi deploy?" | Không có | Pull Request |
Quick Start với ArgoCD
bash
# 1. Cài ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 2. Lấy admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
# 3. Port-forward UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# 4. Tạo Application
kubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/hpn/manifests.git
path: apps/myapp
targetRevision: HEAD
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
selfHeal: true
EOF🚀 Advanced Patterns
App of Apps: Bootstrap Pattern
💡 APP OF APPS LÀ GÌ?
Một "Root Application" quản lý nhiều Applications khác. Chỉ cần deploy 1 app, tự động tạo ra toàn bộ infrastructure.
Root Application YAML:
yaml
# apps/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/hpn/k8s-manifests.git
path: apps # 👈 Thư mục chứa các Application YAML
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueDirectory Structure:
text
k8s-manifests/
├── apps/ # 👈 Root App trỏ đến đây
│ ├── frontend.yaml # Application cho frontend
│ ├── backend.yaml # Application cho backend
│ ├── database.yaml # Application cho database
│ └── monitoring.yaml # Application cho monitoring
├── services/
│ ├── frontend/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── backend/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── configmap.yaml
│ └── ...ApplicationSets: Dynamic Application Generation
💡 APPLICATIONSETS LÀ GÌ?
ApplicationSet tự động tạo nhiều Applications từ template + generator. Thay vì viết 10 Application YAML giống nhau, viết 1 ApplicationSet.
Generator Types:
| Generator | Use Case |
|---|---|
| List | Explicit list of clusters/apps |
| Git Directory | Mỗi folder trong repo = 1 app |
| Git File | Config file định nghĩa apps |
| Cluster | Mỗi cluster = 1 app |
| Matrix | Combine multiple generators |
Example: Git Directory Generator
yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-apps
namespace: argocd
spec:
generators:
# 👇 Mỗi folder trong 'services/' = 1 Application
- git:
repoURL: https://github.com/hpn/k8s-manifests.git
revision: main
directories:
- path: services/*
template:
metadata:
# {{path.basename}} = tên folder (frontend, backend, ...)
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/hpn/k8s-manifests.git
path: '{{path}}'
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueResult: Nếu có 5 folders trong services/, ApplicationSet tự động tạo 5 Applications!
Sync Waves & Hooks
📊 SYNC WAVES
Điều khiển thứ tự deploy - resources với wave thấp deploy trước.
yaml
# Wave -1: Namespace và RBAC (deploy ĐẦU TIÊN)
apiVersion: v1
kind: Namespace
metadata:
name: production
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
# Wave 0: ConfigMaps và Secrets (mặc định)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
annotations:
argocd.argoproj.io/sync-wave: "0"
---
# Wave 1: Database (deploy TRƯỚC app)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
annotations:
argocd.argoproj.io/sync-wave: "1"
---
# Wave 2: Application (deploy SAU database)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
argocd.argoproj.io/sync-wave: "2"Sync Hooks:
yaml
# Pre-sync hook: Chạy TRƯỚC khi sync
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: myapp:migrate
command: ["./migrate.sh"]
restartPolicy: Never| Hook | When |
|---|---|
PreSync | Trước khi sync bắt đầu |
Sync | Cùng lúc với resources |
PostSync | Sau khi sync thành công |
SyncFail | Khi sync fail |
⚠️ ArgoCD Production Pitfalls
⚠️ NHỮNG LỖI THƯỜNG GẶP
1. Auto-prune xóa resources quan trọng
yaml
# ❌ NGUY HIỂM: Prune xóa mọi thứ không có trong Git
syncPolicy:
automated:
prune: true # Nếu bạn quên commit PVC → BỊ XÓA!
# ✅ AN TOÀN: Protect specific resources
syncOptions:
- PrunePropagationPolicy=foreground
- PruneLast=true2. SelfHeal undo emergency fixes
text
Scenario:
- Production incident, bạn cần patch nhanh
- kubectl patch deployment/myapp ...
- selfHeal=true → ArgoCD revert lại ngay lập tức!
Giải pháp:
- Tạm disable selfHeal khi incident
- Hoặc commit fix vào Git (đúng cách)3. ApplicationSet tạo infinite Applications
yaml
# ❌ NGUY HIỂM: Không có filter
generators:
- git:
directories:
- path: '*' # Bao gồm cả .git, node_modules, ...!
# ✅ AN TOÀN: Explicit paths
generators:
- git:
directories:
- path: 'services/*'
- path: 'infrastructure/*'4. Secrets trong Git (ngay cả encrypted)
text
Vấn đề: Commit secrets vào Git repo
- Ngay cả khi dùng SealedSecrets, nếu key bị leak → tất cả secrets exposed
Giải pháp:
- Dùng External Secrets Operator
- Hoặc HashiCorp Vault
- KHÔNG bao giờ commit raw secrets✅ ArgoCD Production Checklist
✅ CHECKLIST TRƯỚC KHI PRODUCTION
Security:
- [ ] RBAC configured - không dùng admin account
- [ ] SSO/OIDC enabled (không dùng local users)
- [ ] Secrets KHÔNG được commit vào Git
- [ ] Network policies cho ArgoCD namespace
Reliability:
- [ ] HA mode enabled (3 replicas)
- [ ] Redis cluster cho application controller
- [ ] PodDisruptionBudget configured
- [ ] Resource limits set
Operations:
- [ ] Backup strategy cho ArgoCD (Applications CRDs)
- [ ] Monitoring dashboard (Prometheus/Grafana)
- [ ] Alert rules cho sync failures
- [ ] Disaster recovery plan documented
Best Practices:
- [ ] App of Apps pattern cho organization
- [ ] Sync waves cho complex deployments
- [ ] Health checks customized per app
- [ ] Notification configured (Slack/Teams)
📊 Tổng Kết
| Khái niệm | Mô tả |
|---|---|
| GitOps | Phương pháp dùng Git làm source of truth cho infrastructure |
| Pull Model | Agent trong cluster kéo changes từ Git (an toàn hơn Push) |
| App of Apps | Root Application quản lý nhiều Applications |
| ApplicationSets | Template + Generator = Dynamic Application creation |
| Sync Waves | Điều khiển thứ tự deploy resources |
| Self-Heal | Tự động fix khi có drift |
⚠️ KEY TAKEAWAYS
- Git là vua - Mọi thay đổi phải qua Git commit
- Pull > Push - ArgoCD trong cluster an toàn hơn CI bên ngoài
- App of Apps - Bootstrap pattern cho multi-app environments
- ApplicationSets - Scale với many clusters/apps
- Beware auto-prune - Có thể xóa resources quan trọng
- No more
kubectl apply- Trong Production, hãy để ArgoCD làm
🔗 Liên kết
- Trước đó: Module 12: Helm Charts
- Tiếp theo: Module 14: CI/CD Pipeline