0

Lab 21 — Final Project: Production GitOps Platform với ArgoCD

🎯 1. Mục tiêu

Sau Lab này, bạn sẽ tự xây dựng được một quy trình GitOps hoàn chỉnh:

  • Hiểu cách CI/CD và GitOps phối hợp với nhau.
  • Dùng Git làm Source of Truth cho Kubernetes.
  • Dùng GitHub Actions để build và push Docker Image.
  • Dùng ArgoCD để tự động deploy Application lên Kubernetes.
  • Quản lý devproduction bằng GitOps.
  • Thiết lập Auto Sync, Self-Healing và Rollback.
  • Kết nối GitOps với Prometheus + Grafana để quan sát hệ thống.
  • Biết cách debug một deployment GitOps khi production gặp sự cố.

🤔 2. Vấn đề thực tế

Ở những Lab trước, chúng ta đã biết cách deploy Kubernetes:

kubectl apply -f deployment.yaml

Cách này rất dễ học.

Nhưng hãy tưởng tượng bạn đang làm production.

Developer push code:

Developer
    │
    │ git push
    ▼
GitHub

Docker Image được build:

app:v1.0.0

Sau đó bạn phải SSH vào server hoặc chạy:

kubectl set image deployment/backend \
    backend=my-registry/backend:v1.0.0

Vài ngày sau có 10 services.

Một tháng sau có:

dev
staging
production

Lúc này việc deploy thủ công bắt đầu trở thành vấn đề.


😵 2.1. Những vấn đề sẽ xuất hiện

1. Không biết production đang chạy version nào

Bạn phải nhớ:

Backend → v1.3.2
Frontend → v2.1.0
Worker → v1.8.4

2. Configuration dễ bị lệch

Git nói:

replicas: 3

Nhưng Kubernetes thực tế lại là:

replicas: 5

3. Khó audit

Ai đã deploy?

Deploy lúc nào?

Deploy version nào?

Tại sao deployment thay đổi?

4. Rollback khó

Nếu version mới lỗi, bạn phải nhớ version cũ và tự chạy command rollback.


🧠 3. GitOps giải quyết vấn đề như thế nào?

GitOps thay đổi một nguyên tắc rất quan trọng:

Git không chỉ lưu source code. Git còn lưu trạng thái mong muốn của hệ thống.

Ví dụ:

Git
│
├── frontend
│   └── image: frontend:v1.2.0
│
├── backend
│   └── image: backend:v1.5.0
│
└── production
    └── replicas: 3

Git trở thành:

Source of Truth

ArgoCD liên tục so sánh:

Git
Desired State
    │
    │ compare
    ▼
Kubernetes
Actual State

Nếu khác nhau:

Git:
replicas = 3

Kubernetes:
replicas = 1

ArgoCD phát hiện:

OUT OF SYNC

và có thể tự động sửa lại.

Đó chính là Self-Healing.


🧠 4. Hiểu nhanh Architecture

Trong Final Project này, chúng ta xây dựng flow:

                    ┌──────────────────┐
                    │    Developer     │
                    └────────┬─────────┘
                             │
                         git push
                             │
                             ▼
                    ┌──────────────────┐
                    │     GitHub       │
                    │  Application     │
                    │      Repo        │
                    └────────┬─────────┘
                             │
                             │ CI
                             ▼
                    ┌──────────────────┐
                    │ GitHub Actions   │
                    │                  │
                    │ Test             │
                    │ Build Image      │
                    │ Push Registry    │
                    └────────┬─────────┘
                             │
                             │ update image tag
                             ▼
                    ┌──────────────────┐
                    │ GitOps Repository│
                    │                  │
                    │ dev/             │
                    │ production/      │
                    └────────┬─────────┘
                             │
                             │ watch Git
                             ▼
                    ┌──────────────────┐
                    │      ArgoCD      │
                    │                  │
                    │ Sync              │
                    │ Self-Healing      │
                    │ Rollback          │
                    └────────┬─────────┘
                             │
                             │ deploy
                             ▼
              ┌──────────────────────────────┐
              │       Kubernetes Cluster    │
              │                              │
              │  ┌────────┐   ┌────────┐   │
              │  │Frontend│   │ Backend│   │
              │  └────────┘   └────────┘   │
              │                              │
              └──────────────┬───────────────┘
                             │
                             │ metrics
                             ▼
                    ┌──────────────────┐
                    │ Prometheus       │
                    │ Grafana          │
                    └──────────────────┘

