0

Lab 6 — GitOps với Kustomize

🎯 Mục tiêu

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

  • Hiểu Kustomize giải quyết vấn đề gì trong GitOps.
  • Biết cách tổ chức Kubernetes manifests cho nhiều environment.
  • Biết sử dụng Base / Overlay.
  • Biết deploy Kustomize application bằng ArgoCD.
  • Hiểu cách thay đổi dev, staging, production mà không copy-paste toàn bộ YAML.
  • Biết một số nguyên tắc tổ chức Kustomize trong production.

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

Ở các lab trước, chúng ta đã deploy application bằng Kubernetes và ArgoCD.

Giả sử Todo App có 3 environment:

Development
    │
    ├── 1 replica
    └── image: todo:v1.0.0

Staging
    │
    ├── 2 replicas
    └── image: todo:v1.0.0

Production
    │
    ├── 5 replicas
    └── image: todo:v1.0.0

Thoạt nhìn khá đơn giản.

Nhưng Kubernetes manifests bắt đầu nhiều lên:

deployment.yaml
service.yaml
configmap.yaml
ingress.yaml
...

Nếu copy toàn bộ YAML cho từng environment:

kubernetes/
├── dev/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
│
├── staging/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
│
└── production/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml

Bạn sẽ có rất nhiều YAML bị trùng lặp.

Ví dụ Service của dev và production gần như giống nhau.

Nếu sửa:

service:
  port: 8080

bạn có thể phải sửa ở nhiều nơi.

Đây là một vấn đề lớn trong GitOps:

GitOps cần Git là Source of Truth, vì vậy repository phải dễ đọc, dễ thay đổi và hạn chế duplication.

Kustomize giúp giải quyết vấn đề này.


🧠 2. Hiểu nhanh về Kustomize

2.1 Kustomize là gì?

Kustomize là công cụ giúp bạn tạo ra Kubernetes manifests khác nhau từ một bộ manifests cơ sở mà không cần copy toàn bộ YAML.

Thay vì:

Dev YAML
Staging YAML
Production YAML

ta có:

              Base
               │
       ┌───────┼────────┐
       ▼       ▼        ▼
      Dev   Staging  Production

Base chứa những thứ chung.

Overlay chứa những thứ khác nhau.


2.2 Base là gì?

Base là cấu hình Kubernetes dùng chung cho tất cả environment.

Ví dụ:

base/
├── deployment.yaml
├── service.yaml
└── kustomization.yaml

Base có thể chứa:

Deployment
Service
ConfigMap
Ingress

Những thứ này không cần phải copy cho từng environment.


2.3 Overlay là gì?

Overlay là lớp cấu hình nằm trên Base để thay đổi behavior cho từng environment.

Ví dụ:

overlays/
├── dev/
├── staging/
└── production/

Mỗi environment có thể thay đổi:

replicas
image
resources
environment variables
Ingress
ConfigMap

Ví dụ:

Base
replicas: 1

       │
       ├── dev
       │    replicas: 1
       │
       ├── staging
       │    replicas: 2
       │
       └── production
            replicas: 5

🏗️ 3. Architecture

Repository của chúng ta sẽ có cấu trúc:

gitops-repo/
│
├── apps/
│   └── todo/
│
│       ├── base/
│       │   ├── deployment.yaml
│       │   ├── service.yaml
│       │   └── kustomization.yaml
│       │
│       └── overlays/
│           │
│           ├── dev/
│           │   ├── kustomization.yaml
│           │   └── replica-patch.yaml
│           │
│           ├── staging/
│           │   ├── kustomization.yaml
│           │   └── replica-patch.yaml
│           │
│           └── production/
│               ├── kustomization.yaml
│               └── replica-patch.yaml

