- Published on
ArgoCD GitOps 완벽 가이드: ApplicationSet·Sync Waves·Hook으로 구현하는 Kubernetes 선언적 배포
- Authors
- Name
- 들어가며
- ArgoCD 아키텍처 개요
- Application 리소스 기본 구성
- AppProject로 RBAC 구현
- ApplicationSet 제너레이터
- Sync Waves를 통한 배포 순서 제어
- Sync Hook 활용
- 시크릿 관리
- 멀티 클러스터 배포
- 롤백 전략
- 모니터링 구성
- 운영 시 주의사항
- 장애 사례 및 복구 절차
- 마치며
- 참고자료

들어가며
GitOps는 Git을 Single Source of Truth로 사용하여 인프라와 애플리케이션의 원하는 상태를 선언적으로 관리하는 운영 패러다임입니다. ArgoCD는 Kubernetes 환경에서 GitOps를 구현하는 가장 널리 사용되는 도구로, CNCF Graduated 프로젝트로서 프로덕션 검증이 완료되었습니다.
이 글에서는 ArgoCD의 핵심 기능인 ApplicationSet을 통한 멀티 클러스터/환경 배포, Sync Waves와 Hook을 통한 배포 순서 제어, RBAC과 시크릿 관리까지 프로덕션 환경에서 필요한 모든 설정을 실전 코드와 함께 다룹니다.
ArgoCD 아키텍처 개요
ArgoCD는 다음과 같은 핵심 컴포넌트로 구성됩니다.
| 컴포넌트 | 역할 | 주요 기능 |
|---|---|---|
| API Server | 웹 UI, CLI, CI/CD 연동 | gRPC/REST API 제공, RBAC 처리 |
| Repo Server | Git 저장소 관리 | 매니페스트 생성(Helm, Kustomize, Plain YAML) |
| Application Controller | 핵심 조정 루프 | 클러스터 상태 감시, 동기화 실행 |
| ApplicationSet Controller | 다중 Application 생성 | 템플릿 기반 자동 Application 생성 |
| Redis | 캐시 | 매니페스트 캐싱, 클러스터 상태 캐싱 |
| Dex | 인증 | SSO, OIDC, LDAP 등 외부 인증 연동 |
ArgoCD 설치
# Namespace 생성 및 ArgoCD 설치
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 또는 Helm으로 설치 (프로덕션 권장)
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
--set server.service.type=LoadBalancer \
--set configs.params."server\.insecure"=true \
--set controller.replicas=2 \
--set repoServer.replicas=2 \
--set redis-ha.enabled=true
# 초기 admin 비밀번호 확인
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath='{.data.password}' | base64 -d
Application 리소스 기본 구성
Application 스펙 상세
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-application
namespace: argocd
# Finalizer: Application 삭제 시 클러스터 리소스도 함께 삭제
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: production
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: apps/my-app/overlays/production
# Kustomize 옵션
kustomize:
namePrefix: prod-
commonLabels:
env: production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Git에서 삭제된 리소스를 클러스터에서도 삭제
selfHeal: true # 수동 변경 시 자동 복구
allowEmpty: false # 빈 매니페스트 배포 방지
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
- ServerSideApply=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas # HPA 관리 대상이므로 무시
Helm 소스 설정
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prometheus-stack
namespace: argocd
spec:
project: monitoring
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 65.1.0
helm:
releaseName: prometheus
valuesObject:
grafana:
enabled: true
adminPassword: vault:secret/grafana#password
prometheus:
prometheusSpec:
retention: 30d
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: gp3
resources:
requests:
storage: 100Gi
destination:
server: https://kubernetes.default.svc
namespace: monitoring
AppProject로 RBAC 구현
프로젝트 정의
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
namespace: argocd
spec:
description: 'Production environment project'
# 허용된 소스 저장소
sourceRepos:
- 'https://github.com/myorg/k8s-manifests.git'
- 'https://github.com/myorg/helm-charts.git'
# 허용된 배포 대상
destinations:
- namespace: 'production'
server: 'https://kubernetes.default.svc'
- namespace: 'production-*'
server: 'https://kubernetes.default.svc'
# 허용된 클러스터 리소스
clusterResourceWhitelist:
- group: ''
kind: Namespace
- group: 'rbac.authorization.k8s.io'
kind: ClusterRole
- group: 'rbac.authorization.k8s.io'
kind: ClusterRoleBinding
# 차단된 네임스페이스 리소스
namespaceResourceBlacklist:
- group: ''
kind: ResourceQuota
- group: ''
kind: LimitRange
# RBAC 역할 정의
roles:
- name: deployer
description: 'Can sync and manage applications'
policies:
- p, proj:production:deployer, applications, get, production/*, allow
- p, proj:production:deployer, applications, sync, production/*, allow
- p, proj:production:deployer, applications, action/*, production/*, allow
groups:
- platform-team
- name: viewer
description: 'Read-only access'
policies:
- p, proj:production:viewer, applications, get, production/*, allow
groups:
- dev-team
ApplicationSet 제너레이터
Git Directory 제너레이터
Git 저장소의 디렉토리 구조를 기반으로 Application을 자동 생성합니다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: app-of-apps
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- git:
repoURL: https://github.com/myorg/k8s-manifests.git
revision: main
directories:
- path: 'apps/*/overlays/production'
- path: 'apps/deprecated-*'
exclude: true
template:
metadata:
name: '{{.path.basename}}'
namespace: argocd
labels:
app.kubernetes.io/managed-by: applicationset
spec:
project: production
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: '{{.path.path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true
Cluster 제너레이터
등록된 클러스터를 기반으로 멀티 클러스터 배포를 자동화합니다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-cluster-apps
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- clusters:
selector:
matchLabels:
env: production
matchExpressions:
- key: region
operator: In
values:
- ap-northeast-2
- us-west-2
- eu-west-1
template:
metadata:
name: 'app-{{.name}}'
namespace: argocd
spec:
project: production
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: 'apps/my-app/overlays/{{.metadata.labels.env}}'
kustomize:
commonLabels:
cluster: '{{.name}}'
region: '{{.metadata.labels.region}}'
destination:
server: '{{.server}}'
namespace: production
Matrix 제너레이터 (복합 조합)
두 제너레이터를 조합하여 모든 조합을 생성합니다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: matrix-deployment
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- matrix:
generators:
# 제너레이터 1: 클러스터 목록
- clusters:
selector:
matchLabels:
env: production
# 제너레이터 2: Git 디렉토리에서 앱 목록
- git:
repoURL: https://github.com/myorg/k8s-manifests.git
revision: main
directories:
- path: 'apps/*'
template:
metadata:
name: '{{.path.basename}}-{{.name}}'
namespace: argocd
spec:
project: production
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: '{{.path.path}}/overlays/production'
destination:
server: '{{.server}}'
namespace: '{{.path.basename}}'
List 제너레이터
정적 값 목록을 기반으로 Application을 생성합니다.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: environment-apps
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- list:
elements:
- env: dev
cluster: https://dev-k8s.example.com
revision: develop
replicas: '1'
- env: staging
cluster: https://staging-k8s.example.com
revision: release/v2.5
replicas: '2'
- env: production
cluster: https://kubernetes.default.svc
revision: main
replicas: '3'
template:
metadata:
name: 'my-app-{{.env}}'
namespace: argocd
spec:
project: '{{.env}}'
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: '{{.revision}}'
path: 'apps/my-app/overlays/{{.env}}'
destination:
server: '{{.cluster}}'
namespace: 'my-app-{{.env}}'
Sync Waves를 통한 배포 순서 제어
Sync Wave 기본 개념
Sync Wave는 argocd.argoproj.io/sync-wave 어노테이션으로 정의하며, 정수 값을 사용하여 낮은 값부터 순차적으로 배포합니다. 기본값은 0입니다.
# Wave -2: 네임스페이스와 RBAC (전제 조건)
apiVersion: v1
kind: Namespace
metadata:
name: production
annotations:
argocd.argoproj.io/sync-wave: '-2'
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-service-account
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '-2'
---
# Wave -1: ConfigMap과 Secret (설정)
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '-1'
data:
APP_ENV: production
LOG_LEVEL: info
---
# Wave 0: 핵심 애플리케이션 (기본값)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '0'
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
serviceAccountName: app-service-account
containers:
- name: app
image: myorg/my-app:v2.5.0
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
---
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '0'
spec:
selector:
app: my-app
ports:
- port: 8080
targetPort: 8080
---
# Wave 1: 의존 리소스 (Ingress, HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '1'
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
---
# Wave 2: 모니터링
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-app-monitor
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '2'
spec:
selector:
matchLabels:
app: my-app
endpoints:
- port: http
interval: 15s
Sync Hook 활용
PreSync Hook: 배포 전 데이터베이스 마이그레이션
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
namespace: production
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
argocd.argoproj.io/sync-wave: '-1'
spec:
backoffLimit: 3
template:
spec:
containers:
- name: migrate
image: myorg/db-migrator:v2.5.0
command: ['./migrate', 'up']
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
restartPolicy: Never
PostSync Hook: 배포 후 검증
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-test
namespace: production
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
backoffLimit: 1
template:
spec:
containers:
- name: smoke-test
image: myorg/smoke-tester:latest
command:
- /bin/sh
- -c
- |
echo "Running smoke tests..."
curl -sf http://my-app.production.svc:8080/healthz || exit 1
curl -sf http://my-app.production.svc:8080/api/v1/status || exit 1
echo "All smoke tests passed!"
restartPolicy: Never
SyncFail Hook: 동기화 실패 시 알림
apiVersion: batch/v1
kind: Job
metadata:
name: sync-fail-notification
namespace: production
annotations:
argocd.argoproj.io/hook: SyncFail
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
spec:
backoffLimit: 1
template:
spec:
containers:
- name: notify
image: curlimages/curl:latest
command:
- /bin/sh
- -c
- |
curl -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d '{"text":"ArgoCD Sync FAILED for my-app in production!"}'
env:
- name: SLACK_WEBHOOK_URL
valueFrom:
secretKeyRef:
name: slack-webhook
key: url
restartPolicy: Never
시크릿 관리
Sealed Secrets 연동
# Sealed Secrets 컨트롤러 설치
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets \
--namespace kube-system
# kubeseal CLI로 시크릿 암호화
kubectl create secret generic db-credentials \
--namespace production \
--from-literal=url='postgresql://user:pass@db:5432/mydb' \
--dry-run=client -o yaml | \
kubeseal --format yaml > sealed-db-credentials.yaml
# Git에 커밋 가능한 SealedSecret
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '-2'
spec:
encryptedData:
url: AgA2X5N0Q...encrypted...base64==
template:
metadata:
name: db-credentials
namespace: production
type: Opaque
External Secrets Operator 연동
# ExternalSecret: AWS Secrets Manager에서 시크릿 동기화
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: production
annotations:
argocd.argoproj.io/sync-wave: '-2'
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secretsmanager
kind: ClusterSecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: url
remoteRef:
key: production/database
property: connection_url
- secretKey: password
remoteRef:
key: production/database
property: password
---
# ClusterSecretStore 정의
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: aws-secretsmanager
spec:
provider:
aws:
service: SecretsManager
region: ap-northeast-2
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
namespace: external-secrets
멀티 클러스터 배포
클러스터 등록
# 대상 클러스터 등록 (kubeconfig 컨텍스트 기반)
argocd cluster add staging-cluster \
--name staging \
--label env=staging \
--label region=ap-northeast-2
argocd cluster add production-cluster \
--name production \
--label env=production \
--label region=ap-northeast-2
# 등록된 클러스터 확인
argocd cluster list
클러스터별 설정 분리
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: platform-services
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ['missingkey=error']
generators:
- matrix:
generators:
- clusters:
selector:
matchLabels:
env: production
- list:
elements:
- app: cert-manager
namespace: cert-manager
chart: cert-manager
repoURL: https://charts.jetstack.io
targetRevision: v1.16.0
- app: external-secrets
namespace: external-secrets
chart: external-secrets
repoURL: https://charts.external-secrets.io
targetRevision: 0.12.0
- app: metrics-server
namespace: kube-system
chart: metrics-server
repoURL: https://kubernetes-sigs.github.io/metrics-server
targetRevision: 3.12.0
template:
metadata:
name: '{{.app}}-{{.name}}'
namespace: argocd
spec:
project: platform
source:
repoURL: '{{.repoURL}}'
chart: '{{.chart}}'
targetRevision: '{{.targetRevision}}'
helm:
releaseName: '{{.app}}'
destination:
server: '{{.server}}'
namespace: '{{.namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
롤백 전략
자동 롤백 설정
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: production
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: apps/my-app/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 3
backoff:
duration: 10s
factor: 2
maxDuration: 5m
CLI를 통한 수동 롤백
# 배포 히스토리 확인
argocd app history my-app
# 특정 리비전으로 롤백
argocd app rollback my-app 5
# 또는 특정 Git 커밋으로 동기화
argocd app sync my-app --revision abc123def
# 동기화 상태 확인
argocd app get my-app
argocd app wait my-app --health
모니터링 구성
ArgoCD Prometheus 메트릭
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/part-of: argocd
endpoints:
- port: metrics
interval: 30s
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: argocd-alerts
namespace: argocd
spec:
groups:
- name: argocd
rules:
- alert: ArgoCDAppOutOfSync
expr: |
argocd_app_info{sync_status="OutOfSync"} == 1
for: 10m
labels:
severity: warning
annotations:
summary: 'Application {{ "{{" }} $labels.name {{ "}}" }} is OutOfSync for more than 10 minutes'
- alert: ArgoCDAppDegraded
expr: |
argocd_app_info{health_status="Degraded"} == 1
for: 5m
labels:
severity: critical
annotations:
summary: 'Application {{ "{{" }} $labels.name {{ "}}" }} is Degraded'
- alert: ArgoCDSyncFailed
expr: |
increase(argocd_app_sync_total{phase="Failed"}[10m]) > 0
labels:
severity: critical
annotations:
summary: 'ArgoCD sync failed for {{ "{{" }} $labels.name {{ "}}" }}'
Slack 알림 설정
# argocd-notifications-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
trigger.on-sync-failed: |
- when: app.status.operationState.phase in ['Error', 'Failed']
send: [app-sync-failed]
trigger.on-health-degraded: |
- when: app.status.health.status == 'Degraded'
send: [app-health-degraded]
trigger.on-sync-succeeded: |
- when: app.status.operationState.phase in ['Succeeded']
oncePer: app.status.sync.revision
send: [app-sync-succeeded]
template.app-sync-failed: |
slack:
attachments: |
[{
"color": "#E96D76",
"title": "Sync Failed: {{.app.metadata.name}}",
"text": "Application {{.app.metadata.name}} sync failed.\nRevision: {{.app.status.sync.revision}}\nMessage: {{.app.status.operationState.message}}"
}]
template.app-health-degraded: |
slack:
attachments: |
[{
"color": "#f4c030",
"title": "Health Degraded: {{.app.metadata.name}}",
"text": "Application {{.app.metadata.name}} health is degraded."
}]
template.app-sync-succeeded: |
slack:
attachments: |
[{
"color": "#18BE52",
"title": "Sync Succeeded: {{.app.metadata.name}}",
"text": "Application {{.app.metadata.name}} synced successfully.\nRevision: {{.app.status.sync.revision}}"
}]
운영 시 주의사항
1. ApplicationSet 보안
ApplicationSet의 project 필드가 템플릿화된 경우, 개발자가 과도한 권한을 가진 프로젝트에 Application을 생성할 수 있습니다. 항상 관리자가 제어하는 소스에서만 프로젝트 필드를 참조하도록 설정해야 합니다.
2. 자동 동기화 주의점
automated.prune: true는 Git에서 제거된 리소스를 클러스터에서 삭제합니다. 실수로 매니페스트를 삭제하면 프로덕션 리소스가 즉시 삭제될 수 있으므로, 중요 리소스에는 argocd.argoproj.io/sync-options: Prune=false 어노테이션을 추가하는 것을 권장합니다.
3. Webhook 보안
ArgoCD가 공개적으로 접근 가능한 경우, 반드시 Webhook 시크릿을 설정하여 DDoS 공격을 방지해야 합니다.
4. Repo Server 리소스
대규모 저장소나 Helm 차트를 처리할 때 Repo Server의 메모리 사용량이 급증할 수 있습니다. 적절한 리소스 제한과 레플리카 수를 설정해야 합니다.
5. 추상화 계층 제한
Application of Applications 패턴 사용 시 3단계 이상의 추상화를 피해야 합니다. 4-5단계의 중첩은 디버깅을 극도로 어렵게 만듭니다.
장애 사례 및 복구 절차
사례 1: Sync 무한 루프
# 증상: Application이 계속 Syncing 상태를 반복
# 원인: ignoreDifferences 미설정으로 인한 drift 감지
# 진단
argocd app diff my-app
argocd app get my-app --show-operation
# 복구: ignoreDifferences 추가
kubectl patch application my-app -n argocd --type merge -p '{
"spec": {
"ignoreDifferences": [
{
"group": "apps",
"kind": "Deployment",
"jsonPointers": ["/spec/replicas"]
}
]
}
}'
사례 2: Repo Server OOM
# 증상: Application이 Unknown 상태, 매니페스트 생성 실패
# 진단
kubectl logs -n argocd deploy/argocd-repo-server --previous
kubectl top pods -n argocd
# 복구: 리소스 제한 증가
kubectl patch deployment argocd-repo-server -n argocd --type json -p '[
{
"op": "replace",
"path": "/spec/template/spec/containers/0/resources/limits/memory",
"value": "4Gi"
}
]'
# Repo Server 재시작
kubectl rollout restart deployment/argocd-repo-server -n argocd
사례 3: 시크릿 동기화 실패 (External Secrets)
# 증상: Application은 Healthy이지만 Pod가 CrashLoopBackOff
# 원인: ExternalSecret이 아직 동기화되지 않음
# 진단
kubectl get externalsecret -n production
kubectl describe externalsecret db-credentials -n production
# 복구: ExternalSecret 강제 동기화
kubectl annotate externalsecret db-credentials \
-n production \
force-sync=$(date +%s) --overwrite
# 또는 Sync Wave로 순서 보장
# ExternalSecret: sync-wave=-2, Deployment: sync-wave=0
사례 4: ApplicationSet 의도치 않은 삭제
# 증상: ApplicationSet 수정 후 기존 Application이 삭제됨
# 원인: 제너레이터 설정 오류로 매칭되는 항목 감소
# 예방: preserveResourcesOnDeletion 설정
kubectl patch applicationset my-appset -n argocd --type merge -p '{
"spec": {
"syncPolicy": {
"preserveResourcesOnDeletion": true
}
}
}'
# 복구: Git 히스토리에서 이전 ApplicationSet 설정 복원
git log --oneline -- applicationsets/my-appset.yaml
git checkout HEAD~1 -- applicationsets/my-appset.yaml
git commit -m "Revert ApplicationSet to restore applications"
git push
마치며
ArgoCD는 GitOps의 핵심 도구로서, ApplicationSet을 통한 멀티 클러스터 자동화, Sync Waves와 Hook을 통한 정밀한 배포 순서 제어, 그리고 RBAC과 시크릿 관리를 통한 보안 강화까지 프로덕션 환경에서 필요한 모든 기능을 제공합니다.
핵심은 Git을 Single Source of Truth로 유지하면서, 적절한 자동화 수준을 설정하는 것입니다. 모든 환경에 자동 동기화를 적용하기보다는, 개발/스테이징에는 자동 동기화를, 프로덕션에는 수동 동기화를 적용하는 점진적 접근을 권장합니다. 모니터링과 알림을 반드시 함께 구성하여, 동기화 실패나 헬스 체크 이상을 신속하게 감지하고 대응할 수 있도록 하시기 바랍니다.