Điểm quan trọng nhất:

Developer
   ↓
GitHub
   ↓
CI
   ↓
Docker Image
   ↓
GitOps Repo
   ↓
ArgoCD
   ↓
Kubernetes

CI tạo artifact.

GitOps quyết định version nào được deploy.

ArgoCD thực hiện deployment.


🏗️ 5. Chuẩn bị môi trường

5.1. Kiến trúc Lab

Chúng ta sử dụng:

macOS
 │
 ├── Docker
 │
 └── Minikube
       │
       ├── ArgoCD
       │
       ├── Todo Frontend
       │
       ├── Todo Backend
       │
       ├── PostgreSQL
       │
       └── Monitoring
            ├── Prometheus
            └── Grafana

Bạn có thể dùng Minikube giống các Lab Kubernetes trước.

Kiểm tra:

kubectl get nodes

Kết quả mong đợi:

NAME       STATUS   ROLES           AGE
minikube   Ready    control-plane   ...

Kiểm tra ArgoCD:

kubectl get pods -n argocd

Nếu chưa cài ArgoCD, cài:

kubectl create namespace argocd
kubectl apply \
  -n argocd \
  -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Chờ các Pod chạy:

kubectl get pods -n argocd

📁 6. Thiết kế GitOps Repository

🤔 Tại sao phải tách GitOps Repository?

Một sai lầm phổ biến của người mới là đặt tất cả vào một repository:

my-app/
├── src/
├── Dockerfile
├── package.json
├── deployment.yaml
└── service.yaml

Điều này vẫn chạy được.

Nhưng khi hệ thống lớn hơn, việc tách:

Application Code

và:

Deployment Configuration

sẽ dễ quản lý hơn.

Chúng ta tạo:

todo-app/

và:

todo-app-gitops/

📂 7. Cấu trúc GitOps Repository

Chúng ta sử dụng Kustomize:

todo-app-gitops/
│
├── base/
│   ├── namespace.yaml
│   ├── backend-deployment.yaml
│   ├── backend-service.yaml
│   ├── frontend-deployment.yaml
│   ├── frontend-service.yaml
│   ├── postgres-deployment.yaml
│   ├── postgres-service.yaml
│   └── kustomization.yaml
│
└── overlays/
    │
    ├── dev/
    │   ├── kustomization.yaml
    │   └── patch.yaml
    │
    └── production/
        ├── kustomization.yaml
        └── patch.yaml

Ý tưởng:

                 base
                  │
          ┌───────┴────────┐
          ▼                ▼
         dev           production

base chứa cấu hình chung.

overlay chứa khác biệt của từng environment.


🧩 8. Tạo Base

8.1. base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - namespace.yaml
  - backend-deployment.yaml
  - backend-service.yaml
  - frontend-deployment.yaml
  - frontend-service.yaml
  - postgres-deployment.yaml
  - postgres-service.yaml

Kustomize sẽ gom các Kubernetes Manifest thành một Application.


🧩 9. Tạo Environment Dev

Tạo:

overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: todo-dev

resources:
  - ../../base

Dev sử dụng cấu hình từ base.

Sau này chúng ta có thể override:

replicas
image
resources
environment variables

mà không cần copy toàn bộ manifest.


🏭 10. Tạo Environment Production

Tạo:

overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: todo-production

resources:
  - ../../base

Bây giờ repository có:

base
 │
 ├── dev
 │
 └── production

🔍 11. Kiểm tra trước khi deploy

Đây là một thói quen rất quan trọng trong production.

Không nên commit Kubernetes Manifest mà chưa biết nó generate ra cái gì.

Chạy:

