0

Lab 7 — GitOps với Helm + ArgoCD

🎯 Mục tiêu

Sau lab này, bạn sẽ:

  • Hiểu Helm đóng vai trò gì trong GitOps.
  • Biết cách tổ chức một Helm Chart trong Git repository.
  • Biết cách để ArgoCD render và deploy Helm Chart.
  • Biết cách quản lý values.yaml cho Kubernetes Application.
  • Thực hành thay đổi configuration trong Git và để ArgoCD tự động cập nhật Kubernetes.
  • Hiểu một số cách tổ chức Helm + GitOps thường gặp trong production.

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

Ở các lab trước, chúng ta đã biết ArgoCD có thể lấy Kubernetes manifests từ Git:

Git Repository
      │
      │ YAML
      ▼
   ArgoCD
      │
      ▼
 Kubernetes

Ví dụ:

kubernetes/
├── deployment.yaml
├── service.yaml
├── configmap.yaml
└── ingress.yaml

Cách này hoạt động tốt.

Nhưng hãy tưởng tượng application của bạn có:

Deployment
Service
ConfigMap
Ingress
HPA
ServiceAccount
Secret
...

Và bạn có:

dev
staging
production

Lúc này số lượng YAML sẽ tăng rất nhanh.

Ví dụ:

dev/
├── deployment.yaml
├── service.yaml
├── ingress.yaml

staging/
├── deployment.yaml
├── service.yaml
├── ingress.yaml

production/
├── deployment.yaml
├── service.yaml
├── ingress.yaml

Bạn sẽ bắt đầu gặp vấn đề:

"Tôi chỉ muốn thay đổi image version, tại sao phải sửa rất nhiều YAML?"

Đây là lúc Helm trở nên hữu ích.


🧠 2. Hiểu nhanh: Helm + GitOps

2.1 Helm giải quyết vấn đề gì?

Helm cho phép chúng ta tạo template cho Kubernetes manifests.

Thay vì viết:

image: my-app:1.0.0
replicas: 2

ta có thể viết:

image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
replicas: {{ .Values.replicaCount }}

Sau đó configuration được đưa vào:

replicaCount: 3

image:
  repository: my-app
  tag: "2.0.0"

Helm sẽ render thành Kubernetes YAML hoàn chỉnh.


2.2 Helm Chart là gì?

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

Helm Chart = một package chứa template Kubernetes + configuration.

Ví dụ:

my-app/
├── Chart.yaml
├── values.yaml
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml

Trong đó:

Chart.yaml
    │
    │ Metadata
    ▼
Helm Chart

values.yaml
    │
    │ Configuration
    ▼
templates/
    │
    │ Render
    ▼
Kubernetes YAML

2.3 Vậy ArgoCD làm gì?

ArgoCD không thay thế Helm.

Hai công cụ có nhiệm vụ khác nhau:

             Git
              │
              ▼
        Helm Chart
              │
              │ Render
              ▼
       Kubernetes YAML
              │
              ▼
           ArgoCD
              │
              │ Sync
              ▼
        Kubernetes

Helm = package/template application

ArgoCD = GitOps deployment engine

Đây là điểm rất quan trọng.

Helm giúp chúng ta tạo Kubernetes manifests linh hoạt. ArgoCD đảm bảo Kubernetes luôn khớp với trạng thái được định nghĩa trong Git.

ArgoCD hỗ trợ Helm Charts như một trong những cách chính để tạo desired state cho application. (Argo CD)


🏗️ 3. Architecture

Trong lab này chúng ta xây dựng:

                    Developer
                        │
                        │ git push
                        ▼
                ┌─────────────────┐
                │ Git Repository  │
                │                 │
                │ Helm Chart      │
                │ ├── Chart.yaml  │
                │ ├── values.yaml │
                │ └── templates/  │
                └────────┬────────┘
                         │
                         │ Watch
                         ▼
                  ┌──────────────┐
                  │    ArgoCD    │
                  │              │
                  │ Helm Render  │
                  │ Sync         │
                  └──────┬───────┘
                         │
                         │ Apply
                         ▼
                ┌─────────────────┐
                │   Kubernetes    │
                │                 │
                │ Deployment      │
                │ Service         │
                │ Pod             │
                └─────────────────┘

Flow quan trọng nhất:

Git
 ↓
Helm Chart
 ↓
ArgoCD
 ↓
Helm Render
 ↓
Kubernetes

🧪 4. Chuẩn bị môi trường

4.1 Kiểm tra Kubernetes

kubectl get nodes

Kết quả mong muốn:

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

