Lab 1 — GitOps Fundamentals
🎯 Mục tiêu
Sau lab này, bạn sẽ:
- Hiểu GitOps là gì và tại sao Git có thể trở thành Source of Truth.
- Phân biệt được cách deploy truyền thống và deploy theo GitOps.
- Hiểu vai trò của Git Repository, CI, CD và Kubernetes trong GitOps.
- Hiểu khái niệm Desired State và Actual State.
- Tự xây dựng một workflow GitOps đơn giản bằng Kubernetes và Git.
1. 🤔 Vấn đề thực tế
Hãy tưởng tượng bạn đang vận hành một Kubernetes cluster.
Một ngày bình thường, developer yêu cầu:
"Anh deploy version
v1.2.0lên production giúp em."
Bạn có thể làm:
kubectl set image deployment/todo-backend \
todo-backend=myapp:v1.2.0
Kiểm tra:
kubectl rollout status deployment/todo-backend
Mọi thứ có vẻ ổn.
Nhưng vài ngày sau, một vấn đề xảy ra.
Một DevOps Engineer khác chạy:
kubectl set image deployment/todo-backend \
todo-backend=myapp:v1.1.0
Production lại quay về version cũ.
Vấn đề nằm ở đâu?
Kubernetes hiện tại đang chứa trạng thái:
Production Kubernetes
todo-backend
└── image: myapp:v1.1.0
Nhưng Git repository lại ghi:
Git
todo-backend
└── image: myapp:v1.2.0
Hai nơi đang có hai sự thật khác nhau.
Git
│
│ v1.2.0
▼
┌─────────┐
│ ??? │
└─────────┘
▲
│ v1.1.0
│
Kubernetes
Đây chính là một trong những vấn đề GitOps muốn giải quyết.
2. 🧠 GitOps là gì?
GitOps là cách quản lý và vận hành hệ thống trong đó:
Git repository là nơi lưu trạng thái mong muốn của hệ thống.
Thay vì DevOps Engineer trực tiếp thay đổi production bằng:
kubectl apply
kubectl edit
kubectl set image
ta thay đổi configuration trong Git:
Git
│
│ git push
▼
GitOps Repository
│
▼
GitOps Tool
│
▼
Kubernetes
Ví dụ:
Bạn muốn deploy:
myapp:v1.2.0
Thay vì:
kubectl set image ...
Bạn sửa Git:
image: myapp:v1.2.0
Sau đó:
git add .
git commit -m "Deploy myapp v1.2.0"
git push
GitOps tool sẽ phát hiện thay đổi và đưa Kubernetes về trạng thái đó.
3. 🔑 Hai khái niệm quan trọng: Desired State và Actual State
Đây là phần quan trọng nhất để hiểu GitOps.
3.1. 🎯 Desired State
Desired State là trạng thái mà bạn muốn hệ thống có.
Ví dụ Git chứa:
replicas: 3
image: myapp:v1.2.0
Điều đó có nghĩa:
Tôi muốn Kubernetes chạy 3 Pod với image
myapp:v1.2.0.
Đây chính là Desired State.
3.2. ⚙️ Actual State
Actual State là trạng thái thực tế đang chạy trên Kubernetes.
Ví dụ:
Kubernetes
replicas: 3
image: myapp:v1.1.0
Khi đó:
Desired State
image: v1.2.0
≠
Actual State
image: v1.1.0
Có sự khác biệt.
GitOps tool sẽ phát hiện:
Git
Desired State
│
│ compare
▼
┌───────────┐
│ GitOps │
│ Tool │
└─────┬─────┘
│
│ difference
▼
Kubernetes
Actual State
Sau đó nó thực hiện reconciliation.
Reconciliation = đưa Actual State về lại Desired State.
4. 🔄 GitOps hoạt động như thế nào?
Một workflow GitOps cơ bản:
Developer
│
│ git push
▼
┌───────────────┐
│ Git Repository│
│ │
│ Desired State │
└───────┬───────┘
│
│ detect change
▼
┌───────────────┐
│ GitOps Tool │
│ │
│ Compare │
│ Reconcile │
└───────┬───────┘
│
│ apply
▼
┌────────────────┐
│ Kubernetes │
│ │
│ Actual State │
└────────────────┘
Trong các lab tiếp theo, công cụ GitOps chúng ta sử dụng là Argo CD.
5. 🆚 Deploy truyền thống vs GitOps
5.1. 🛠️ Cách truyền thống
DevOps Engineer có thể trực tiếp chạy:
kubectl apply -f deployment.yaml
Hoặc:
kubectl set image ...
Flow:
Developer
│
▼
DevOps Engineer
│
│ kubectl
▼
Kubernetes
Vấn đề:
- Khó biết ai đã thay đổi production.
- Có thể xảy ra thay đổi thủ công ngoài Git.
- Khó audit.
- Khó rollback.
- Git không còn phản ánh chính xác production.
5.2. 🚀 GitOps
Với GitOps:
Developer
│
│ Pull Request
▼
Git Repository
│
│ Change detected
▼
Argo CD
│
│ Sync
▼
Kubernetes
Git trở thành Source of Truth.
Source of Truth là gì?
Hiểu đơn giản:
Đây là nơi chúng ta tin tưởng để biết hệ thống nên ở trạng thái nào.
Ví dụ:
Git
production/
└── deployment.yaml
└── image: myapp:v1.2.0
Nếu Kubernetes đang chạy:
myapp:v1.1.0
thì GitOps tool biết rằng:
Expected: v1.2.0
Actual: v1.1.0
→ OutOfSync
6. 🏗️ Architecture
Một GitOps architecture đơn giản:
Developer
│
│ git push
▼
┌─────────────────┐
│ Git │
│ │
│ Desired State │
└────────┬────────┘
│
│ Watch
▼
┌─────────────────┐
│ Argo CD │
│ │
│ Compare │
│ Sync │
│ Reconcile │
└────────┬────────┘
│
│ Apply
▼
┌─────────────────┐
│ Kubernetes │
│ │
│ Actual State │
│ │
│ ┌─────────────┐ │
│ │ Application │ │
│ └─────────────┘ │
└─────────────────┘
Điểm quan trọng:
Developer không cần SSH vào Kubernetes để thay đổi application.
Thay đổi được thực hiện thông qua Git.
7. 🧪 Thực hành — Mô phỏng GitOps
Trong lab này chúng ta chưa cần Argo CD.
Mục đích là hiểu bản chất GitOps trước, sau đó Lab 3 mới đưa Argo CD vào.
7.1. 📁 Tạo GitOps Repository
Tạo một repository:
mkdir gitops-demo
cd gitops-demo
git init
Tạo cấu trúc:
gitops-demo/
└── app/
└── deployment.yaml
Tạo file:
mkdir app
touch app/deployment.yaml
7.2. 📝 Tạo Desired State
Thêm vào app/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
Ở đây chúng ta đang nói:
Tôi muốn:
Deployment: nginx
Replicas: 2
Image: nginx:1.27
Đây chính là Desired State.
8. 🚀 Deploy Desired State
Apply configuration:
kubectl apply -f app/deployment.yaml
Kiểm tra:
kubectl get deployment nginx
Kết quả mong đợi:
NAME READY UP-TO-DATE AVAILABLE
nginx 2/2 2 2
Kiểm tra image:
kubectl get deployment nginx \
-o jsonpath='{.spec.template.spec.containers[0].image}'
Kết quả:
nginx:1.27
Bây giờ:
Git
Desired State
│
│ apply
▼
Kubernetes
Actual State
replicas = 2
image = nginx:1.27
Hai trạng thái giống nhau.
Desired State == Actual State
✅
9. 💥 Mô phỏng Drift
Đây là phần rất quan trọng.
Giả sử một người nào đó trực tiếp thay đổi production:
kubectl scale deployment nginx --replicas=5
Kiểm tra:
kubectl get deployment nginx
Bạn sẽ thấy:
READY
5/5
Nhưng Git vẫn ghi:
replicas: 2
Chúng ta có:
Git
Desired State
replicas: 2
│
│
│ ≠
▼
Kubernetes
Actual State
replicas: 5
Đây gọi là Drift.
Drift = Actual State đã lệch khỏi Desired State.
10. 🔧 Reconciliation thủ công
Trong GitOps thực tế, Argo CD sẽ phát hiện và xử lý drift.
Nhưng hiện tại chúng ta làm thủ công để hiểu bản chất.
Chạy:
kubectl apply -f app/deployment.yaml
Kiểm tra:
kubectl get deployment nginx
Kết quả:
READY
2/2
Kubernetes đã quay lại:
Desired State
replicas: 2
Đây chính là ý tưởng cốt lõi của GitOps:
Git
Desired State
│
│
▼
Compare State
│
│ Drift?
▼
Reconciliation
│
▼
Kubernetes
Actual State
Argo CD sẽ tự động hóa quá trình này.
11. 🔄 Thay đổi Application bằng Git
Bây giờ hãy thay đổi:
replicas: 2
thành:
replicas: 3
Sau đó:
git add .
git commit -m "Scale nginx to 3 replicas"
Nếu repository đã kết nối với GitHub:
git push
Git bây giờ chứa:
Desired State
replicas: 3
Nhưng Kubernetes vẫn có thể đang chạy:
Actual State
replicas: 2
Argo CD trong các lab sau sẽ nhìn thấy:
Git:
3 replicas
Kubernetes:
2 replicas
→ OutOfSync
Sau đó Argo CD sẽ sync:
2 replicas
│
│ Sync
▼
3 replicas
12. 🧠 Explain → Do → See Result → Understand
Đây là cách bạn nên ghi nhớ GitOps.
Explain
Git chứa:
Desired State
Kubernetes chứa:
Actual State
Do
Thay đổi configuration trong Git:
replicas: 3
See Result
GitOps tool phát hiện:
Desired ≠ Actual
Understand
GitOps tool thực hiện:
Reconciliation
để đưa:
Actual State
↓
Desired State
13. 🧩 GitOps có phải chỉ là "deploy bằng Git" không?
Không.
Đây là một hiểu nhầm rất phổ biến.
Nếu bạn làm:
git push
↓
CI
↓
kubectl apply
thì chưa thể hiện đầy đủ tư duy GitOps.
Điểm quan trọng hơn là:
Git
│
│ Desired State
▼
GitOps Controller
│
│ Continuously compare
▼
Kubernetes
│
│ Actual State
└──────────────┐
│
▼
Reconcile
GitOps thường có một controller liên tục quan sát và reconcile hệ thống.
Argo CD chính là một GitOps controller.
14. 🆚 Push Model và Pull Model
Đây là một concept rất quan trọng khi học GitOps.
14.1. 📤 Push Model
CI/CD pipeline chủ động deploy:
Git
│
▼
CI/CD
│
│ kubectl apply
▼
Kubernetes
Ví dụ:
GitHub Actions
│
│ kubectl
▼
Kubernetes
CI cần quyền truy cập Kubernetes.
14.2. 📥 Pull Model
GitOps thường sử dụng Pull Model:
Git
│
│
▼
Argo CD
│
│ pull / watch
▼
Kubernetes
Argo CD chạy bên trong hoặc gần Kubernetes và chủ động theo dõi Git.
Git
│
│ "Desired State"
▼
Argo CD
│
│ Sync
▼
Kubernetes
Tại sao Pull Model tốt?
CI pipeline không nhất thiết phải giữ Kubernetes credentials để deploy.
Điều này giúp:
- Giảm quyền truy cập từ bên ngoài vào cluster.
- Tách CI và CD.
- Dễ audit.
- Dễ kiểm soát deployment.
- Phù hợp với production environment.
15. 🔐 GitOps và Security
GitOps không tự động làm hệ thống secure.
Nhưng nó giúp tạo ra một boundary tốt hơn.
Ví dụ cách làm không tốt:
GitHub Actions
│
│ kubeconfig
│ admin permission
▼
Production
Nếu GitHub Actions bị compromise, attacker có thể có quyền rất lớn trên cluster.
Một mô hình tốt hơn:
GitHub Actions
│
│ Build / Test
▼
Container Registry
GitOps Repository
│
▼
Argo CD
│
▼
Production
CI không nhất thiết phải có quyền admin trên production cluster.
16. 💡 Kinh nghiệm Production
16.1. 🚫 Không sửa trực tiếp Production
Tránh:
kubectl edit deployment
kubectl set image
kubectl scale
để thay đổi cấu hình lâu dài trong production.
Nếu cần thay đổi:
Change Git
↓
Pull Request
↓
Review
↓
Merge
↓
Argo CD
↓
Production
Bạn vẫn có thể dùng kubectl để debug.
Nhưng:
kubectlnên được xem là công cụ vận hành/debug, không phải nơi lưu Desired State.
16.2. 📝 Mọi thay đổi nên trace được
Một thay đổi production tốt nên có:
Who?
What?
Why?
When?
Ví dụ:
PR #152
Author: Thong
Change: nginx 1.27 → 1.28
Reason: Security update
Review: Approved
Deployment: Argo CD
Sau này nếu có incident, việc điều tra dễ hơn rất nhiều.
16.3. 🔙 Rollback dễ hơn
Nếu Git có:
Commit A
↓
nginx:1.27
Commit B
↓
nginx:1.28
Và version 1.28 có vấn đề:
Revert Commit B
↓
Git
↓
Argo CD
↓
Kubernetes
↓
nginx:1.27
Git trở thành một lịch sử thay đổi của infrastructure/application.
17. 🧪 Bài tập thực hành
Exercise 1 — Deployment
- [ ] Tạo Git repository
gitops-demo. - [ ] Tạo Deployment nginx.
- [ ] Deploy lên Kubernetes.
- [ ] Kiểm tra Desired State và Actual State.
Exercise 2 — Drift
- [ ] Đặt
replicas: 2trong Git. - [ ] Deploy lên Kubernetes.
- [ ] Dùng
kubectl scaleđể tăng lên 5. - [ ] Quan sát sự khác biệt.
- [ ] Apply lại configuration từ Git.
- [ ] Kiểm tra Kubernetes quay về 2 replicas.
Exercise 3 — Git Change
Thay đổi:
replicas: 2
thành:
replicas: 3
Sau đó:
git add .
git commit -m "Scale nginx to 3 replicas"
Quan sát:
Git
replicas: 3
Kubernetes
replicas: 2
Bạn đã tạo ra một Drift theo hướng ngược lại.
Ở các lab sau, Argo CD sẽ tự động xử lý phần này.
18. 🧠 Tổng kết
Nếu chỉ nhớ 5 điều, hãy nhớ:
1️⃣ GitOps không đơn giản là "deploy bằng Git"
Nó là một cách vận hành hệ thống dựa trên:
Git = Desired State
2️⃣ Kubernetes có Actual State
Desired State
≠
Actual State
thì xảy ra Drift.
3️⃣ GitOps Controller thực hiện Reconciliation
Desired State
↓
Compare
↓
Drift?
↓
Reconcile
↓
Actual State
4️⃣ Argo CD là GitOps Controller
Argo CD sẽ theo dõi Git và Kubernetes để giữ cho chúng đồng bộ.
5️⃣ Production nên thay đổi thông qua Git
Thay vì:
kubectl → Production
ưu tiên:
Git
↓
Pull Request
↓
Review
↓
Argo CD
↓
Kubernetes
19. 🚀 Lab tiếp theo
Ở Lab 1, chúng ta mới mô phỏng GitOps bằng tay.
Lab tiếp theo sẽ giải quyết một câu hỏi thực tế:
Nếu một project có Dev, Staging và Production thì nên tổ chức GitOps Repository như thế nào?
Trong Lab 2 — GitOps Repository Structure, chúng ta sẽ xây dựng cấu trúc:
gitops-repo/
├── apps/
│ └── todo-app/
│
├── environments/
│ ├── dev/
│ ├── staging/
│ └── production/
│
└── README.md
và tìm hiểu tại sao việc thiết kế repository ngay từ đầu lại rất quan trọng khi hệ thống bắt đầu có nhiều application và nhiều environment.
All rights reserved