Imported from jawsbaek/scp-gitops-sample (
gitops-control-plane/apps/AGENTS.md). Install upstream withnpx skills add jawsbaek/scp-gitops-sample --skill apps. Copyright stays with the author.
gitops-control-plane/apps/ — App-of-Apps 및 ApplicationSet
Argo CD App-of-Apps 패턴의 핵심으로 모든 인프라, 서비스, 애플리케이션 Application을 자동 생성합니다.
Purpose
- 계층적 관리: 루트 → 중간 ApplicationSet → 개별 Application
- 자동 감지: Git 디렉토리 변경 → Application 자동 생성/삭제
- 환경별 동기화: dev/staging 자동, prod 수동 승인
- 단일 진입점:
app-of-apps만 적용하면 전체 시스템 관리
Key Files
| 파일 | 설명 |
|---|---|
app-of-apps.yaml |
최상위 루트 Application (sync-wave: -10) |
applicationset-infra.yaml |
환경별 인프라 ApplicationSet (dev/staging/prod) |
applicationset-services.yaml |
클러스터 서비스 ApplicationSet (동기화 순서 지정) |
applicationset-apps.yaml |
비즈니스 앱 ApplicationSet (env × app 매트릭스) |
For AI Agents
Working In This Directory
ApplicationSet 자동 감지 원리
# 1. 인프라 ApplicationSet → environments/{env}/infra 스캔
# - environments/dev/infra 존재 → dev-infra Application 생성
# - environments/staging/infra 존재 → staging-infra Application 생성
# 2. 서비스 ApplicationSet → cluster-services/* 스캔
# - cluster-services/argocd 존재 → svc-argocd Application 생성
# - cluster-services/cert-manager 존재 → svc-cert-manager Application 생성
# 3. 앱 ApplicationSet → app-manifests/overlays/{env}/{app} 스캔
# - app-manifests/overlays/dev/itop → dev-itop Application 생성
# - app-manifests/overlays/prod/itop → prod-itop Application 생성
ApplicationSet 상태 확인
# ApplicationSet 목록
kubectl get applicationset -n argocd
# 생성된 Application 확인
argocd app list | grep -E "^(dev|staging|prod|svc)-"
# ApplicationSet 상세 정보
kubectl describe applicationset services-applicationset -n argocd
새 Application 추가 절차
1. 인프라 추가 (환경별)
# environments/dev/infra/ 디렉토리 생성
mkdir -p environments/dev/infra
# → applicationset-infra가 자동으로 dev-infra Application 생성
2. 클러스터 서비스 추가
# cluster-services/{service-name}/ 디렉토리 생성
mkdir -p cluster-services/{service-name}
# → applicationset-services가 자동으로 svc-{service-name} Application 생성
3. 비즈니스 앱 추가
# app-manifests/overlays/{env}/{app}/ 디렉토리 생성
mkdir -p app-manifests/overlays/dev/{app-name}
# → applicationset-apps가 자동으로 dev-{app-name} Application 생성
Common Patterns
루트 Application (app-of-apps.yaml)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app-of-apps
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-10" # 가장 먼저 동기화
spec:
project: default
source:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
targetRevision: main
path: gitops-control-plane/apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: false # ApplicationSet 삭제 방지
selfHeal: true
syncOptions:
- CreateNamespace=true
인프라 ApplicationSet (Git Generator)
# applicationset-infra.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: infra-applicationset
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
revision: main
directories:
- path: environments/*/infra
template:
metadata:
name: '{{ .path.basename }}-infra'
annotations:
argocd.argoproj.io/sync-wave: "-5"
spec:
project: infra
source:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
targetRevision: main
path: '{{ .path.path }}'
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
서비스 ApplicationSet (Sync Wave)
# applicationset-services.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: services-applicationset
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
revision: main
directories:
- path: cluster-services/*
template:
metadata:
name: svc-{{ .path.basename }}
annotations:
# Sync Wave 자동 할당 (디렉토리명으로 결정)
argocd.argoproj.io/sync-wave: |-
{{- if has .path.basename (list "namespaces" "storage" "coredns") }}
"-5"
{{- else if eq .path.basename "cert-manager" }}
"-3"
{{- else if has .path.basename (list "openbao" "secrets" "external-secrets") }}
"-2"
{{- else if has .path.basename (list "istio-system" "service-mesh") }}
"-1"
{{- else if has .path.basename (list "argocd" "rbac") }}
"0"
{{- else if has .path.basename (list "monitoring" "logging") }}
"1"
{{- else if eq .path.basename "kyverno" }}
"5"
{{- else }}
"10"
{{- end }}
spec:
project: platform
source:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
targetRevision: main
path: '{{ .path.path }}'
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
앱 ApplicationSet (Matrix Generator)
# applicationset-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps-applicationset
namespace: argocd
spec:
goTemplate: true
# 환경 및 앱 조합 생성
generators:
- matrix:
generators:
- git:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
revision: main
directories:
- path: app-manifests/overlays/dev/*
- list:
elements:
- name: dev
cluster: ske-dev
syncAutomated: "true"
# staging과 prod도 유사하게 정의
template:
metadata:
name: '{{ .path.basename }}-{{ .name }}'
spec:
project: apps
source:
repoURL: https://gitlab.scp.internal/gitops/scp-gitops-gemini.git
targetRevision: main
path: '{{ .path.path }}'
destination:
server: '{{ .cluster }}'
syncPolicy:
automated:
prune: '{{ .syncAutomated }}'
selfHeal: true
Dependencies
| 컴포넌트 | 경로 | 역할 |
|---|---|---|
| Argo CD Projects | ../projects/ |
정책 및 권한 정의 |
| Argo CD ConfigMap | ../argocd/argocd-cm.yaml |
저장소, SSO, 알림 설정 |
| Environments | ../../environments/ |
인프라 정의 |
| Cluster Services | ../../cluster-services/ |
서비스 정의 |
| App Manifests | ../../app-manifests/ |
애플리케이션 정의 |
| GitLab | 외부 | 소스 저장소 |
Sync Wave 실행 순서
| Wave | 컴포넌트 | 목적 |
|---|---|---|
| -10 | app-of-apps | 루트 Application |
| -5 | namespaces, storage, coredns | 기초 인프라 |
| -3 | cert-manager | 인증서 발급 |
| -2 | openbao, secrets, external-secrets | 비밀값 관리 |
| -1 | istio-system, service-mesh | 서비스 메시 |
| 0 | argocd, rbac | GitOps 컨트롤 플레인 |
| 1 | monitoring, logging | 관찰성 |
| 5 | kyverno | 정책 엔포스먼트 |
| 10+ | 앱 | 비즈니스 애플리케이션 |
중요: ApplicationSet 생성 규칙을 정확히 따르면 Git 디렉토리 구조만으로 자동 Application 생성이 가능합니다.