kubectl kustomize overlays/dev

Nếu muốn kiểm tra production:

kubectl kustomize overlays/production

Bạn sẽ thấy toàn bộ Kubernetes Manifest sau khi Kustomize render.


🚀 12. Tạo ArgoCD Application

🤔 Tại sao cần Application?

ArgoCD cần biết:

"Tôi phải lấy configuration ở đâu và deploy vào Kubernetes nào?"

ArgoCD Application chính là object mô tả điều đó.

Tạo:

argocd/todo-dev.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application

metadata:
  name: todo-dev
  namespace: argocd

spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/todo-app-gitops.git
    targetRevision: main
    path: overlays/dev

  destination:
    server: https://kubernetes.default.svc
    namespace: todo-dev

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Thay:

YOUR_USERNAME

bằng GitHub username của bạn.


🧠 13. Hiểu syncPolicy

Đây là phần rất quan trọng.

syncPolicy:
  automated:
    prune: true
    selfHeal: true

Có thể hiểu:

Git
 │
 │ desired state
 ▼
ArgoCD
 │
 ├── Difference?
 │       │
 │       └── YES
 │            │
 │            ▼
 │          Sync
 │
 ├── Resource deleted?
 │       │
 │       └── prune
 │
 └── Kubernetes changed manually?
         │
         └── selfHeal

automated

Cho phép ArgoCD tự động Sync.

prune

Nếu resource đã bị xóa khỏi Git:

Git:
Deployment
Service

Sau đó Git chỉ còn:

Service

ArgoCD có thể xóa Deployment khỏi Kubernetes.

selfHeal

Nếu ai đó chạy:

kubectl scale deployment backend --replicas=10

trong khi Git quy định:

replicas = 3

ArgoCD sẽ phát hiện drift và đưa hệ thống về trạng thái trong Git.


🚀 14. Deploy Application bằng ArgoCD

Apply Application:

kubectl apply -f argocd/todo-dev.yaml

Kiểm tra:

kubectl get applications -n argocd

Bạn sẽ thấy:

NAME       SYNC STATUS   HEALTH STATUS
todo-dev   Synced        Healthy

Kiểm tra namespace:

kubectl get all -n todo-dev

👀 15. Xem ArgoCD UI

Lấy password:

kubectl -n argocd \
  get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 --decode

Port-forward:

kubectl port-forward svc/argocd-server \
  -n argocd 8080:443

Mở:

https://localhost:8080

Đăng nhập:

Username:
admin

Password:

<password lấy ở trên>

Bạn sẽ thấy:

todo-dev
   │
   ├── Synced
   └── Healthy

🧪 16. Test GitOps — Thay đổi Application

Đây mới là phần quan trọng nhất của Lab.

Giả sử hiện tại Backend:

replicas: 1

Thay đổi GitOps:

replicas: 2

Commit:

git add .
git commit -m "scale backend to 2 replicas"
git push

👀 17. See Result

Kiểm tra ArgoCD.

Bạn sẽ thấy:

Git
replicas: 2
       │
       ▼
    ArgoCD
       │
       ▼
Kubernetes
replicas: 2

Kiểm tra:

kubectl get pods -n todo-dev

Có thể thấy:

backend-xxxxx   Running
backend-yyyyy   Running

Bạn vừa thực hiện deployment mà không chạy kubectl apply.

Đó chính là GitOps.


🔥 18. Test Self-Healing

Bây giờ thử cố tình thay đổi Kubernetes bằng tay.

Ví dụ:

kubectl scale deployment backend \
  -n todo-dev \
  --replicas=5

Kiểm tra:

kubectl get deployment -n todo-dev

Bạn sẽ thấy:

READY
5/5

Nhưng Git vẫn nói:

replicas: 2

ArgoCD phát hiện:

Desired State = 2
Actual State  = 5

Sau một khoảng thời gian, ArgoCD sẽ đưa hệ thống trở về:

2 replicas

Kiểm tra:

kubectl get deployment -n todo-dev

🧠 19. Điều gì vừa xảy ra?

Bạn vừa thấy một trong những điểm mạnh nhất của GitOps:

          Git
           │
      Desired = 2
           │
           ▼
        ArgoCD
           │
     compare state
           │
           ▼
     Kubernetes
     Actual = 5
           │
           │ drift
           ▼
        Self-Heal
           │
           ▼
     Actual = 2

Điều này đặc biệt hữu ích trong production.

Nếu một người vô tình thay đổi production bằng:

kubectl edit

GitOps có thể phát hiện và sửa lại.


🔄 20. Test Rollback

Giả sử production đang chạy:

backend:v1.0.0

Bạn release:

backend:v1.1.0

Nhưng version mới có bug.

Git history:

commit A
backend:v1.0.0

commit B
backend:v1.1.0

Rollback rất đơn giản:

git revert <commit-B>

Sau đó:

git push

Flow:

Git
 │
 │ revert
 ▼
ArgoCD
 │
 │ Sync
 ▼
Kubernetes
 │
 ▼
backend:v1.0.0

Đây là một cách rollback rất đẹp vì:

Rollback cũng được thực hiện thông qua Git.


🔐 21. GitOps Secrets

Một vấn đề bắt đầu xuất hiện:

Chúng ta có:

DATABASE_PASSWORD
JWT_SECRET
API_KEY

Không được commit:

password: my-secret-password

vào Git.

Trong production, bạn có thể sử dụng:

External Secrets

hoặc:

Sealed Secrets

hoặc secret manager như:

AWS Secrets Manager
HashiCorp Vault
Google Secret Manager
Azure Key Vault

Mô hình:

Git
 │
 │ reference
 ▼
Secret Manager
 │
 │ secret
 ▼
Kubernetes Secret
 │
 ▼
Application

Điểm cần nhớ:

GitOps không có nghĩa là commit plaintext secrets vào Git.


⚙️ 22. Kết nối CI với GitOps

Bây giờ chúng ta hoàn thiện pipeline.

Developer sửa code:

src/

Push:

git push

GitHub Actions chạy:

Test
  ↓
Build
  ↓
Docker Image
  ↓
Push Registry

Ví dụ:

backend:v1.2.0

Sau đó CI cập nhật GitOps repository:

image: backend:v1.2.0

ArgoCD phát hiện Git thay đổi:

GitOps Repo
     │
     ▼
   ArgoCD
     │
     ▼
 Kubernetes

🔄 23. Full CI/CD + GitOps Flow

Đây là flow bạn nên nhớ sau Final Project:

Developer
    │
    │ git push
    ▼
┌──────────────┐
│   GitHub     │
│ Application  │
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│ GitHub Actions   │
│                  │
│ Test             │
│ Build            │
│ Docker Push      │
└────────┬─────────┘
         │
         │ image:v1.2.0
         ▼
┌──────────────────┐
│ GitOps Repository│
│                  │
│ image:v1.2.0     │
└────────┬─────────┘
         │
         │ Git change
         ▼
┌──────────────────┐
│     ArgoCD       │
│                  │
│ Detect Diff      │
│ Sync             │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│   Kubernetes     │
│                  │
│ backend:v1.2.0   │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Prometheus       │
│ Grafana          │
└──────────────────┘

📊 24. Monitoring Deployment

GitOps giúp deploy.

Nhưng deploy xong chưa có nghĩa là Application khỏe.

Ví dụ:

ArgoCD:
Healthy ✅

Application:
HTTP 500 ❌

Đây là lý do cần Monitoring.

Nếu bạn đã triển khai Prometheus + Grafana ở các Lab trước, hãy kiểm tra:

CPU
Memory
Request Rate
Request Latency
HTTP 5xx
Pod Restart

Một flow production hoàn chỉnh sẽ là:

Git
 ↓
ArgoCD
 ↓
Kubernetes
 ↓
Application
 ↓
Prometheus
 ↓
Grafana

🚨 25. Test Production Incident

Hãy mô phỏng một sự cố.

Ví dụ Backend bị crash:

kubectl delete pod \
  -n todo-production \
  -l app=todo-backend