4.2 Kiểm tra Helm

helm version

Ví dụ:

version.BuildInfo{
  Version:"v3.x.x",
  ...
}

4.3 Kiểm tra ArgoCD

kubectl get pods -n argocd

Bạn cần thấy các component của ArgoCD đang Running.

Ví dụ:

NAME                                  READY   STATUS
argocd-server                         1/1     Running
argocd-repo-server                    1/1     Running
argocd-application-controller         1/1     Running

Nếu chưa cài ArgoCD, hãy hoàn thành Lab 3 — Install ArgoCD trước. Cách cài đặt chính thức hiện tại của ArgoCD sử dụng namespace argocd và manifest cài đặt chính thức. (Argo CD)


🧱 5. Tạo Helm Chart

🧠 Explain

Thay vì tự tạo hàng loạt file Kubernetes YAML, chúng ta sẽ để Helm quản lý chúng.

Tạo chart:

helm create todo-app

Kiểm tra:

cd todo-app
tree

Bạn sẽ thấy cấu trúc tương tự:

todo-app/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── ingress.yaml
    ├── serviceaccount.yaml
    ├── hpa.yaml
    └── ...

Helm đã tạo sẵn rất nhiều template.

Trong lab này, chúng ta không cần tất cả.


🧹 6. Tối giản Helm Chart

🧠 Explain

Khi học Helm, đừng cố học thuộc toàn bộ cấu trúc mà Helm generate.

Chúng ta chỉ cần hiểu:

Chart.yaml
    ↓
Thông tin Chart

values.yaml
    ↓
Configuration

templates/
    ↓
Kubernetes resources

Xóa các template không cần thiết:

rm -f templates/ingress.yaml
rm -f templates/hpa.yaml
rm -f templates/serviceaccount.yaml
rm -f templates/tests/*

Giữ lại:

todo-app/
├── Chart.yaml
├── values.yaml
└── templates/
    ├── deployment.yaml
    └── service.yaml

⚙️ 7. Tạo values.yaml

🧠 Explain

values.yaml là nơi chúng ta đưa configuration ra khỏi Kubernetes template.

Ví dụ:

replicaCount: 2

image:
  repository: nginx
  tag: "1.27"

service:
  type: ClusterIP
  port: 80

Điều này giúp chúng ta thay đổi configuration mà không phải sửa template.

Ví dụ:

dev

replicaCount: 1
image.tag: "1.27"

Trong production:

production

replicaCount: 3
image.tag: "1.28"

Template vẫn giữ nguyên.


✍️ 8. Tạo values.yaml

Thay nội dung values.yaml bằng:

replicaCount: 2

image:
  repository: nginx
  tag: "1.27"

service:
  type: ClusterIP
  port: 80

📦 9. Tạo Deployment Template

Mở:

templates/deployment.yaml

Thay bằng:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}

  selector:
    matchLabels:
      app: {{ .Release.Name }}

  template:
    metadata:
      labels:
        app: {{ .Release.Name }}

    spec:
      containers:
        - name: nginx
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

          ports:
            - containerPort: 80

📡 10. Tạo Service Template

Mở:

templates/service.yaml

Thay bằng:

apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
spec:
  type: {{ .Values.service.type }}

  selector:
    app: {{ .Release.Name }}

  ports:
    - port: {{ .Values.service.port }}
      targetPort: 80

🔍 11. Kiểm tra Helm Render

🧠 Explain

Đây là bước cực kỳ quan trọng.

Trước khi để ArgoCD deploy, hãy hiểu Helm thực sự tạo ra cái gì.

Chạy:

helm template todo-app .

Bạn sẽ thấy Helm biến:

replicas: {{ .Values.replicaCount }}

thành:

replicas: 2

Và:

image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

thành:

image: "nginx:1.27"

Mental Model

values.yaml
     │
     ▼
Helm Template
     │
     ▼
Kubernetes YAML

Helm không trực tiếp chạy Pod.

Nó chủ yếu giúp tạo ra Kubernetes manifests.


🧪 12. Kiểm tra bằng helm lint

Chạy:

helm lint .

Nếu thành công:

1 chart(s) linted, 0 chart(s) failed

Nếu có lỗi YAML hoặc cấu trúc Chart, Helm sẽ báo ở đây.

Tip: helm lint nên được chạy trong CI trước khi merge Pull Request.


📦 13. Đưa Helm Chart vào Git

🧠 Explain

GitOps yêu cầu:

Git phải chứa desired state của hệ thống.

Vì vậy Helm Chart cũng phải nằm trong Git.

Ví dụ repository:

gitops-repo/
│
└── apps/
    └── todo-app/
        ├── Chart.yaml
        ├── values.yaml
        └── templates/
            ├── deployment.yaml
            └── service.yaml

Commit:

git add .
git commit -m "feat: add todo app helm chart"
git push

🚀 14. Tạo ArgoCD Application

🧠 Explain

Bây giờ Git đã chứa Helm Chart.

Chúng ta cần nói cho ArgoCD biết:

"Hãy lấy Chart này từ repository và deploy nó vào Kubernetes."

Tạo:

argocd/todo-app.yaml

Nội dung:

apiVersion: argoproj.io/v1alpha1
kind: Application

metadata:
  name: todo-app
  namespace: argocd

spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
    targetRevision: main
    path: apps/todo-app

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

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

Thay:

YOUR_USERNAME
YOUR_GITOPS_REPO

bằng repository thật của bạn.

ArgoCD Application dùng source để xác định Git repository/path và destination để xác định Kubernetes cluster/namespace cần deploy. (Argo CD)


🧠 15. Điều gì đang xảy ra?

Đây là phần quan trọng nhất của lab.

Khi bạn:

kubectl apply -f argocd/todo-app.yaml

ArgoCD sẽ:

              GitHub
                 │
                 │ Pull
                 ▼
        ┌─────────────────┐
        │   Helm Chart    │
        │                 │
        │ Chart.yaml      │
        │ values.yaml     │
        │ templates/      │
        └────────┬────────┘
                 │
                 │ Helm render
                 ▼
        Kubernetes manifests
                 │
                 ▼
              ArgoCD
                 │
                 │ Sync
                 ▼
            Kubernetes

ArgoCD hỗ trợ nhiều kiểu source như plain manifests, Kustomize và Helm. (Argo CD)


▶️ 16. Deploy Application

Apply Application:

kubectl apply -f argocd/todo-app.yaml

Kiểm tra:

kubectl get applications -n argocd

Bạn có thể thấy:

NAME       SYNC STATUS   HEALTH STATUS
todo-app   Synced        Healthy

Kiểm tra Kubernetes:

kubectl get all -n todo-app

Kết quả tương tự:

NAME                            READY
pod/todo-app-xxxxxxxxxx-xxxxx   1/1
pod/todo-app-xxxxxxxxxx-yyyyy   1/1

NAME               TYPE        CLUSTER-IP
service/todo-app   ClusterIP   10.x.x.x

👀 17. Xem Application trên ArgoCD

Port-forward ArgoCD:

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

Mở:

https://localhost:8080

Bạn sẽ thấy:

┌─────────────────────────────┐
│         todo-app            │
│                             │
│  Synced       Healthy       │
│                             │
│      ┌──────────────┐       │
│      │ Deployment   │       │
│      └──────┬───────┘       │
│             │               │
│           Pods              │
│             │               │
│          Service            │
│                             │
└─────────────────────────────┘

Đây là lúc GitOps bắt đầu trở nên rất trực quan:

Git nói application phải như thế nào → ArgoCD đảm bảo Kubernetes đúng như vậy.


🔄 18. Thay đổi Application bằng Git

Bây giờ chúng ta thử điều tuyệt vời nhất.

Mở:

values.yaml

Thay:

replicaCount: 2

thành:

replicaCount: 4

Commit:

git add values.yaml
git commit -m "scale todo app to 4 replicas"
git push

👀 19. See Result

Kiểm tra:

kubectl get pods -n todo-app

Bạn sẽ thấy số lượng Pod tăng lên:

NAME                         READY
todo-app-xxxxx-xxxxx         1/1
todo-app-xxxxx-yyyyy         1/1
todo-app-xxxxx-zzzzz         1/1
todo-app-xxxxx-aaaaa         1/1

Hoặc:

kubectl get deployment -n todo-app
NAME       READY   UP-TO-DATE   AVAILABLE
todo-app   4/4     4            4

Bạn không cần chạy:

kubectl scale deployment ...

Bạn chỉ thay đổi Git.


🧠 20. Tại sao điều này quan trọng?

So sánh hai cách.

❌ Cách thủ công

Developer
    │
    │ kubectl scale
    ▼
Kubernetes

Vấn đề:

Git ──────────── Kubernetes
       ❌ lệch nhau

Git nói:

replicas: 2

Kubernetes thực tế:

replicas: 4

✅ GitOps

Developer
    │
    │ git push
    ▼
   Git
    │
    ▼
 ArgoCD
    │
    ▼
Kubernetes

Bây giờ:

Git
 │
 │ Desired State
 ▼
ArgoCD
 │
 │ Reconcile
 ▼
Kubernetes

Git trở thành Source of Truth.


🩹 21. Thử Self-Healing

Đây là một bài test rất đáng làm.

Chạy:

kubectl scale deployment todo-app \
  -n todo-app \
  --replicas=1

Kiểm tra:

kubectl get deployment -n todo-app

Ban đầu:

READY
1/1

Nhưng hãy chờ một chút.

ArgoCD phát hiện:

Git desired state:
replicas = 4

Kubernetes:
replicas = 1

Sau đó ArgoCD sẽ đưa cluster trở lại:

replicas = 4

Kiểm tra:

kubectl get deployment todo-app -n todo-app
READY
4/4

Đây chính là Self-Healing.


🔥 22. Một thay đổi khác: Image Version

Tiếp tục sửa:

image:
  repository: nginx
  tag: "1.28"

Commit:

git add values.yaml
git commit -m "chore: upgrade nginx image"
git push

Flow:

values.yaml
     │
     │ git push
     ▼
   GitHub
     │
     ▼
   ArgoCD
     │
     │ Helm render
     ▼
image: nginx:1.28
     │
     ▼
 Kubernetes

Bạn có thể kiểm tra:

kubectl describe deployment todo-app -n todo-app

🎛️ 23. Quản lý nhiều Environment

Đây mới là nơi Helm thực sự hữu ích trong GitOps.

Giả sử có:

dev
staging
production

Ta không muốn copy toàn bộ Chart ba lần.

Thay vào đó:

apps/
└── todo-app/
    ├── Chart.yaml
    ├── templates/
    │   ├── deployment.yaml
    │   └── service.yaml
    │
    └── values/
        ├── dev.yaml
        ├── staging.yaml
        └── production.yaml

Ví dụ:

dev.yaml

replicaCount: 1

image:
  repository: nginx
  tag: "1.27"

staging.yaml

replicaCount: 2

image:
  repository: nginx
  tag: "1.27"

production.yaml

replicaCount: 4

image:
  repository: nginx
  tag: "1.28"

Concept:

                 Helm Chart
                     │
          ┌──────────┼──────────┐
          ▼          ▼          ▼
        dev       staging    production
          │          │          │
       1 Pod       2 Pods      4 Pods

⚙️ 24. Override Helm Values trong ArgoCD

ArgoCD có thể truyền Helm values khi render application.

Ví dụ:

spec:
  source:
    repoURL: https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
    targetRevision: main
    path: apps/todo-app

    helm:
      valueFiles:
        - values/production.yaml

Điều này cho phép:

Same Chart
    │
    ├── values/dev.yaml
    │
    ├── values/staging.yaml
    │
    └── values/production.yaml

Mỗi environment sử dụng configuration riêng.

Helm hỗ trợ nhiều file values và file được chỉ định sau sẽ có độ ưu tiên cao hơn file trước. (Helm Blog)


🧩 25. Một Pattern tốt hơn cho Production

Một GitOps repository có thể được tổ chức như:

gitops/
│
├── apps/
│   └── todo-app/
│       ├── Chart.yaml
│       ├── templates/
│       │   ├── deployment.yaml
│       │   └── service.yaml
│       │
│       └── values/
│           ├── dev.yaml
│           ├── staging.yaml
│           └── production.yaml
│
└── argocd/
    ├── todo-app-dev.yaml
    ├── todo-app-staging.yaml
    └── todo-app-production.yaml

Architecture:

                       Git
                        │
              ┌─────────┼─────────┐
              │         │         │
             Dev      Staging     Prod
              │         │         │
              ▼         ▼         ▼
           ArgoCD     ArgoCD     ArgoCD
              │         │         │
              ▼         ▼         ▼
          Kubernetes Kubernetes Kubernetes

⚠️ 26. Một số lỗi thường gặp

❌ ArgoCD báo OutOfSync

Đừng lập tức chạy:

kubectl apply

Hãy hỏi:

Git đang muốn gì và Kubernetes đang có gì?

Kiểm tra:

argocd app get todo-app

Sau đó xem:

Desired State
      vs
Live State

❌ Helm chạy được nhưng ArgoCD fail

Trước tiên test:

helm lint .

Sau đó:

helm template todo-app .

Nếu Helm render đã lỗi thì vấn đề nằm ở Chart.

Nếu Helm render thành công nhưng ArgoCD lỗi, hãy kiểm tra:

Repository
Path
Revision
Values
Destination
Permissions

❌ Sửa trực tiếp Kubernetes

Ví dụ:

kubectl edit deployment todo-app -n todo-app

Đây là điều nên tránh trong GitOps.

Vì:

Git:
replicas = 2

Kubernetes:
replicas = 5

Bạn đã tạo ra configuration drift.

Nếu thay đổi là thay đổi chính thức:

Edit Git
   ↓
Commit
   ↓
Pull Request
   ↓
Review
   ↓
ArgoCD
   ↓
Kubernetes

💡 27. Production Tips

① Không copy Helm Chart cho từng environment

❌ Không nên:

todo-dev-chart/
todo-staging-chart/
todo-prod-chart/

Thường tốt hơn:

One Chart
    +
Different Values

② Không nhét mọi thứ vào values.yaml

values.yaml nên chứa configuration.

Không nên biến nó thành một file chứa toàn bộ application logic.


③ Pin version

Thay vì:

image:
  tag: latest

nên dùng:

image:
  tag: "1.28.3"

Production cần biết chính xác version nào đang chạy.


④ Production nên đi qua Pull Request

Flow tốt:

Developer
    │
    ▼
Git Push
    │
    ▼
Pull Request
    │
    ▼
Review
    │
    ▼
Merge
    │
    ▼
ArgoCD
    │
    ▼
Production

Điều này tạo ra:

  • Audit history
  • Code review
  • Rollback dễ dàng
  • Không cần SSH vào production để deploy

Đó cũng chính là một trong những giá trị cốt lõi của GitOps: application configuration và environment được version-control, deployment có thể audit và tự động hóa. (Argo CD)


🧪 28. Exercise

Exercise 1 — Thay đổi Replica

Thay:

replicaCount: 2

thành:

replicaCount: 3

Commit → Push.

Kiểm tra:

kubectl get pods -n todo-app

Mục tiêu:

3 Pods

Exercise 2 — Thay đổi Image

Đổi:

tag: "1.27"

sang một version khác.

Kiểm tra:

kubectl describe deployment todo-app -n todo-app

Tìm:

Image:

Exercise 3 — Test Self-Healing

Scale thủ công:

kubectl scale deployment todo-app \
  -n todo-app \
  --replicas=1

Chờ ArgoCD reconcile.

Kiểm tra:

kubectl get deployment -n todo-app

Mục tiêu:

3/3

nếu Git đang khai báo:

replicaCount: 3

Exercise 4 — Tạo Staging Environment

Tạo:

values/staging.yaml

với:

replicaCount: 2

image:
  repository: nginx
  tag: "1.28"

Tạo một ArgoCD Application riêng:

todo-app-staging

Deploy vào:

todo-staging

Kết quả:

                    Git
                     │
             ┌───────┴────────┐
             │                │
        production          staging
             │                │
             ▼                ▼
          ArgoCD            ArgoCD
             │                │
             ▼                ▼
       todo-app-prod    todo-app-staging

🧠 29. Tổng kết bản chất

Sau lab này, bạn không cần học thuộc hàng chục câu lệnh Helm.

Chỉ cần nhớ 4 thành phần:

Chart
  ↓
Templates

Values
  ↓
Configuration

Helm
  ↓
Render Kubernetes manifests

ArgoCD
  ↓
Sync Git → Kubernetes

Hay nhớ bằng một câu:

Helm quyết định Kubernetes manifest được tạo như thế nào; ArgoCD quyết định manifest đó được đồng bộ xuống Kubernetes như thế nào.

Flow cuối cùng:

Developer
    │
    │ git push
    ▼
┌─────────────────┐
│ Git Repository  │
│                 │
│ Helm Chart      │
│ values.yaml     │
│ templates/      │
└────────┬────────┘
         │
         ▼
      ArgoCD
         │
         │ Helm Render
         ▼
 Kubernetes Manifest
         │
         │ Sync
         ▼
┌─────────────────┐
│   Kubernetes    │
│                 │
│ Deployment      │
│ Service         │
│ Pods             │
└─────────────────┘

🎓 Sau Lab 7

Bạn đã đi từ:

Lab 1–5
Kubernetes + GitOps fundamentals
          ↓
Lab 6
Kustomize
          ↓
Lab 7
Helm + ArgoCD

Lab 8 — Environment Management, chúng ta sẽ giải quyết bài toán lớn hơn:

Làm thế nào quản lý Dev / Staging / Production mà không copy-paste Kubernetes configuration?

Đây là bước rất quan trọng để chuyển từ một GitOps lab đơn giản sang GitOps architecture thực tế.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí