0

Lab 16 — App of Apps Pattern với ArgoCD

🎯 Mục tiêu

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

  • Hiểu App of Apps Pattern là gì và tại sao cần nó.
  • Biết cách một ArgoCD Application có thể quản lý nhiều Application khác.
  • Tổ chức GitOps Repository theo hướng dễ mở rộng.
  • Deploy nhiều ứng dụng bằng một Application duy nhất.
  • Hiểu cách Pattern này được sử dụng trong môi trường production.

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

Ở các Lab trước, chúng ta đã dùng ArgoCD để deploy Application.

Ví dụ:

ArgoCD
   │
   └── Todo App

Ban đầu hệ thống chỉ có một ứng dụng nên mọi thứ khá đơn giản.

Nhưng production thường không chỉ có một Application.

Ví dụ:

Production Cluster

├── frontend
├── backend
├── postgres
├── redis
├── monitoring
├── ingress
└── logging

Nếu mỗi Application được tạo và quản lý riêng:

ArgoCD
 ├── frontend
 ├── backend
 ├── postgres
 ├── redis
 ├── monitoring
 ├── logging
 └── ingress

Khi số lượng Application tăng lên hàng chục hoặc hàng trăm, việc quản lý chúng bắt đầu trở nên khó khăn.

Chúng ta muốn có một cách đơn giản hơn:

ArgoCD
   │
   ▼
Root Application
   │
   ├── frontend
   ├── backend
   ├── postgres
   ├── redis
   ├── monitoring
   └── logging

Đây chính là ý tưởng của App of Apps Pattern.

Thay vì quản lý từng Application bằng tay, chúng ta tạo một Application "cha" để quản lý các Application "con".


🧠 2. Hiểu nhanh App of Apps

2.1. Application bình thường

Ở những Lab trước, bạn có thể có:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: todo-app
spec:
  source:
    repoURL: https://github.com/example/gitops.git
    path: apps/todo
  destination:
    server: https://kubernetes.default.svc
    namespace: todo-app

Application này có nhiệm vụ:

ArgoCD
   │
   ▼
todo-app
   │
   ▼
Kubernetes Resources

2.2. App of Apps

Với App of Apps, chúng ta tạo một Application đặc biệt:

                    ArgoCD
                       │
                       ▼
                ┌─────────────┐
                │ Root App    │
                └──────┬──────┘
                       │
             ┌─────────┼─────────┐
             ▼         ▼         ▼
          Frontend   Backend   Redis
             │         │         │
             ▼         ▼         ▼
         Resources  Resources  Resources

Root Application không trực tiếp deploy tất cả Deployment, Service, ConfigMap...

Nó deploy các ArgoCD Application.

Các Application con sau đó chịu trách nhiệm deploy Application thực tế.


🏗️ 3. Architecture

Trong Lab này chúng ta xây dựng một hệ thống đơn giản:

                         GitHub
                           │
                           │ Git
                           ▼
                  ┌──────────────────┐
                  │ GitOps Repository │
                  │                  │
                  │ apps/            │
                  │ ├── frontend     │
                  │ ├── backend      │
                  │ └── redis        │
                  │                  │
                  │ root/            │
                  │ └── applications │
                  └────────┬─────────┘
                           │
                           │ Watch
                           ▼
                    ┌──────────────┐
                    │    ArgoCD    │
                    │              │
                    │  Root App    │
                    └──────┬───────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
         Frontend App  Backend App  Redis App
              │            │            │
              ▼            ▼            ▼
         Kubernetes   Kubernetes   Kubernetes

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

Root Application
       │
       ├── Application: frontend
       ├── Application: backend
       └── Application: redis

🛠️ 4. Chuẩn bị GitOps Repository

4.1. Tạo cấu trúc Repository

Giả sử repository của chúng ta là:

gitops/
├── root/
│   └── applications/
│       ├── frontend.yaml
│       ├── backend.yaml
│       └── redis.yaml
│
└── apps/
    ├── frontend/
    │   ├── deployment.yaml
    │   └── service.yaml
    │
    ├── backend/
    │   ├── deployment.yaml
    │   └── service.yaml
    │
    └── redis/
        ├── deployment.yaml
        └── service.yaml

Có hai phần quan trọng:

root/
    │
    └── ArgoCD Applications

apps/
    │
    └── Kubernetes manifests

Root sẽ quản lý Application.

Application sẽ quản lý Kubernetes resources.


🧪 5. Tạo Application cho Frontend

5.1. Tại sao?

Trước tiên chúng ta cần một Application con.

Application này chịu trách nhiệm deploy frontend.

Tạo:

root/applications/frontend.yaml

Nội dung:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/gitops.git
    targetRevision: HEAD
    path: apps/frontend

  destination:
    server: https://kubernetes.default.svc
    namespace: frontend

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