Kubernetes sẽ tạo Pod mới.

Kiểm tra:

kubectl get pods -n todo-production

Bạn sẽ thấy:

old pod
   ↓
Terminating

new pod
   ↓
Running

ArgoCD vẫn giữ trạng thái:

Synced
Healthy

Điều này cho thấy:

Kubernetes chịu trách nhiệm duy trì Application runtime.

ArgoCD chịu trách nhiệm đảm bảo Kubernetes khớp với Git.

Prometheus/Grafana chịu trách nhiệm cho bạn biết hệ thống đang hoạt động thế nào.

Ba thành phần có vai trò khác nhau.


🏭 26. Production Environment

Bây giờ tạo:

overlays/production/

Production nên khác Dev.

Ví dụ:

replicas: 3

Trong khi Dev:

replicas: 1

Architecture:

                 base
                  │
        ┌─────────┴─────────┐
        ▼                   ▼
       dev             production
     replicas=1         replicas=3

Đây là lý do Kustomize rất hữu ích trong GitOps.


🛡️ 27. Production Safety Rule

Một nguyên tắc quan trọng:

Không nên cho mọi thay đổi vào production tự động ngay lập tức.

Có thể áp dụng:

Development
    │
    │ Auto Sync
    ▼
Production
    │
    │ Pull Request
    │
    ▼
Code Review
    │
    │ Approve
    ▼
Merge
    │
    ▼
ArgoCD
    │
    ▼
Production

Ví dụ:

feature branch
      ↓
      PR
      ↓
review
      ↓
merge main
      ↓
ArgoCD
      ↓
production

Điều này tạo ra một audit trail rõ ràng.


🧪 28. Final Exercise

Bây giờ hãy tự thực hiện toàn bộ flow mà không nhìn lại từng bước.

Exercise 1 — Application Deployment

  • Tạo GitOps Repository.
  • Tạo base.
  • Tạo dev.
  • Tạo production.
  • Deploy bằng ArgoCD.

Kiểm tra:

kubectl get applications -n argocd

Exercise 2 — Automatic Deployment

Thay đổi:

replicas: 1

thành:

replicas: 2

Commit:

git commit -m "scale backend"
git push

Quan sát ArgoCD.


Exercise 3 — Self-Healing

Scale Kubernetes thủ công:

kubectl scale deployment backend \
  -n todo-dev \
  --replicas=5

Quan sát ArgoCD sửa lại về trạng thái Git.


Exercise 4 — Rollback

Deploy:

backend:v1.1.0

Sau đó rollback về:

backend:v1.0.0

Chỉ sử dụng Git.


Exercise 5 — Production

Thiết lập:

dev       → replicas = 1
production → replicas = 3

Không copy toàn bộ Manifest.

Sử dụng:

base + overlays

Exercise 6 — Incident

Giả lập:

Pod Crash

Sau đó kiểm tra:

kubectl get pods

và:

kubectl get applications -n argocd

Trả lời:

Kubernetes xử lý vấn đề gì?

ArgoCD xử lý vấn đề gì?

Monitoring xử lý vấn đề gì?


🔍 29. Troubleshooting

❌ ArgoCD báo OutOfSync

Kiểm tra:

kubectl get application todo-dev -n argocd

Sau đó kiểm tra:

Git
    ↓
Manifest
    ↓
Kustomize
    ↓
Kubernetes

Đừng vội chạy:

kubectl apply

Vì như vậy bạn đang bypass GitOps.


❌ Application Degraded

Kiểm tra Pod:

kubectl get pods -n todo-dev

Sau đó:

kubectl describe pod <pod-name> -n todo-dev

và:

kubectl logs <pod-name> -n todo-dev

Nhớ:

ArgoCD báo trạng thái
       ↓
Kubernetes Events
       ↓
Pod Logs

ArgoCD không thay thế Kubernetes troubleshooting.


❌ ArgoCD không thấy Git change

Kiểm tra:

git log

và:

git status

Sau đó kiểm tra repository trong ArgoCD.

