Argo CD로 GitOps 파이프라인 구축: App-of-Apps, 환경 분리, 자동 동기화/PR 기반 승격
Argo Rollouts로 카나리/블루그린을 자동화했다면, 이제 Argo CD로 배포 상태 = Git을 구현해 보겠습니다. 핵심은 “모든 클러스터 상태를 선언적으로 Git에 보관하고, Argo CD가 주기적으로 이를 관찰해 자동 동기화”하는 것입니다. 이 글은 App-of-Apps 패턴으로 다수의 애플리케이션을 관리하고, dev→staging→prod로 PR 승인 기반 승격을 만드는 실전 템플릿을 제공합니다.
1) 저장소 구조(권장 예시)
gitops/
├─ apps/ # 개별 앱 선언(Helm/Kustomize)
│ └─ order-api/
│ ├─ base/ # 공통 정의
│ │ ├─ kustomization.yaml
│ │ ├─ deployment.yaml
│ │ └─ service.yaml
│ └─ overlays/
│ ├─ dev/
│ │ ├─ kustomization.yaml
│ │ └─ values-dev.yaml
│ ├─ staging/
│ │ └─ ...
│ └─ prod/
│ └─ ...
└─ clusters/
├─ dev/
│ └─ root-app.yaml # App-of-Apps (dev)
├─ staging/
│ └─ root-app.yaml
└─ prod/
└─ root-app.yaml
한 줄 요약: apps/*에 앱 템플릿(Helm/Kustomize), clusters/*에 각 환경의 루트 앱을 둡니다. 루트 앱은 하위 앱들을 자식 App으로 선언해서 환경별 일괄 배포를 가능하게 합니다.
2) Argo CD 설치 및 최초 접근
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 초기 비밀번호
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
kubectl -n argocd port-forward svc/argocd-server 8080:443
# https://localhost:8080 접속 → admin / (초기 비번)
실서비스에서는 Ingress(또는 LB)를 붙이고 SSO/OIDC로 로그인 연동을 권장합니다.
3) App-of-Apps: 환경 루트 앱 정의
dev 클러스터의 루트 앱 예시입니다(스테이징/프로드는 repoURL/경로만 다르게 복제).
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/gitops.git
targetRevision: main
path: clusters/dev
directory:
recurse: true
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true # Git에 없는 리소스 삭제
selfHeal: true # 드리프트 자동 복구
syncOptions:
- CreateNamespace=true
clusters/dev 경로에는 실제로 “자식 App”들을 선언한 매니페스트(아래 4장)를 둡니다.
4) 자식 App 선언(여러 서비스 동시 관리)
예: dev 환경에 order-api, user-api를 함께 올립니다.
# clusters/dev/order-api.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: order-api-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/gitops.git
targetRevision: main
path: apps/order-api/overlays/dev
destination:
server: https://kubernetes.default.svc
namespace: order-api
syncPolicy:
automated: { prune: true, selfHeal: true }
syncOptions: [ "CreateNamespace=true" ]
---
# clusters/dev/user-api.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: user-api-dev
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/gitops.git
targetRevision: main
path: apps/user-api/overlays/dev
destination:
server: https://kubernetes.default.svc
namespace: user-api
syncPolicy:
automated: { prune: true, selfHeal: true }
이런 자식 App 파일들을 clusters/dev에 두고, 루트 앱(root-dev)이 재귀로 읽게 합니다.
5) Kustomize/Helm로 환경 차이 오버레이
order-api의 dev 오버레이 예시입니다.
# apps/order-api/overlays/dev/kustomization.yaml
resources:
- ../../base
patches:
- target:
kind: Deployment
name: order-api
path: patch-deploy.yaml
configMapGenerator:
- name: order-api-config
literals:
- SPRING_PROFILES_ACTIVE=dev
secretGenerator:
- name: db-secret
literals:
- DB_URL=jdbc:postgresql://dev-db:5432/shop
- DB_USER=shop
- DB_PASSWORD=devpass
generatorOptions:
disableNameSuffixHash: true
# apps/order-api/overlays/dev/patch-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
spec:
replicas: 2
template:
spec:
containers:
- name: app
image: registry.example.com/order-api:1.2.3-dev
env:
- name: JAVA_TOOL_OPTIONS
value: "-Xms512m -Xmx512m"
프로드에서는 replicas·리소스·이미지 태그·도메인·시크릿을 달리합니다. 비밀값은 시크릿 매니저(Sealed Secrets, External Secrets) 연계를 추천합니다.
6) PR 기반 승격(Promotion) 전략
- 개발 완료 → CI에서 이미지 태깅
:1.2.3및apps/order-api/overlays/dev의 태그 업데이트 PR 생성 - dev 동기화 OK → staging 브랜치(또는 폴더)로 동일 태그 PR
- staging에서 기능/성능 검증 OK → prod로 PR 머지 → Argo CD가 자동 배포
즉, 승격 행위는 YAML의 이미지 태그를 바꾸는 PR에 불과합니다. 기록이 남고, 롤백도 쉽습니다 (이전 커밋으로 되돌리기).
7) 동기화(자동/수동)와 보호장치
- 자동 동기화(
automated.prune/selfHeal): Git ≒ 클러스터 상태를 유지 - 수동 승인: prod만 manual sync로 두고, Merge 후
Sync버튼으로 승격 - Sync Waves: 종속성을 고려해 리소스를 순서대로 적용(인그레스→서비스→롤아웃)
# wave 주기(주석)
metadata:
annotations:
argocd.argoproj.io/sync-wave: "0" # 작은 숫자 먼저 적용
8) Rollouts 연계: 카나리 자동 승격/중단 포함
Argo CD는 단순히 매니페스트를 동기화합니다. 런타임 단계 제어는 Rollouts가 담당합니다. 즉, Git에 Rollout을 커밋하면, Argo CD가 이를 반영하고, Rollouts가 가중치 전환 + 지표 판정을 실행합니다. 실패 시 자동 중단/롤백이 일어나므로 GitOps + Progressive Delivery가 결합됩니다.
9) 알림/감시: 드리프트·Sync 실패·헬스 체크
- 드리프트: 클러스터에서 수동 변경 발생 시 OutOfSync 감지 → SelfHeal로 복구
- Sync 실패: Slack/Webhook 연동으로 이벤트 통지(Argo CD Notifications)
- 헬스: 애플리케이션 Health(Progressing/Degraded/Healthy)로 대시보드 모니터링
# Notifications 설정(요지)
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: xoxb-***
trigger.on-sync-failed: |
- when: app.status.operationState.phase in ['Error','Failed']
send: [slack]
template.slack: |
message: |
[{{.app.metadata.name}}] {{.app.status.operationState.phase}}
10) 보안/권한
- RBAC: prod 네임스페이스는 읽기 전용 역할을 대부분에게 부여, Sync 권한은 일부에 제한
- SSO/OIDC: 팀/조직 계정으로 접근 제어, 감사 로그 유지
- 비밀 관리: Sealed Secrets/External Secrets(Cloud KMS, Vault)로 Git 평문 방지
11) 트러블슈팅 빠른 분기
- OutOfSync 반복 → 클러스터 내 수동 변경 탐지,
selfHeal켜고, 원인 리소스에 주석/소유권 확인 - Sync 실패 →
Events에서 원인 확인(네임스페이스 권한/CRD 순서/헬름 차트 값) - 프로드만 자동 배포 금지 → prod 루트 앱에서
automated제거, 수동 Sync로 전환 - 분기/폴더 혼용 → “브랜치=환경”, “폴더=서비스” 원칙으로 단순화
12) 체크리스트(복붙용)
- 저장소 구조:
apps/*+clusters/*, 환경별 루트 앱(App-of-Apps) - Argo CD 설치, admin 초기 비밀번호 변경/SSO 적용
- 루트 앱 생성 → 자식 App 재귀 로딩 확인
- 자동 동기화(prune/selfHeal) 여부를 환경별로 결정
- PR 승인으로 이미지 태그 승격(dev→staging→prod)
- Rollouts와 결합: 카나리/블루그린 지표 판정 자동화
- 알림/감사: Notifications + RBAC + Sealed/External Secrets
Argo CD를 도입하면 “누가 언제 무엇을 배포했는가”가 Git 히스토리로 남습니다. PR 승인으로 승격하고, 실패 시 커밋 하나로 롤백하세요. 이것이 안전하고 재현 가능한 운영의 출발점입니다.
'배포·CI,CD·클라우드' 카테고리의 다른 글
| Velero로 Kubernetes 백업·복구: S3/MinIO 연동, PV 스냅샷, 네임스페이스 단위 복원 (0) | 2025.11.02 |
|---|---|
| External Secrets로 시크릿 자동 주입: AWS Secrets Manager/KMS · Kubernetes 네이티브 시크릿 관리 (1) | 2025.11.01 |
| Argo Rollouts로 프로그레시브 딜리버리: Canary/Blue-Green, 자동 프로모션·중단, 메트릭 연동(Prometheus) (0) | 2025.10.31 |
| KEDA + Prometheus Adapter로 HPA 커스텀 메트릭 오토스케일링(스레드·큐·지연 기반) (0) | 2025.10.31 |
| GitHub Actions: push 시 테스트 자동화 YAML (0) | 2025.10.04 |