Flow:

                    Git Repository
                          │
                          ▼
                    ┌───────────┐
                    │   Base    │
                    │           │
                    │ Deployment│
                    │ Service   │
                    └─────┬─────┘
                          │
             ┌────────────┼────────────┐
             ▼            ▼            ▼
           Dev         Staging     Production
             │            │            │
             ▼            ▼            ▼
        replicas: 1   replicas: 2   replicas: 5
             │            │            │
             └────────────┼────────────┘
                          ▼
                       ArgoCD
                          │
                          ▼
                    Kubernetes

Điểm quan trọng:

ArgoCD không thay thế Kustomize.

ArgoCD chịu trách nhiệm:

Git → Kubernetes

Kustomize chịu trách nhiệm:

Base + Overlay → Kubernetes Manifest

Hai công cụ bổ sung cho nhau.


🧪 4. Chuẩn bị Lab

4.1 Kiểm tra Kustomize

Các phiên bản Kubernetes hiện đại thường đã tích hợp Kustomize trong kubectl.

Kiểm tra:

kubectl version --client

Sau đó:

kubectl kustomize version

Nếu command hoạt động là chúng ta có thể bắt đầu.


🛠️ 5. Tạo GitOps Repository

5.1 Tạo cấu trúc thư mục

mkdir -p gitops-repo/apps/todo/base
mkdir -p gitops-repo/apps/todo/overlays/dev
mkdir -p gitops-repo/apps/todo/overlays/staging
mkdir -p gitops-repo/apps/todo/overlays/production

cd gitops-repo

Kiểm tra:

tree

Kết quả:

apps
└── todo
    ├── base
    └── overlays
        ├── dev
        ├── staging
        └── production

🧱 6. Tạo Base

6.1 Tại sao cần Base?

Todo App có một số cấu hình giống nhau ở mọi environment:

Deployment
Service
Container port
Service port
Labels

Không có lý do gì phải viết lại chúng 3 lần.

Vì vậy chúng ta đưa chúng vào base.


6.2 Tạo Deployment

Tạo:

apps/todo/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment

metadata:
  name: todo-backend

spec:
  replicas: 1

  selector:
    matchLabels:
      app: todo-backend

  template:
    metadata:
      labels:
        app: todo-backend

    spec:
      containers:
        - name: todo-backend
          image: nginx:1.27

          ports:
            - containerPort: 80

          resources:
            requests:
              cpu: 100m
              memory: 128Mi

            limits:
              cpu: 500m
              memory: 512Mi

Ở đây chúng ta sử dụng nginx để lab tập trung vào Kustomize.

Trong project thật, bạn có thể thay bằng:

your-registry/todo-backend:v1.0.0

🧩 7. Tạo Service

Tạo:

apps/todo/base/service.yaml
apiVersion: v1
kind: Service

metadata:
  name: todo-backend

spec:
  selector:
    app: todo-backend

  ports:
    - port: 80
      targetPort: 80

  type: ClusterIP

📝 8. Tạo kustomization.yaml

Đây là file quan trọng nhất của Kustomize.

Tạo:

apps/todo/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - service.yaml

Bạn có thể hiểu đơn giản:

kustomization.yaml
       │
       ├── deployment.yaml
       │
       └── service.yaml

Nó nói cho Kustomize biết:

"Hãy lấy những resource này và tạo thành một Kubernetes application."


🔍 9. Build Base

Explain

Trước khi đưa Kustomize vào ArgoCD, chúng ta nên kiểm tra local trước.

Điều này rất quan trọng.

Nếu Kustomize build sai:

Git
 ↓
ArgoCD
 ↓
ERROR

Debug sẽ khó hơn.

Vì vậy:

Validate manifest trước, commit sau.


Do

Chạy:

kubectl kustomize apps/todo/base

Hoặc:

kubectl kustomize apps/todo/base > /tmp/todo.yaml

See Result

Bạn sẽ thấy Kustomize tạo ra:

apiVersion: apps/v1
kind: Deployment
...
---
apiVersion: v1
kind: Service
...

Kustomize không tạo ra Kubernetes resource mới.

Nó chỉ:

YAML nguồn
   ↓
Kustomize
   ↓
Manifest Kubernetes hoàn chỉnh

🌱 10. Tạo Development Environment

10.1 Tại sao cần Overlay?

Dev cần ít resource.

Ví dụ:

Dev
replicas = 1

Production:

Production
replicas = 5

Chúng ta không muốn sửa Base mỗi lần deploy production.

Vì vậy tạo Overlay.


10.2 Tạo Dev kustomization

Tạo:

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

namespace: todo-dev

resources:
  - ../../base

replicas:
  - name: todo-backend
    count: 1

Ở đây:

../../base

có nghĩa:

Dev sử dụng Base làm cấu hình nền.

Sau đó:

replicas:
  - name: todo-backend
    count: 1

ghi đè số replica.


🔵 11. Tạo Staging Environment

Tạo:

apps/todo/overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: todo-staging

resources:
  - ../../base

replicas:
  - name: todo-backend
    count: 2

Staging sử dụng cùng Base nhưng:

replicas = 2

🔴 12. Tạo Production Environment

Tạo:

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

namespace: todo-production

resources:
  - ../../base

replicas:
  - name: todo-backend
    count: 5

Production:

replicas = 5

🔍 13. So sánh các Environment

Bây giờ chúng ta có:

                 BASE
                  │
        ┌─────────┼─────────┐
        ▼         ▼         ▼
       DEV     STAGING   PRODUCTION
        │         │         │
      1 pod      2 pods     5 pods

Điểm quan trọng là:

deployment.yaml
service.yaml

chỉ tồn tại một lần.

Chúng ta không copy chúng cho từng environment.


🧪 14. Build Development

Do

kubectl kustomize apps/todo/overlays/dev

Hoặc:

kubectl kustomize apps/todo/overlays/dev > /tmp/todo-dev.yaml

See Result

Bạn sẽ thấy:

spec:
  replicas: 1

và:

metadata:
  namespace: todo-dev

🧪 15. Build Production

Chạy:

kubectl kustomize apps/todo/overlays/production

Bạn sẽ thấy:

spec:
  replicas: 5

và:

metadata:
  namespace: todo-production

Như vậy:

Base
 │
 ├── Dev Overlay
 │      ↓
 │   replicas: 1
 │
 ├── Staging Overlay
 │      ↓
 │   replicas: 2
 │
 └── Production Overlay
        ↓
     replicas: 5

🚀 16. Deploy trực tiếp bằng kubectl

Trước khi dùng ArgoCD, hãy thử deploy bằng Kubernetes.

Dev

kubectl apply -k apps/todo/overlays/dev

Kiểm tra:

kubectl get pods -n todo-dev

Bạn sẽ thấy Pod:

todo-backend-xxxxxxxxxx-xxxxx

Kiểm tra Deployment:

kubectl get deployment -n todo-dev

Expected:

NAME           READY   UP-TO-DATE   AVAILABLE
todo-backend   1/1     1            1

🔄 17. Kustomize + ArgoCD

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

Trước đây:

Developer
    │
    ▼
Git
    │
    ▼
kubectl apply
    │
    ▼
Kubernetes

Bây giờ:

Developer
    │
    ▼
Git Repository
    │
    ▼
   ArgoCD
    │
    │ Kustomize
    ▼
Kubernetes

ArgoCD có thể đọc:

apps/todo/overlays/dev

và tự xử lý Kustomize.

Bạn không cần build YAML rồi commit YAML generated vào Git.


🏗️ 18. Tạo ArgoCD Application

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/gitops-repo.git
    targetRevision: main
    path: apps/todo/overlays/dev

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

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

Thay:

YOUR_USERNAME

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


📤 19. Push Repository lên GitHub

Tạo repository:

gitops-repo

Sau đó:

git init
git add .
git commit -m "feat: add todo app with kustomize"
git branch -M main
git remote add origin https://github.com/YOUR_USERNAME/gitops-repo.git
git push -u origin main