Các lỗi thường gặp:

Sai repoURL
Sai branch
Sai path
Git chưa push
Kustomize lỗi

💡 30. Production Tips

Tip 1 — Đừng dùng latest

Không nên:

image: backend:latest

Nên:

image: backend:v1.4.2

Hoặc tốt hơn nữa:

backend:git-abc123

Bạn luôn biết chính xác version đang chạy.


Tip 2 — Git là nơi thay đổi

Trong GitOps:

❌ kubectl edit
❌ kubectl set image
❌ sửa production trực tiếp

Thay vào đó:

Change Git
   ↓
Review
   ↓
Merge
   ↓
ArgoCD
   ↓
Kubernetes

Tip 3 — Không để Secret plaintext trong Git

Không commit:

password: production-password

Hãy sử dụng Secret Management.


Tip 4 — Production nên có Approval

Dev:

Git Push
 ↓
ArgoCD
 ↓
Deploy

Production:

Git Push
 ↓
Pull Request
 ↓
Review
 ↓
Merge
 ↓
ArgoCD
 ↓
Deploy

Tip 5 — Monitoring không phải phần phụ

Một deployment thành công không có nghĩa Application đang hoạt động tốt.

Luôn quan sát:

Deployment
    ↓
Health
    ↓
Metrics
    ↓
Logs
    ↓
Alerts

🧠 31. Bạn thực sự đã học được gì?

Đừng cố nhớ tất cả command.

Hãy nhớ 4 thành phần chính:

┌──────────────┐
│ GitHub       │
│ Source Code  │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ CI           │
│ Build Image  │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ GitOps Repo  │
│ Desired State│
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ ArgoCD       │
│ Deployment   │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│ Kubernetes   │
│ Runtime      │
└──────────────┘

Có thể hiểu đơn giản:

CI tạo ra phần mềm.

GitOps mô tả phần mềm nên chạy như thế nào.

ArgoCD đảm bảo Kubernetes chạy đúng như Git.

Kubernetes chạy Application.

Monitoring cho biết Application có thực sự khỏe hay không.


🏆 32. Final Project — Definition of Done

Bạn hoàn thành Lab 21 khi có thể chứng minh được:

☑ GitHub Application Repository
☑ GitOps Repository
☑ Kustomize Base
☑ Dev Environment
☑ Production Environment
☑ ArgoCD Application
☑ Automated Sync
☑ Self-Healing
☑ Prune
☑ Git-based Rollback
☑ CI Build Docker Image
☑ Push Docker Registry
☑ Update GitOps Repository
☑ Kubernetes Deployment
☑ Prometheus Monitoring
☑ Grafana Dashboard
☑ Troubleshooting Flow

Và quan trọng nhất, bạn có thể tự giải thích flow:

Developer
    │
    ▼
Git Push
    │
    ▼
CI
    │
    ▼
Docker Image
    │
    ▼
GitOps Repository
    │
    ▼
ArgoCD
    │
    ▼
Kubernetes
    │
    ▼
Application
    │
    ▼
Monitoring

🎓 33. Kết thúc Phase GitOps + ArgoCD

Ở Lab đầu tiên, bạn có thể đã deploy Kubernetes bằng:

kubectl apply

Đến Lab cuối cùng, tư duy đã thay đổi:

                    BEFORE

Developer
    │
    ▼
kubectl apply
    │
    ▼
Kubernetes

thành:

                    AFTER

Developer
    │
    ▼
     Git
    │
    ▼
   CI/CD
    │
    ▼
GitOps Repository
    │
    ▼
   ArgoCD
    │
    ▼
Kubernetes
    │
    ▼
Monitoring

Đây chính là bước chuyển từ:

"Biết deploy Kubernetes"

sang:

"Biết xây dựng một quy trình Kubernetes deployment có tính tự động, audit được và có khả năng self-healing."

Và đó là nền tảng rất quan trọng trước khi bước sang các chủ đề DevOps nâng cao hơn như Cloud, Terraform, CI/CD nâng cao, Security, Observability và Production Infrastructure.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.