0

Lab 2 — GitOps Repository Structure

1. 🎯 Mục tiêu

Sau Lab này, bạn sẽ hiểu và thực hành được:

  • Hiểu GitOps Repository là gì và tại sao cần một cấu trúc repository rõ ràng.
  • Phân biệt Application RepositoryGitOps Repository.
  • Biết cách tổ chức Kubernetes manifests theo dev, staging, production.
  • Hiểu vai trò của Kustomize trong việc quản lý nhiều environment.
  • Tự xây dựng một GitOps repository có thể sử dụng với ArgoCD ở các Lab tiếp theo.

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

Ở các Lab Kubernetes trước, có thể bạn đã deploy application bằng:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Cách này rất đơn giản.

Nhưng hãy tưởng tượng bạn có 3 environment:

Development
Staging
Production

Mỗi environment lại có:

Deployment
Service
ConfigMap
Ingress
HPA
Secret
...

Lúc này nếu quản lý bằng các file nằm rải rác trên máy cá nhân:

my-project/
├── deployment.yaml
├── service.yaml
├── deployment-prod.yaml
├── deployment-staging.yaml
├── service-prod.yaml
└── service-staging.yaml

sẽ rất nhanh trở nên khó quản lý.

Ví dụ:

Production đang chạy version v1.5, nhưng developer không biết chính xác file nào đang mô tả trạng thái Production.

Đây chính là vấn đề GitOps muốn giải quyết.

GitOps đưa ra một nguyên tắc rất đơn giản:

Git là Source of Truth.

Nói đơn giản:

Git Repository
      │
      │ mô tả
      ▼
Desired State
      │
      ▼
Kubernetes Cluster

Nếu Git nói:

image: todo-backend:v1.5

thì Kubernetes nên chạy:

todo-backend:v1.5

Nếu Git thay đổi thành:

image: todo-backend:v1.6

ArgoCD sẽ phát hiện sự khác biệt và đồng bộ Kubernetes.


3. 🧠 Hiểu nhanh

3.1. GitOps Repository là gì?

GitOps Repository là repository chứa các file mô tả trạng thái mong muốn của Kubernetes.

Ví dụ:

GitOps Repository
│
├── Deployment
├── Service
├── Ingress
├── ConfigMap
├── HPA
└── ...

Repository này không nhất thiết chứa source code application.

Nó chủ yếu trả lời câu hỏi:

"Kubernetes Production nên chạy như thế nào?"


3.2. Application Repository và GitOps Repository

Đây là một phân chia rất quan trọng.

Application Repository

Chứa source code:

todo-backend/
├── src/
├── package.json
├── Dockerfile
└── ...

Nó trả lời:

Application được xây dựng như thế nào?


GitOps Repository

Chứa deployment configuration:

todo-gitops/
├── apps/
├── environments/
└── ...

Nó trả lời:

Application được deploy như thế nào?

Có thể hình dung:

┌──────────────────────┐
│ Application Repo     │
│                      │
│ Source Code          │
│ Dockerfile           │
│ Tests                │
└──────────┬───────────┘
           │
           │ CI
           ▼
      Docker Image
           │
           │
           ▼
┌──────────────────────┐
│ GitOps Repo          │
│                      │
│ Kubernetes manifests │
│ Environment config   │
└──────────┬───────────┘
           │
           │ ArgoCD
           ▼
┌──────────────────────┐
│ Kubernetes           │
└──────────────────────┘

Tại sao tách hai repository?

source codedeployment state có vòng đời khác nhau.

Ví dụ:

Developer
   │
   │ sửa source code
   ▼
Application Repo
   │
   │ CI build
   ▼
todo-backend:v1.6
   │
   │ update deployment
   ▼
GitOps Repo
   │
   │ ArgoCD
   ▼
Production

CI chịu trách nhiệm build artifact.

GitOps + ArgoCD chịu trách nhiệm deploy artifact.


4. 🏗️ Architecture

Trong Lab này, chúng ta sẽ xây dựng repository theo mô hình:

                    ┌──────────────────────┐
                    │ Application Repo     │
                    │                      │
                    │ todo-backend         │
                    │ todo-frontend        │
                    └──────────┬───────────┘
                               │
                               │ CI builds image
                               ▼
                    ┌──────────────────────┐
                    │ Container Registry   │
                    │                      │
                    │ backend:v1.0         │
                    │ backend:v1.1         │
                    └──────────┬───────────┘
                               │
                               │ image tag
                               ▼
                    ┌──────────────────────┐
                    │ GitOps Repository    │
                    │                      │
                    │ environments/        │
                    │ ├── dev              │
                    │ ├── staging          │
                    │ └── production       │
                    └──────────┬───────────┘
                               │
                               │ ArgoCD
                               ▼
                    ┌──────────────────────┐
                    │ Kubernetes Cluster   │
                    └──────────────────────┘

5. 🗂️ Thiết kế GitOps Repository

Có nhiều cách tổ chức GitOps repository.

Trong Lab này, chúng ta sử dụng cấu trúc đơn giản nhưng có thể mở rộng:

todo-gitops/
│
├── apps/
│   ├── backend/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── kustomization.yaml
│   │
│   └── frontend/
│       ├── deployment.yaml
│       ├── service.yaml
│       └── kustomization.yaml
│
└── environments/
    ├── dev/
    ├── staging/
    └── production/

Ý tưởng:

apps/
    ↓
Application configuration

environments/
    ↓
Environment-specific configuration

6. 🧩 Tại sao cần dev, staging, production?

Trong production thực tế, bạn thường không deploy trực tiếp:

Developer → Production

Mà thường:

Developer
    ↓
Development
    ↓
Staging
    ↓
Production

Mỗi environment có thể có configuration khác nhau.

Ví dụ:

                 DEV        STAGING       PROD
--------------------------------------------------
Replicas           1            2            5
CPU             100m         200m         500m
Memory          256Mi        512Mi          1Gi
Domain        dev.xxx     staging.xxx    xxx.com

Source code có thể giống nhau.

Nhưng deployment configuration khác nhau.

Đó là lý do chúng ta không nên copy toàn bộ YAML thành:

deployment-dev.yaml
deployment-staging.yaml
deployment-production.yaml

Cách đó sẽ tạo rất nhiều duplication.

Thay vào đó, chúng ta có thể dùng Kustomize.


7. 🛠️ Kustomize là gì?

Kustomize cho phép chúng ta có một cấu hình Kubernetes cơ bản và tùy chỉnh nó cho từng environment.

Ví dụ:

Base
 │
 ├──────────► Dev
 │
 ├──────────► Staging
 │
 └──────────► Production

Thay vì copy:

deployment-dev.yaml
deployment-staging.yaml
deployment-production.yaml

chúng ta có:

base/
    deployment.yaml
    service.yaml

overlays/
    dev/
    staging/
    production/

Base

Chứa configuration chung.

Overlay

Chứa những thay đổi riêng của từng environment.


8. 🧪 Thực hành — Tạo GitOps Repository

8.1. Tạo repository

Tạo một repository mới:

todo-gitops

Clone repository:

git clone <your-gitops-repository>
cd todo-gitops

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

Tạo:

mkdir -p apps/backend
mkdir -p apps/frontend

mkdir -p environments/dev
mkdir -p environments/staging
mkdir -p environments/production

Kiểm tra:

tree

Kết quả:

todo-gitops
├── apps
│   ├── backend
│   └── frontend
└── environments
    ├── dev
    ├── staging
    └── production

9. 📦 Tạo Backend Base

Tạo:

apps/backend/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: backend
          image: nginx:1.27
          ports:
            - containerPort: 80

Tạo Service:

apps/backend/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: todo-backend
spec:
  selector:
    app: todo-backend

  ports:
    - port: 80
      targetPort: 80

Tạo:

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

resources:
  - deployment.yaml
  - service.yaml

10. 🔍 See Result — Build Base

Kustomize có thể render configuration thành Kubernetes YAML.

Chạy:

kubectl kustomize apps/backend

Bạn sẽ thấy:

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

Điều quan trọng ở đây:

Kustomize chưa deploy gì cả.

Nó chỉ tạo ra final Kubernetes manifests.

Có thể hình dung:

deployment.yaml
service.yaml
       │
       │ Kustomize
       ▼
Final Kubernetes YAML

11. 🌱 Tạo Environment Dev

Bây giờ chúng ta muốn dev chạy backend với:

replicas = 1

Tạo:

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

resources:
  - ../../apps/backend

Build:

kubectl kustomize environments/dev

Kustomize sẽ lấy configuration từ:

apps/backend

và sử dụng nó cho:

environments/dev

12. 🚀 Tạo Environment Production

Production có yêu cầu khác.

Ví dụ:

replicas = 3

Tạo:

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

resources:
  - ../../apps/backend

replicas:
  - name: todo-backend
    count: 3

Build:

kubectl kustomize environments/production

Tìm:

replicas: 3

Trong khi Dev vẫn:

replicas: 1

13. 🧠 Hiểu bản chất

Chúng ta đang có:

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

Điểm quan trọng:

Chúng ta không copy Deployment 3 lần.

Chúng ta chỉ thay đổi những gì khác nhau.

Đây chính là một trong những lý do Kustomize rất phù hợp với GitOps.


14. 🏗️ Hoàn thiện Repository

Sau khi hoàn thành, repository có thể có cấu trúc:

todo-gitops/
│
├── apps/
│   │
│   ├── backend/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── kustomization.yaml
│   │
│   └── frontend/
│       ├── deployment.yaml
│       ├── service.yaml
│       └── kustomization.yaml
│
└── environments/
    │
    ├── dev/
    │   └── kustomization.yaml
    │
    ├── staging/
    │   └── kustomization.yaml
    │
    └── production/
        └── kustomization.yaml

Đây là cấu trúc cơ bản mà chúng ta sẽ tiếp tục sử dụng ở các Lab sau.


15. 🔄 Git Commit

Đây là bước quan trọng trong GitOps.

Commit repository:

git add .
git commit -m "feat: create gitops repository structure"
git push

Bây giờ Git repository đã chứa:

Desired State

của Kubernetes.


16. 👀 See Result — Git trở thành Source of Truth

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

replicas: 3

Bạn thay đổi Git:

count: 5

Commit:

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

Khi ArgoCD được kết nối ở các Lab sau:

Git
 │
 │ replicas: 5
 ▼
ArgoCD
 │
 │ Sync
 ▼
Kubernetes
 │
 └── 5 Pods

Bạn không cần SSH vào server rồi chạy kubectl scale thủ công.

Đây chính là tư duy GitOps.


17. ⚠️ Những cách tổ chức nên tránh

17.1. Copy toàn bộ YAML cho từng environment

Không nên:

deployment-dev.yaml
deployment-staging.yaml
deployment-production.yaml

Vì sau một thời gian:

100 dòng × 3 environment
= 300 dòng

Một thay đổi nhỏ có thể phải sửa ở nhiều nơi.


17.2. Trộn source code với GitOps configuration

Không nên biến repository thành:

todo-app/
├── src/
├── Dockerfile
├── package.json
├── deployment.yaml
├── service.yaml
├── production.yaml
└── staging.yaml

Repository sẽ ngày càng khó quản lý khi application lớn lên.

Tách:

todo-app

và:

todo-gitops

sẽ rõ ràng hơn.


17.3. Để secret thật trong Git

Tuyệt đối tránh:

stringData:
  password: my-production-password

rồi:

git push

Git lưu lịch sử.

Ngay cả khi bạn xóa file sau đó, secret vẫn có thể tồn tại trong Git history.

Ở các Lab sau chúng ta sẽ tìm hiểu cách xử lý vấn đề này bằng:

Sealed Secrets
External Secrets
Secret Manager

18. 💡 Production Tips

Tip 1 — GitOps Repository nên dễ đọc

Khi có sự cố Production, người khác phải có thể mở repository và nhanh chóng hiểu:

Application nào?
Environment nào?
Version nào?
Configuration nào?

Tip 2 — Không nên tạo quá nhiều abstraction

Một lỗi phổ biến là biến Kustomize thành một hệ thống quá phức tạp:

base
 └── common
      └── shared
           └── templates
                └── overlays
                     └── ...

Nếu developer mất 30 phút chỉ để tìm:

"Production đang lấy configuration từ đâu?"

thì cấu trúc đã quá phức tạp.

GitOps tốt không phải là GitOps có nhiều file nhất.


Tip 3 — Environment nên có ownership rõ ràng

Ví dụ:

environments/dev
        ↓
Developer

environments/staging
        ↓
Development Team

environments/production
        ↓
Platform / DevOps Team

Trong production thực tế, bạn có thể kết hợp với:

Pull Request
Code Review
Branch Protection
Approval

để tránh việc một người vô tình thay đổi Production.


19. 🧪 Exercise

Bây giờ hãy tự thực hành mà không nhìn lại phần trên.

Exercise 1 — Tạo Backend

Tạo:

apps/backend/

bao gồm:

deployment.yaml
service.yaml
kustomization.yaml

Exercise 2 — Tạo 3 Environment

Tạo:

environments/
├── dev/
├── staging/
└── production/

Mỗi environment phải có:

kustomization.yaml

Exercise 3 — Khác biệt giữa Environment

Thiết lập:

Dev         → 1 replica
Staging     → 2 replicas
Production  → 3 replicas

Sau đó kiểm tra:

kubectl kustomize environments/dev
kubectl kustomize environments/staging
kubectl kustomize environments/production

Xác nhận số replica khác nhau.


Exercise 4 — Git Workflow

Thực hiện:

git add .
git commit -m "feat: add environment configurations"
git push

Sau đó kiểm tra repository trên GitHub.

Bạn phải có thể trả lời:

"Nếu Kubernetes Production bị mất, GitOps Repository có đủ thông tin để mô tả lại Production hay không?"

Nếu câu trả lời là , bạn đã bắt đầu hiểu đúng tư duy GitOps.


20. 🧠 Tổng kết

Trong Lab này, điều quan trọng nhất không phải là nhớ cú pháp Kustomize.

Bạn cần nhớ mối quan hệ giữa các thành phần:

Application Repo
      │
      │ source code
      ▼
   CI / Build
      │
      │ Docker Image
      ▼
GitOps Repo
      │
      │ desired state
      ▼
    ArgoCD
      │
      │ sync
      ▼
 Kubernetes

Và GitOps Repository:

todo-gitops/
│
├── apps/
│   ├── backend/
│   └── frontend/
│
└── environments/
    ├── dev/
    ├── staging/
    └── production/

🎯 Mental Model cần nhớ

Application Repository nói "app được viết như thế nào".

GitOps Repository nói "app phải được deploy như thế nào".

ArgoCD đảm bảo Kubernetes chạy đúng với những gì Git mô tả.


21. 🚀 Lab tiếp theo

Ở Lab 2, chúng ta mới xây dựng GitOps Repository.

Nhưng hiện tại Git chỉ đang chứa YAML.

Kubernetes vẫn chưa tự động đọc repository này.

Lab 3 — Install ArgoCD, chúng ta sẽ cài ArgoCD và kết nối:

GitHub
   │
   │ Watch
   ▼
ArgoCD
   │
   │ Sync
   ▼
Kubernetes

Từ đây, chúng ta sẽ bắt đầu thấy GitOps thực sự hoạt động: thay đổi Git → ArgoCD phát hiện → Kubernetes được cập nhậ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í