🚀 20. Deploy Application vào ArgoCD

Apply ArgoCD 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 Kubernetes:

kubectl get all -n todo-dev

👀 21. Quan sát trên ArgoCD

Mở ArgoCD UI.

Bạn sẽ thấy:

todo-dev
    │
    ├── Deployment
    │     └── todo-backend
    │
    └── Service
          └── todo-backend

ArgoCD đang theo dõi:

Git
 │
 │ desired state
 ▼
ArgoCD
 │
 │ actual state
 ▼
Kubernetes

Nếu hai trạng thái khác nhau:

Git:
replicas = 1

Kubernetes:
replicas = 3

ArgoCD có thể phát hiện:

OutOfSync

và với:

selfHeal: true

ArgoCD sẽ cố gắng đưa Kubernetes trở lại trạng thái trong Git.


🧪 22. Thử nghiệm Self-Healing

Đây là một bài test rất quan trọng.

Do

Thay đổi Deployment trực tiếp:

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

Kiểm tra:

kubectl get deployment -n todo-dev

Bạn sẽ thấy:

READY
3/3

See Result

Một lúc sau:

kubectl get deployment -n todo-dev

có thể trở lại:

READY
1/1

Tại sao?

Vì Git vẫn nói:

replicas = 1

ArgoCD coi Git là:

Desired State — trạng thái mong muốn.

Kubernetes đang có:

Actual State — trạng thái thực tế.

ArgoCD phát hiện:

Desired State
replicas = 1

       ≠

Actual State
replicas = 3

và reconcile lại.


🧠 23. Hiểu bản chất GitOps + Kustomize + ArgoCD

Đây là phần bạn nên nhớ.

Không cần học thuộc hàng chục câu lệnh.

Chỉ cần hiểu:

                Git
                 │
                 │ Source of Truth
                 ▼
        ┌─────────────────┐
        │ Kustomize       │
        │                 │
        │ Base + Overlay  │
        └────────┬────────┘
                 │
                 ▼
              ArgoCD
                 │
                 │ Reconcile
                 ▼
            Kubernetes

Kustomize làm gì?

Base
 +
Overlay
 ↓
Manifest cuối cùng

ArgoCD làm gì?

Git
 ↓
Compare
 ↓
Sync
 ↓
Kubernetes

Kubernetes làm gì?

Run Application

🌍 24. Quản lý nhiều Environment

Bây giờ hãy tưởng tượng project thực tế:

GitOps Repository
│
└── apps
    │
    └── todo
        │
        ├── base
        │
        └── overlays
            ├── dev
            ├── staging
            └── production

Mỗi environment có ArgoCD Application riêng:

                 Git
                  │
          ┌───────┼────────┐
          ▼       ▼        ▼
        dev    staging   production
          │       │        │
          ▼       ▼        ▼
       ArgoCD   ArgoCD   ArgoCD
          │       │        │
          ▼       ▼        ▼
      Kubernetes Kubernetes Kubernetes

Trong thực tế, bạn có thể có:

todo-dev
todo-staging
todo-production

và mỗi Application trỏ tới:

apps/todo/overlays/dev
apps/todo/overlays/staging
apps/todo/overlays/production

⚙️ 25. Khi nào nên dùng Kustomize?

Kustomize đặc biệt phù hợp khi:

  • Có nhiều environment.
  • Manifest Kubernetes tương đối giống nhau.
  • Chỉ cần thay đổi một số giá trị giữa các environment.
  • Muốn tránh copy-paste YAML.
  • Muốn Git repository dễ đọc.

Ví dụ:

                    Base
                     │
          ┌──────────┼──────────┐
          ▼          ▼          ▼
         Dev      Staging     Prod
          │          │          │
        1 pod       2 pods      5 pods

Đây là use case rất phổ biến của Kustomize.


⚠️ 26. Những lỗi thường gặp

❌ 26.1 Sai đường dẫn Base

