Lab 10 — ArgoCD Application & Project
🎯 Mục tiêu
Sau lab này, bạn sẽ:
- Hiểu Application và AppProject khác nhau như thế nào.
- Tạo một ArgoCD
Applicationbằng YAML. - Tạo
AppProjectđể giới hạn Git Repository và Kubernetes Namespace mà Application được phép sử dụng. - Hiểu cách dùng Project để tạo boundary/security cho môi trường DevOps thực tế.
- Biết cách kiểm tra các lỗi thường gặp như
InvalidSpec,PermissionDenied,OutOfSync.
🤔 1. Vấn đề thực tế
Ở các lab trước, bạn đã dùng ArgoCD để deploy application.
Ví dụ:
Git Repository
│
▼
ArgoCD
│
▼
Kubernetes
│
└── todo-app
Ban đầu, bạn chỉ có một vài Application nên mọi thứ khá đơn giản.
Nhưng hãy tưởng tượng công ty có:
ArgoCD
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Team A Team B Team C
│ │ │
Dev Staging Prod
Nếu tất cả team đều có quyền:
Git Repository: *
Namespace: *
Cluster Resource: *
thì sẽ rất nguy hiểm.
Ví dụ Team A chỉ nên deploy:
GitHub:
company/team-a/*
Kubernetes:
team-a-dev
nhưng lại có quyền deploy:
production
kube-system
monitoring
thì một thay đổi sai có thể ảnh hưởng cả cluster.
Vì vậy chúng ta cần 2 khái niệm:
Application
↓
"Deploy cái gì và deploy ở đâu?"
AppProject
↓
"Application này được phép làm những gì?"
Đây chính là mục tiêu của lab này.
🧠 2. Hiểu nhanh
2.1. ArgoCD Application là gì?
Application là một đối tượng Kubernetes mà ArgoCD dùng để mô tả một ứng dụng cần được deploy.
Nó trả lời 3 câu hỏi:
1. Lấy manifest từ đâu?
2. Deploy vào đâu?
3. Dùng Project nào?
Ví dụ:
spec:
project: todo-project
source:
repoURL: https://github.com/example/gitops.git
path: apps/todo
destination:
server: https://kubernetes.default.svc
namespace: todo-app
Có thể hiểu:
Application
│
├── Project
│ └── todo-project
│
├── Source
│ └── GitHub → apps/todo
│
└── Destination
└── Kubernetes → todo-app
ArgoCD sau đó liên tục so sánh trạng thái trong Git với trạng thái thực tế trong cluster. Nếu khác nhau, Application có thể ở trạng thái OutOfSync. ([Argo CD][1])
2.2. AppProject là gì?
Nếu Application nói:
"Tôi muốn deploy Todo App."
thì AppProject nói:
"Bạn được phép deploy Todo App ở đâu và từ đâu."
Ví dụ:
AppProject: todo-project
Allowed Git:
github.com/company/todo-gitops
Allowed Namespace:
todo-app
Allowed Cluster Resources:
Không cho phép
Diagram:
AppProject
│
┌──────────┼──────────┐
▼ ▼ ▼
Git Repo Namespace Resources
│ │ │
▼ ▼ ▼
Allowed todo-app Limited
Đây là lớp kiểm soát rất quan trọng khi ArgoCD được sử dụng bởi nhiều team. ArgoCD cho phép Project giới hạn repositories và destinations mà Application được phép sử dụng. ([Argo CD][2])
🏗️ 3. Architecture
Trong lab này chúng ta xây dựng:
GitHub
│
│
GitOps Repository
│
▼
┌─────────────┐
│ ArgoCD │
│ │
│ Application │
└──────┬──────┘
│
│ uses
▼
┌─────────────┐
│ AppProject │
│ │
│ Git: allowed│
│ Namespace: │
│ todo-app │
└──────┬──────┘
│
│ permission check
▼
Kubernetes Cluster
│
▼
todo-app
Flow quan trọng:
Application
│
▼
"Deploy từ repo X vào namespace Y"
│
▼
AppProject kiểm tra
│
├── Repo X được phép? ──► YES
│
├── Namespace Y được phép? ──► YES
│
└── Resource được phép? ──► YES
│
▼
Sync
🧪 4. Chuẩn bị môi trường
4.1. Kiểm tra ArgoCD
Nếu bạn đã hoàn thành các lab trước:
kubectl get pods -n argocd
Bạn cần thấy các component chính đang Running.
Ví dụ:
NAME READY STATUS
argocd-server-xxx 1/1 Running
argocd-repo-server-xxx 1/1 Running
argocd-application-controller-xxx 1/1 Running
Kiểm tra CLI:
argocd version --client
4.2. Kiểm tra Application hiện tại
argocd app list
Bạn có thể đã có Application từ các lab trước.
Ví dụ:
NAME PROJECT STATUS HEALTH
todo-app default Synced Healthy
Điểm đáng chú ý:
PROJECT
↓
default
Application hiện tại đang sử dụng Project mặc định.
Trong lab này chúng ta sẽ tạo Project riêng:
default
↓
todo-project
🧪 5. Tạo Namespace cho Todo App
Trước tiên tạo namespace:
kubectl create namespace todo-app
Kiểm tra:
kubectl get namespace todo-app
Kết quả:
NAME STATUS
todo-app Active
🧪 6. Tạo AppProject
🤔 Tại sao cần làm việc này?
Không nên để tất cả Application sử dụng default Project trong môi trường production.
Thay vào đó, chúng ta tạo:
todo-project
và giới hạn nó:
Git Repository
↓
chỉ GitOps repo của Todo App
Kubernetes
↓
chỉ namespace todo-app
6.1. Tạo file Project
Tạo:
argocd/
└── projects/
└── todo-project.yaml
Nội dung:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: todo-project
namespace: argocd
spec:
description: Project for Todo Application
sourceRepos:
- https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
destinations:
- namespace: todo-app
server: https://kubernetes.default.svc
clusterResourceWhitelist: []
Thay
YOUR_USERNAME/YOUR_GITOPS_REPObằng repository GitOps của bạn.
6.2. Apply Project
kubectl apply -f argocd/projects/todo-project.yaml
Kiểm tra:
kubectl get appproject -n argocd
Kết quả:
NAME AGE
default ...
todo-project ...
🧠 7. Hiểu cấu hình AppProject
Đây là phần quan trọng nhất của lab.
sourceRepos
sourceRepos:
- https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
Có nghĩa:
Application thuộc Project này chỉ được phép lấy manifest từ repository được khai báo.
Ví dụ Application cố tình sử dụng:
repoURL: https://github.com/random-user/malicious-repo.git
ArgoCD sẽ từ chối vì repository này không nằm trong sourceRepos.
destinations
destinations:
- namespace: todo-app
server: https://kubernetes.default.svc
Có nghĩa:
Application chỉ được deploy vào namespace
todo-apptrên cluster này.
Nếu Application muốn deploy vào:
kube-system
hoặc:
production
Project sẽ chặn.
clusterResourceWhitelist
clusterResourceWhitelist: []
Điều này rất đáng chú ý.
Application không được cấp quyền tạo các cluster-scoped resources thông qua whitelist này.
Ví dụ các resource như:
ClusterRole
ClusterRoleBinding
Namespace
CustomResourceDefinition
không nên mặc nhiên cho phép mọi team tạo.
Production tip: Đây là tư duy least privilege — chỉ cấp đúng quyền cần thiết, không cấp toàn cluster chỉ vì "cho dễ".
🧪 8. Tạo Application sử dụng Project
Bây giờ chúng ta tạo Application.
Tạo:
argocd/
└── applications/
└── todo-app.yaml
Nội dung:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: todo-app
namespace: argocd
spec:
project: todo-project
source:
repoURL: https://github.com/YOUR_USERNAME/YOUR_GITOPS_REPO.git
targetRevision: main
path: apps/todo
destination:
server: https://kubernetes.default.svc
namespace: todo-app
syncPolicy:
automated:
prune: true
selfHeal: true
Application directory thông thường có thể chứa plain Kubernetes YAML; ArgoCD cũng hỗ trợ Helm, Kustomize và các config-management tool khác. ([Argo CD][3])
🧪 9. Apply Application
kubectl apply -f argocd/applications/todo-app.yaml
Kiểm tra:
kubectl get application -n argocd
Bạn sẽ thấy:
NAME SYNC STATUS HEALTH STATUS
todo-app Synced Healthy
Hoặc kiểm tra bằng CLI:
argocd app get todo-app
👀 10. See Result trên ArgoCD
Mở ArgoCD UI:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Sau đó truy cập:
https://localhost:8080
Trong Application:
todo-app
Bạn sẽ thấy:
Project
todo-project
Source
GitHub
apps/todo
Destination
todo-app
Sync
Synced
Health
Healthy
Điều quan trọng là Application không còn thuộc default Project.
🧪 11. Thử phá Project để hiểu bản chất
Đây là phần quan trọng nhất.
Đừng chỉ tạo YAML rồi xem Synced.
Hãy thử tạo một Application vi phạm policy.
11.1. Sai Repository
Sửa:
repoURL: https://github.com/random-user/test.git
Apply:
kubectl apply -f argocd/applications/todo-app.yaml
Kiểm tra:
argocd app get todo-app
ArgoCD có thể báo lỗi liên quan đến repository không được Project cho phép.
Bản chất:
Application
│
│ repo = random-user/test
▼
todo-project
│
│ sourceRepos?
▼
❌ NO
│
▼
DENIED
🧪 12. Thử deploy vào Namespace khác
Đổi:
destination:
server: https://kubernetes.default.svc
namespace: default
Apply:
kubectl apply -f argocd/applications/todo-app.yaml
Kiểm tra:
argocd app get todo-app
Lúc này Project sẽ không cho phép Application deploy vào default.
Bởi vì:
destinations:
- namespace: todo-app
chỉ cho phép:
todo-app
không phải:
default
🧠 13. Application vs AppProject
Đây là điểm bạn nên nhớ.
| Application | AppProject | |
|---|---|---|
| Mục đích | Mô tả application | Kiểm soát quyền |
| Git Repository | Chọn repo/path | Giới hạn repo |
| Namespace | Chọn namespace | Giới hạn namespace |
| Cluster | Chọn cluster | Giới hạn cluster |
| Resource | Deploy resources | Có thể giới hạn resources |
| Scope | Một application | Một nhóm applications |
Có thể nhớ bằng câu:
Application nói "deploy gì". Project nói "được phép deploy ở đâu".
🏗️ 14. Mô hình nhiều Team
Trong production, bạn có thể tổ chức:
ArgoCD
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
team-a-project team-b-project platform-project
│ │ │
▼ ▼ ▼
team-a team-b platform
namespace namespace namespace
Ví dụ:
team-a-project
├── repo: github.com/company/team-a/*
└── namespace: team-a-*
team-b-project
├── repo: github.com/company/team-b/*
└── namespace: team-b-*
platform-project
├── repo: github.com/company/platform/*
└── namespace: monitoring
Như vậy:
Team A
├── deploy Team A
└── ❌ không deploy Production
Team B
├── deploy Team B
└── ❌ không deploy Team A
Platform Team
├── monitoring
├── ingress
└── infrastructure
Đây mới là lý do AppProject thực sự hữu ích trong môi trường doanh nghiệp.
🔐 15. Production Tip — Đừng dùng default Project cho mọi thứ
default Project rất tiện khi học:
Lab
↓
default project
↓
Application
Nhưng khi hệ thống lớn hơn:
Production
↓
nhiều Team
↓
nhiều Application
nên tạo Project riêng:
team-a
team-b
team-c
platform
monitoring
và giới hạn:
Source Repository
+
Destination
+
Resource Permission
Điều này giúp giảm blast radius — tức là khi một team hoặc một cấu hình bị sai, phạm vi ảnh hưởng được giới hạn.
🧪 16. Exercise 1 — Tạo Project cho Backend
Tạo:
backend-project
Yêu cầu:
Git Repository:
GitOps repository của bạn
Namespace:
todo-app
Cluster:
local Kubernetes cluster
Sau đó tạo:
backend-app
và cho Application sử dụng:
project: backend-project
Kiểm tra
argocd app list
Kỳ vọng:
NAME PROJECT STATUS
backend-app backend-project Synced
🧪 17. Exercise 2 — Test Permission
Thử thay đổi Application:
namespace: default
và kiểm tra:
argocd app get backend-app
Câu hỏi
Tại sao Application không thể deploy vào default?
Gợi ý:
Nhìn vào:
spec:
destinations:
của AppProject.
🧪 18. Exercise 3 — Multi-Team
Tạo:
team-a-project
team-b-project
Mô hình:
team-a-project
└── namespace: team-a
team-b-project
└── namespace: team-b
Sau đó tạo:
team-a-app
team-b-app
Kỳ vọng:
team-a-app
│
└── team-a-project
│
└── team-a namespace
team-b-app
│
└── team-b-project
│
└── team-b namespace
Cuối cùng thử cho:
team-a-app
deploy vào:
team-b
và quan sát kết quả.
🧪 19. Troubleshooting
❌ Application is invalid
Kiểm tra:
argocd app get todo-app
Sau đó kiểm tra Project:
kubectl get appproject todo-project -n argocd -o yaml
Đặc biệt kiểm tra:
sourceRepos:
destinations:
❌ Repository không được phép
Nếu thấy lỗi liên quan đến:
repository is not permitted
kiểm tra:
spec:
sourceRepos:
Repository trong Application phải match repository được Project cho phép.
❌ Namespace không được phép
Nếu thấy lỗi tương tự:
destination is not permitted
kiểm tra:
spec:
destinations:
Ví dụ Project chỉ cho:
destinations:
- namespace: todo-app
thì Application không thể deploy vào:
default
production
monitoring
❌ Application OutOfSync
Đầu tiên:
argocd app get todo-app
Sau đó:
argocd app diff todo-app
Bạn cần phân biệt:
OutOfSync
≠
Deployment Failed
OutOfSync chỉ có nghĩa:
Git Desired State
≠
Cluster Live State
ArgoCD phát hiện sự khác biệt giữa desired state trong Git và live state trong Kubernetes. ([Argo CD][1])
💡 20. Production Tips
① Không cấp quyền quá rộng
Tránh:
sourceRepos:
- '*'
destinations:
- namespace: '*'
server: '*'
nếu không thực sự cần.
Thay vào đó:
Allowed Repository
+
Allowed Namespace
+
Allowed Resources
② Tách Project theo boundary
Thay vì:
one-project
└── 100 applications
có thể tổ chức:
platform-project
team-a-project
team-b-project
monitoring-project
Từ đó dễ quản lý quyền và giảm blast radius.
③ Project cũng nên được quản lý bằng Git
Đừng tạo Project production thủ công mãi bằng:
kubectl apply ...
Mục tiêu cuối cùng của GitOps là:
Git
│
├── Applications
├── AppProjects
├── Helm
├── Kustomize
└── Policies
│
▼
ArgoCD
│
▼
Kubernetes
Như vậy cấu hình quyền cũng có history:
Who changed?
When?
Why?
What changed?
④ Cẩn thận với prune
Ở các lab trước bạn có thể đã sử dụng:
automated:
prune: true
Prune có nghĩa ArgoCD có thể xóa resource không còn tồn tại trong desired state. ArgoCD mặc định không tự động prune trong automated sync nếu bạn chưa bật tùy chọn này. ([Argo CD][4])
Trong production, nên đặc biệt cẩn thận với:
prune: true
nhất là khi repository hoặc path có thể bị thay đổi ngoài ý muốn.
🧠 21. Tổng kết
Sau lab này, hãy nhớ mô hình:
ArgoCD
│
┌───────────┴───────────┐
│ │
Application AppProject
│ │
│ │
"Deploy gì?" "Được phép làm gì?"
│ │
▼ ▼
Git Source Permissions
Destination Repository
Sync Policy Namespace
Resources
Hay đơn giản hơn:
Application = What + Where AppProject = Where you're allowed to go
Trong GitOps production:
Developer
│
▼
Git
│
▼
Application
│
▼
AppProject
│
├── Repository allowed?
├── Destination allowed?
└── Resource allowed?
│
▼
ArgoCD
│
▼
Kubernetes
Đây là nền tảng để bước sang các bài tiếp theo như GitOps CI/CD Pipeline, Image Automation, ApplicationSet và App of Apps. ArgoCD cũng sử dụng Application làm nền tảng cho các cơ chế quản lý nhiều application như ApplicationSet.
All rights reserved