ArgoCD ApplicationSets
지원 버전: ArgoCD v2.9+ 마지막 업데이트: 2026년 2월 22일
목차
ApplicationSet 개요
ApplicationSet은 템플릿을 사용하여 여러 ArgoCD Application을 자동으로 생성하는 컨트롤러입니다. 대규모 배포, 멀티 클러스터 환경, 동적 환경 관리에 유용합니다.
기본 구조
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-applicationset
namespace: argocd
spec:
# 생성기: Application 생성에 사용할 데이터 소스
generators:
- list:
elements:
- name: dev
namespace: dev
- name: staging
namespace: staging
# 템플릿: 생성될 Application의 템플릿
template:
metadata:
name: 'myapp-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: 'environments/{{name}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true
# 동기화 정책
syncPolicy:
preserveResourcesOnDeletion: false # ApplicationSet 삭제 시 Application도 삭제
# 전략
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: env
operator: In
values:
- dev
- matchExpressions:
- key: env
operator: In
values:
- staging생성기 (Generators)
ApplicationSet은 9가지 생성기를 지원합니다.
1. List Generator
정적 목록에서 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: list-generator-example
namespace: argocd
spec:
generators:
- list:
elements:
- name: dev
namespace: dev-ns
cluster: https://dev-cluster.example.com
values:
replicas: "1"
environment: development
- name: staging
namespace: staging-ns
cluster: https://staging-cluster.example.com
values:
replicas: "2"
environment: staging
- name: prod
namespace: prod-ns
cluster: https://prod-cluster.example.com
values:
replicas: "5"
environment: production
template:
metadata:
name: 'myapp-{{name}}'
labels:
environment: '{{values.environment}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: 'k8s/{{name}}'
helm:
parameters:
- name: replicaCount
value: '{{values.replicas}}'
destination:
server: '{{cluster}}'
namespace: '{{namespace}}'2. Cluster Generator
ArgoCD에 등록된 클러스터에서 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-generator-example
namespace: argocd
spec:
generators:
- clusters:
# 모든 클러스터
selector: {}
# 또는 레이블 셀렉터
# selector:
# matchLabels:
# environment: production
# matchExpressions:
# - key: region
# operator: In
# values:
# - ap-northeast-2
# - us-west-2
values:
helmVersion: "3"
template:
metadata:
name: 'cluster-addons-{{name}}'
labels:
cluster: '{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/cluster-addons.git
targetRevision: main
path: addons
helm:
valueFiles:
- 'values-{{metadata.labels.environment}}.yaml'
destination:
server: '{{server}}'
namespace: kube-system클러스터 Secret에 레이블 추가:
apiVersion: v1
kind: Secret
metadata:
name: prod-cluster-secret
namespace: argocd
labels:
argocd.argoproj.io/secret-type: cluster
environment: production
region: ap-northeast-2
type: Opaque
stringData:
name: prod-cluster
server: https://prod-cluster.example.com
config: |
{
"bearerToken": "...",
"tlsClientConfig": {
"insecure": false,
"caData": "..."
}
}3. Git Generator - Directory
Git 저장소의 디렉토리 구조에서 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: git-directory-generator
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/gitops-repo.git
revision: main
directories:
# 포함할 디렉토리
- path: apps/*
# 제외할 디렉토리
- path: apps/excluded-app
exclude: true
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/gitops-repo.git
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true저장소 구조:
gitops-repo/
├── apps/
│ ├── frontend/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── backend/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ ├── database/
│ │ └── statefulset.yaml
│ └── excluded-app/ # 제외됨
│ └── ...4. Git Generator - File
Git 저장소의 JSON/YAML 파일에서 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: git-file-generator
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/gitops-config.git
revision: main
files:
- path: 'environments/*/config.json'
template:
metadata:
name: '{{name}}-app'
labels:
environment: '{{environment}}'
region: '{{region}}'
spec:
project: '{{project}}'
source:
repoURL: '{{repoURL}}'
targetRevision: '{{targetRevision}}'
path: '{{path}}'
helm:
valueFiles:
- 'values-{{environment}}.yaml'
parameters:
- name: image.tag
value: '{{imageTag}}'
destination:
server: '{{cluster}}'
namespace: '{{namespace}}'config.json 파일 예시:
{
"name": "myapp-dev",
"environment": "dev",
"region": "ap-northeast-2",
"project": "development",
"repoURL": "https://github.com/myorg/myapp.git",
"targetRevision": "develop",
"path": "helm/myapp",
"cluster": "https://dev-cluster.example.com",
"namespace": "myapp-dev",
"imageTag": "dev-latest"
}5. Matrix Generator
두 생성기의 조합을 생성합니다 (카테시안 곱):
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: matrix-generator-example
namespace: argocd
spec:
generators:
- matrix:
generators:
# 첫 번째 생성기: 클러스터
- clusters:
selector:
matchLabels:
environment: production
# 두 번째 생성기: 애플리케이션 목록
- list:
elements:
- app: frontend
port: "80"
- app: backend
port: "8080"
- app: api-gateway
port: "443"
template:
metadata:
name: '{{name}}-{{app}}'
labels:
cluster: '{{name}}'
app: '{{app}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/apps.git
targetRevision: main
path: '{{app}}'
helm:
parameters:
- name: clusterName
value: '{{name}}'
- name: service.port
value: '{{port}}'
destination:
server: '{{server}}'
namespace: '{{app}}'결과 예시 (3 클러스터 × 3 앱 = 9 Application):
- prod-ap-northeast-2-frontend
- prod-ap-northeast-2-backend
- prod-ap-northeast-2-api-gateway
- prod-us-west-2-frontend
- prod-us-west-2-backend
- prod-us-west-2-api-gateway
- ...
6. Merge Generator
여러 생성기의 출력을 병합합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: merge-generator-example
namespace: argocd
spec:
generators:
- merge:
mergeKeys:
- name # 병합 키
generators:
# 기본 설정
- list:
elements:
- name: dev
replicas: "1"
resources: small
- name: staging
replicas: "2"
resources: medium
- name: prod
replicas: "5"
resources: large
# 환경별 오버라이드
- list:
elements:
- name: dev
cluster: https://dev-cluster.example.com
namespace: dev-ns
- name: staging
cluster: https://staging-cluster.example.com
namespace: staging-ns
- name: prod
cluster: https://prod-cluster.example.com
namespace: prod-ns
replicas: "10" # prod만 오버라이드
template:
metadata:
name: 'myapp-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: helm
helm:
parameters:
- name: replicaCount
value: '{{replicas}}'
- name: resources
value: '{{resources}}'
destination:
server: '{{cluster}}'
namespace: '{{namespace}}'7. SCM Provider Generator
GitHub, GitLab 등의 조직/그룹을 스캔하여 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: scm-provider-generator
namespace: argocd
spec:
generators:
- scmProvider:
# GitHub
github:
organization: myorg
api: https://api.github.com/
tokenRef:
secretName: github-token
key: token
# 필터
filters:
- repositoryMatch: '^k8s-.*' # k8s-로 시작하는 저장소
branchMatch: main
- labelMatch: argocd-enabled # 토픽 레이블
# 또는 GitLab
# gitlab:
# group: mygroup
# includeSubgroups: true
# 또는 Bitbucket
# bitbucketServer:
# project: MYPROJ
template:
metadata:
name: '{{repository}}'
spec:
project: default
source:
repoURL: '{{url}}'
targetRevision: '{{branch}}'
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: '{{repository}}'
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true8. Pull Request Generator
Pull Request를 기반으로 Preview 환경을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pr-generator-example
namespace: argocd
spec:
generators:
- pullRequest:
github:
owner: myorg
repo: myapp
tokenRef:
secretName: github-token
key: token
# 레이블 필터
labels:
- preview
- deploy-preview
# 재확인 간격
requeueAfterSeconds: 60
template:
metadata:
name: 'myapp-pr-{{number}}'
labels:
app: myapp
pr: '{{number}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: '{{head_sha}}'
path: k8s
kustomize:
namePrefix: 'pr-{{number}}-'
commonLabels:
pr: '{{number}}'
destination:
server: https://kubernetes.default.svc
namespace: 'preview-pr-{{number}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=truePR이 병합/닫히면 Application이 자동 삭제됩니다.
9. Cluster Decision Resource Generator
외부 리소스(예: Placement)를 기반으로 클러스터를 선택합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-decision-resource-generator
namespace: argocd
spec:
generators:
- clusterDecisionResource:
# Duck-typing을 통한 리소스 참조
configMapRef: cluster-decisions
name: my-placement
requeueAfterSeconds: 180
labelSelector:
matchLabels:
environment: production
# 또는 values 추출
values:
region: '{{metadata.labels.region}}'
template:
metadata:
name: 'addon-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/cluster-addons.git
targetRevision: main
path: addons
destination:
server: '{{clusterName}}'
namespace: kube-system10. Plugin Generator
외부 서비스를 호출하여 Application을 생성합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: plugin-generator-example
namespace: argocd
spec:
generators:
- plugin:
configMapRef: my-plugin
input:
parameters:
environment: production
region: ap-northeast-2
requeueAfterSeconds: 300
template:
metadata:
name: '{{name}}'
spec:
project: default
source:
repoURL: '{{repoURL}}'
targetRevision: '{{revision}}'
path: '{{path}}'
destination:
server: '{{cluster}}'
namespace: '{{namespace}}'Plugin ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-plugin
namespace: argocd
data:
token: "$plugin.token" # Secret 참조
baseUrl: "https://api.example.com/applications"Go 템플릿
ApplicationSet은 Go 템플릿을 지원합니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: go-template-example
namespace: argocd
spec:
goTemplate: true # Go 템플릿 활성화
goTemplateOptions: ["missingkey=error"] # 누락된 키 오류 처리
generators:
- list:
elements:
- name: dev
replicas: 1
features:
- logging
- monitoring
- name: prod
replicas: 5
features:
- logging
- monitoring
- alerting
template:
metadata:
name: 'myapp-{{ .name }}'
annotations:
# 조건부 어노테이션
{{- if eq .name "prod" }}
notifications.argoproj.io/subscribe.on-sync-failed.slack: production-alerts
{{- end }}
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: helm
helm:
values: |
replicaCount: {{ .replicas }}
features:
{{- range .features }}
- {{ . }}
{{- end }}
destination:
server: https://kubernetes.default.svc
namespace: 'myapp-{{ .name }}'Go 템플릿 함수
# 문자열 조작
name: '{{ .name | upper }}' # 대문자
name: '{{ .name | lower }}' # 소문자
name: '{{ .name | title }}' # 타이틀 케이스
name: '{{ .name | replace "-" "_" }}' # 대체
# 조건
{{- if eq .environment "prod" }}
replicas: 5
{{- else }}
replicas: 1
{{- end }}
# 기본값
namespace: '{{ .namespace | default "default" }}'
# 반복
{{- range .items }}
- {{ . }}
{{- end }}
# 인덱스
value: '{{ index .values "key-with-dash" }}'Progressive Syncs
Progressive Syncs를 사용하면 Application을 단계적으로 롤아웃할 수 있습니다:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: progressive-sync-example
namespace: argocd
spec:
generators:
- list:
elements:
- name: dev
env: dev
- name: staging
env: staging
- name: prod-ap
env: prod
region: ap-northeast-2
- name: prod-us
env: prod
region: us-west-2
strategy:
type: RollingSync
rollingSync:
steps:
# Step 1: dev 먼저
- matchExpressions:
- key: env
operator: In
values:
- dev
# 최대 동시 업데이트 수
maxUpdate: 100% # 또는 숫자 (예: 1)
# Step 2: staging
- matchExpressions:
- key: env
operator: In
values:
- staging
# Step 3: prod (한 번에 하나씩)
- matchExpressions:
- key: env
operator: In
values:
- prod
maxUpdate: 1
template:
metadata:
name: 'myapp-{{name}}'
labels:
env: '{{env}}'
{{- if .region }}
region: '{{region}}'
{{- end }}
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: 'envs/{{env}}'
destination:
server: https://kubernetes.default.svc
namespace: 'myapp-{{name}}'Progressive Sync 흐름
멀티 클러스터 배포 패턴
패턴 1: 환경별 배포
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-env-deployment
namespace: argocd
spec:
generators:
- matrix:
generators:
- list:
elements:
- env: dev
cluster: https://dev.example.com
revision: develop
- env: staging
cluster: https://staging.example.com
revision: release
- env: prod
cluster: https://prod.example.com
revision: main
- git:
repoURL: https://github.com/myorg/apps.git
revision: main
directories:
- path: apps/*
template:
metadata:
name: '{{env}}-{{path.basename}}'
spec:
project: '{{env}}'
source:
repoURL: https://github.com/myorg/apps.git
targetRevision: '{{revision}}'
path: '{{path}}'
kustomize:
namePrefix: '{{env}}-'
destination:
server: '{{cluster}}'
namespace: '{{path.basename}}'패턴 2: 리전별 배포
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-region-deployment
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
environment: production
values:
helmRepo: https://charts.example.com
strategy:
type: RollingSync
rollingSync:
steps:
# AP 리전 먼저
- matchExpressions:
- key: region
operator: In
values:
- ap-northeast-2
- ap-southeast-1
# US 리전
- matchExpressions:
- key: region
operator: In
values:
- us-west-2
- us-east-1
# EU 리전 마지막
- matchExpressions:
- key: region
operator: In
values:
- eu-west-1
template:
metadata:
name: '{{name}}-platform-services'
labels:
cluster: '{{name}}'
region: '{{metadata.labels.region}}'
spec:
project: platform
source:
repoURL: '{{values.helmRepo}}'
chart: platform-services
targetRevision: 2.0.0
helm:
valueFiles:
- 'values-{{metadata.labels.region}}.yaml'
destination:
server: '{{server}}'
namespace: platform패턴 3: 테넌트별 배포
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tenant-deployment
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/myorg/tenant-config.git
revision: main
files:
- path: 'tenants/*/config.yaml'
template:
metadata:
name: 'tenant-{{tenant.name}}'
labels:
tenant: '{{tenant.name}}'
tier: '{{tenant.tier}}'
spec:
project: tenants
source:
repoURL: https://github.com/myorg/tenant-app.git
targetRevision: main
path: helm
helm:
values: |
tenant:
name: {{ tenant.name }}
tier: {{ tenant.tier }}
resources:
{{- if eq tenant.tier "enterprise" }}
requests:
cpu: "2"
memory: "4Gi"
{{- else }}
requests:
cpu: "500m"
memory: "1Gi"
{{- end }}
destination:
server: '{{cluster}}'
namespace: 'tenant-{{tenant.name}}'템플릿 오버라이드
생성기별 템플릿 오버라이드
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: template-override-example
namespace: argocd
spec:
generators:
- list:
elements:
- name: dev
env: development
- name: prod
env: production
# 이 생성기의 결과에만 적용되는 템플릿 오버라이드
template:
metadata:
annotations:
custom-annotation: 'from-list-generator'
- clusters:
selector:
matchLabels:
environment: staging
# 이 생성기의 결과에만 적용
template:
spec:
syncPolicy:
automated:
prune: false # staging은 prune 비활성화
# 기본 템플릿
template:
metadata:
name: 'app-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: main
path: manifests
destination:
server: https://kubernetes.default.svc
namespace: '{{name}}'
syncPolicy:
automated:
prune: true
selfHeal: true템플릿 병합 동작
다음 단계
트래픽 관리: Argo Rollouts를 통한 블루/그린, 카나리 배포를 구현하세요.
프로젝트와 RBAC: ApplicationSet과 함께 프로젝트를 사용하여 접근을 제어하세요.
모범 사례: ApplicationSet 사용 시 권장 패턴을 학습하세요.
참고 자료
퀴즈
이 장에서 배운 내용을 테스트하려면 ApplicationSets 퀴즈를 풀어보세요.