Ví dụ:

resources:
  - ../../base

Nếu cấu trúc thư mục sai, Kustomize sẽ báo lỗi.

Kiểm tra:

tree apps/todo

❌ 26.2 Resource name không đúng

Ví dụ Base:

metadata:
  name: todo-backend

nhưng Overlay:

replicas:
  - name: backend
    count: 3

Kustomize không tìm thấy resource:

backend

vì tên thật là:

todo-backend

Kinh nghiệm: khi patch không hoạt động, kiểm tra kindmetadata.name trước.


❌ 26.3 ArgoCD báo OutOfSync

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

kubectl apply

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

Hãy kiểm tra:

Git
 ↓
Kustomize
 ↓
ArgoCD
 ↓
Kubernetes

Xác định trạng thái nào đang khác.


💡 27. Kinh nghiệm Production

27.1 Không copy toàn bộ manifest

Không nên:

dev/deployment.yaml
staging/deployment.yaml
production/deployment.yaml

nếu 90% nội dung giống nhau.

Nên:

base/
overlays/

27.2 Base nên chứa cấu hình chung

Ví dụ:

Deployment
Service
common labels
container ports
resource defaults

Overlay chứa:

replicas
environment-specific config
image
Ingress
resources

27.3 Không biến Kustomize thành "mê cung patch"

Khi project lớn, bạn có thể thấy:

patch-1.yaml
patch-2.yaml
patch-prod.yaml
patch-prod-v2.yaml
patch-prod-final.yaml
patch-prod-final-v2.yaml

Đây là dấu hiệu cấu trúc đang trở nên khó quản lý.

Kustomize nên giúp cấu hình dễ hiểu hơn, không phải tạo thêm một tầng phức tạp.


🧪 28. Exercise

Exercise 1 — Tạo Production Overlay

Tạo:

overlays/production/

với:

replicas = 5
namespace = todo-production

Kiểm tra:

kubectl kustomize apps/todo/overlays/production

Exercise 2 — Thay đổi Image

Thay:

nginx:1.27

thành:

nginx:1.28

chỉ trong Production.

Gợi ý sử dụng:

images:
  - name: nginx
    newTag: "1.28"

Sau đó:

kubectl kustomize apps/todo/overlays/production

Kiểm tra image đã thay đổi chưa.


Exercise 3 — GitOps Workflow

Thay đổi:

production replicas: 5

thành:

production replicas: 3

Sau đó:

git add .
git commit -m "chore: scale production"
git push

Quan sát ArgoCD.

Bạn nên thấy:

Git
 │
 │ push
 ▼
ArgoCD
 │
 │ detect change
 ▼
Sync
 │
 ▼
Kubernetes

🎯 29. Tổng kết

Sau Lab này, bạn nên hình dung GitOps architecture như sau:

                  GitHub
                    │
                    │
                    ▼
             ┌─────────────┐
             │   Kustomize │
             │             │
             │ Base        │
             │    +        │
             │ Overlay     │
             └──────┬──────┘
                    │
                    ▼
                ArgoCD
                    │
                    │ Reconcile
                    ▼
              Kubernetes
                    │
                    ▼
               Application

Điều quan trọng nhất cần nhớ:

Kustomize
    =
Base + Overlay
ArgoCD
    =
Git → Kubernetes

Kết hợp lại:

Git
 │
 ├── Base
 │
 └── Overlay
       │
       ▼
   Kustomize
       │
       ▼
    ArgoCD
       │
       ▼
 Kubernetes

Sau Lab 6, bạn đã có nền tảng để quản lý nhiều Kubernetes environment bằng GitOps mà không phải copy-paste hàng loạt YAML.

Lab 7 — GitOps với Helm, chúng ta sẽ giải quyết một vấn đề khác: khi application trở nên phức tạp, có rất nhiều cấu hình và muốn đóng gói Kubernetes manifests thành một package có thể tái sử dụng.


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í