Thay:

YOUR_USERNAME

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


5.2. Tạo Backend Application

Tạo:

root/applications/backend.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: backend
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/gitops.git
    targetRevision: HEAD
    path: apps/backend

  destination:
    server: https://kubernetes.default.svc
    namespace: backend

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

5.3. Tạo Redis Application

Tạo:

root/applications/redis.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: redis
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/gitops.git
    targetRevision: HEAD
    path: apps/redis

  destination:
    server: https://kubernetes.default.svc
    namespace: redis

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

Bây giờ Git repository chứa:

root/applications/

├── frontend.yaml
├── backend.yaml
└── redis.yaml

Nhưng ArgoCD vẫn chưa biết rằng nó phải tạo ba Application này.

Đó là nhiệm vụ của Root Application.


🚀 6. Tạo Root Application

6.1. Tại sao?

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

Thay vì chạy:

kubectl apply -f frontend.yaml
kubectl apply -f backend.yaml
kubectl apply -f redis.yaml

chúng ta tạo một Application duy nhất.

Root Application sẽ theo dõi:

root/applications/

và tự động tạo các Application bên trong đó.


6.2. Tạo Root Application

Tạo:

root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/gitops.git
    targetRevision: HEAD
    path: root/applications
    directory:
      recurse: true

  destination:
    server: https://kubernetes.default.svc
    namespace: argocd

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Apply:

kubectl apply -f root-app.yaml

👀 7. See Result

Kiểm tra:

kubectl get applications -n argocd

Bạn sẽ thấy:

NAME        SYNC STATUS   HEALTH STATUS
root-app    Synced        Healthy
frontend    Synced        Healthy
backend     Synced        Healthy
redis       Synced        Healthy

Kiểm tra Kubernetes:

kubectl get pods -A

Ví dụ:

NAMESPACE   NAME
frontend    frontend-xxxxx
backend     backend-xxxxx
redis       redis-xxxxx

🔍 8. Quan sát mối quan hệ Parent → Child

Đây là điều quan trọng nhất cần hiểu.

ArgoCD đang có:

root-app
   │
   ├── frontend
   │      └── Deployment
   │
   ├── backend
   │      └── Deployment
   │
   └── redis
          └── Deployment

Có thể xem Application:

kubectl get application root-app -n argocd

Và:

kubectl get application frontend -n argocd

Điểm khác biệt:

root-app
   │
   │ quản lý
   ▼
ArgoCD Applications

frontend
backend
redis

Trong khi:

frontend
   │
   │ quản lý
   ▼
Kubernetes Resources

Deployment
Service
ConfigMap
...

🧪 9. Thử thêm một Application

Đây là lúc chúng ta thấy App of Apps thực sự hữu ích.

Giả sử cần thêm:

Prometheus

Không cần tạo một Root Application mới.

Chỉ cần thêm:

root/applications/prometheus.yaml

Ví dụ:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: argocd
spec:
  project: default

  source:
    repoURL: https://github.com/YOUR_USERNAME/gitops.git
    targetRevision: HEAD
    path: apps/prometheus

  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring

  syncPolicy:
    automated:
      prune: true
      selfHeal: true

    syncOptions:
      - CreateNamespace=true

Commit:

git add .
git commit -m "add prometheus application"
git push

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

Git
 │
 │ new prometheus.yaml
 ▼
Root App
 │
 ▼
Prometheus App
 │
 ▼
Prometheus Resources

Kiểm tra:

kubectl get applications -n argocd

Kết quả:

NAME         SYNC STATUS   HEALTH STATUS
root-app     Synced        Healthy
frontend     Synced        Healthy
backend      Synced        Healthy
redis        Synced        Healthy
prometheus   Synced        Healthy

🎉 Bạn vừa thêm một Application mới mà không cần tạo thêm ArgoCD Application thủ công.


🧠 10. Tại sao Pattern này mạnh?

Hãy tưởng tượng production có:

50 Applications

Nếu quản lý thủ công:

kubectl apply
kubectl apply
kubectl apply
...

Rất khó kiểm soát.

Với App of Apps:

Git Repository
      │
      ▼
  Root App
      │
      ├── app-01
      ├── app-02
      ├── app-03
      ├── ...
      └── app-50

Git trở thành nơi mô tả:

"Cluster này cần chạy những Application nào?"

ArgoCD chỉ việc biến trạng thái trong Git thành trạng thái thực tế của Kubernetes.


🏭 11. Production Pattern

Trong production, cấu trúc có thể lớn hơn:

gitops/
│
├── bootstrap/
│   └── root-app.yaml
│
├── applications/
│   ├── monitoring.yaml
│   ├── logging.yaml
│   ├── ingress.yaml
│   ├── frontend.yaml
│   ├── backend.yaml
│   └── database.yaml
│
└── apps/
    ├── monitoring/
    ├── logging/
    ├── ingress/
    ├── frontend/
    ├── backend/
    └── database/

Flow:

             Git Repository
                    │
                    ▼
              ┌──────────┐
              │ Root App │
              └────┬─────┘
                   │
       ┌───────────┼───────────┐
       ▼           ▼           ▼
   Monitoring    Backend     Frontend
       │           │           │
       ▼           ▼           ▼
    Resources   Resources   Resources

Điều này giúp team có một nơi duy nhất để nhìn thấy:

Cluster đang chạy những gì?

⚠️ 12. Một số lưu ý Production

12.1. Đừng biến Root App thành "God Application"

App of Apps rất tiện nhưng không có nghĩa là mọi thứ phải nằm trong một Root App duy nhất.

Cluster lớn có thể chia:

Platform Root
├── Monitoring
├── Logging
└── Ingress

Application Root
├── Frontend
├── Backend
└── Worker

Giúp giảm mức độ phức tạp.


12.2. Cẩn thận với prune

Nếu bật:

prune: true

ArgoCD có thể xóa resource không còn tồn tại trong Git.

Đây là điều rất mạnh nhưng cũng rất nguy hiểm.

GitOps tốt không chỉ là "tự động", mà còn phải kiểm soát được những gì automation có quyền thay đổi.


12.3. Không commit Secret plaintext

Không nên:

gitops/
└── secret.yaml

password: my-production-password

Thay vào đó có thể sử dụng:

External Secrets
Sealed Secrets
Vault
Cloud Secret Manager

Chúng ta sẽ đi sâu hơn ở các Lab về Secrets.


🧪 13. Exercise

Exercise 1 — Thêm Application mới

Tạo:

apps/nginx/

và:

root/applications/nginx.yaml

Mục tiêu:

root-app
    │
    └── nginx
          │
          └── nginx Deployment

Kiểm tra:

kubectl get applications -n argocd

Exercise 2 — Xóa Application

Xóa:

root/applications/nginx.yaml

Commit và push:

git add .
git commit -m "remove nginx application"
git push

Quan sát ArgoCD.

Câu hỏi:

Điều gì xảy ra với Application nginx?


Exercise 3 — Self-Healing

Xóa thủ công một Pod:

kubectl delete pod -n frontend <pod-name>

Quan sát:

kubectl get pods -n frontend -w

Bạn sẽ thấy Kubernetes tạo Pod mới.

Điều này giúp phân biệt:

Kubernetes Self-Healing
        vs
ArgoCD Self-Healing

Kubernetes tự phục hồi Pod dựa trên desired state của Deployment.

ArgoCD đảm bảo Kubernetes configuration quay lại trạng thái được định nghĩa trong Git.


🧩 14. Hiểu bản chất trong 30 giây

Nếu chỉ nhớ một diagram của Lab này, hãy nhớ:

                  Git
                   │
                   ▼
              ┌─────────┐
              │ Root App│
              └────┬────┘
                   │
          creates/manages
                   │
       ┌───────────┼───────────┐
       ▼           ▼           ▼
   Frontend     Backend      Redis
      App          App         App
       │           │           │
       ▼           ▼           ▼
  Kubernetes  Kubernetes  Kubernetes
   Resources   Resources   Resources

Root App không phải Application chính của business.

Nó là Application dùng để quản lý các Application khác.

Đó chính là:

App of Apps Pattern.


🎯 15. Kết luận

Trong các Lab trước, chúng ta học cách ArgoCD deploy một Application.

Trong Lab này, chúng ta nâng cấp cách quản lý:

1 Application
      ↓
Many Applications
      ↓
App of Apps

Từ đây, Git repository không chỉ mô tả:

"Application này chạy như thế nào?"

mà còn mô tả:

"Cluster này cần chạy những Application nào?"

Đó là bước chuyển rất quan trọng từ deploy bằng ArgoCD sang quản lý cả Kubernetes platform bằng GitOps.

🔑 Những gì cần nhớ

  • Application → quản lý Kubernetes resources.
  • Root Application → quản lý các ArgoCD Applications.
  • App of Apps → dùng một Application để quản lý nhiều Application.
  • Git → Source of Truth.
  • Thêm Application → thêm manifest vào Git.
  • Xóa Application → xóa manifest khỏi Git.
  • ArgoCD → liên tục đưa cluster về trạng thái được định nghĩa trong Git.

Ở Lab tiếp theo, chúng ta sẽ đi thêm một bước với ApplicationSet — thay vì phải tạo từng Application manifest, ArgoCD có thể tự động generate hàng loạt Application dựa trên template và danh sách environment/cluster.


All Rights Reserved

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