- Published on
ArgoCD + Argo Rollouts로 구현하는 GitOps 배포 전략 — Blue-Green, Canary 완벽 가이드
- Authors
- Name
- 들어가며
- GitOps 핵심 원칙
- ArgoCD 기본 구성
- Argo Rollouts 설치
- Blue-Green 배포
- Canary 배포
- AnalysisTemplate — 자동 분석
- Git 저장소 구조
- 알림 설정
- 운영 베스트 프랙티스
- 퀴즈
- 마무리
- 참고 자료

들어가며
GitOps는 Git을 Single Source of Truth로 사용하여 인프라와 애플리케이션의 원하는 상태를 선언적으로 관리하는 운영 패러다임입니다. ArgoCD는 Kubernetes 환경에서 GitOps를 구현하는 가장 널리 사용되는 도구이며, Argo Rollouts는 여기에 점진적 배포 전략을 추가합니다.
이 글에서는 ArgoCD + Argo Rollouts 조합으로 Blue-Green과 Canary 배포를 구현하는 방법을 실전 코드와 함께 살펴봅니다.
GitOps 핵심 원칙
GitOps의 4가지 원칙:
- 선언적(Declarative): 시스템의 원하는 상태를 선언적으로 기술
- 버전 관리(Versioned): 모든 상태가 Git에 저장되고 버전 관리
- 자동 적용(Automated): 승인된 변경사항이 자동으로 시스템에 적용
- 지속적 조정(Continuously Reconciled): 에이전트가 실제 상태와 원하는 상태를 지속 비교/조정
ArgoCD 기본 구성
Application 리소스
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
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
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
ApplicationSet으로 멀티 클러스터 관리
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: 'my-app-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/myorg/k8s-manifests.git
targetRevision: main
path: 'apps/my-app/overlays/{{metadata.labels.region}}'
destination:
server: '{{server}}'
namespace: production
Argo Rollouts 설치
# Argo Rollouts Controller 설치
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# kubectl 플러그인 설치
brew install argoproj/tap/kubectl-argo-rollouts
# 대시보드 실행
kubectl argo rollouts dashboard -n argo-rollouts
Blue-Green 배포
개념
Blue-Green 배포 플로우:
[사용자] → [Active Service] → [Blue (v1)] ← 현재 프로덕션
[Green (v2)] ← 새 버전 대기
전환 후:
[사용자] → [Active Service] → [Green (v2)] ← 새 프로덕션
[Blue (v1)] ← 이전 버전 (롤백 대비)
Rollout 리소스
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
namespace: production
spec:
replicas: 5
revisionHistoryLimit: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: myorg/my-app:v2.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
strategy:
blueGreen:
activeService: my-app-active
previewService: my-app-preview
autoPromotionEnabled: false
scaleDownDelaySeconds: 300
prePromotionAnalysis:
templates:
- templateName: smoke-test
args:
- name: service-name
value: my-app-preview
postPromotionAnalysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: my-app-active
---
apiVersion: v1
kind: Service
metadata:
name: my-app-active
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: my-app-preview
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
배포 관리 명령어
# 배포 상태 확인
kubectl argo rollouts get rollout my-app -n production -w
# 수동 프로모션 (Blue → Green 전환)
kubectl argo rollouts promote my-app -n production
# 롤백
kubectl argo rollouts undo my-app -n production
# 특정 리비전으로 롤백
kubectl argo rollouts undo my-app --to-revision=2 -n production
# 배포 중단
kubectl argo rollouts abort my-app -n production
Canary 배포
단계별 Canary 전략
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app-canary
spec:
replicas: 10
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: myorg/my-app:v2.0.0
ports:
- containerPort: 8080
strategy:
canary:
canaryService: my-app-canary
stableService: my-app-stable
steps:
# 5% 트래픽으로 시작
- setWeight: 5
- pause:
duration: 5m
# 자동 분석 실행
- analysis:
templates:
- templateName: error-rate-check
args:
- name: service-name
value: my-app-canary
# 20%로 확대
- setWeight: 20
- pause:
duration: 10m
- analysis:
templates:
- templateName: latency-check
# 50%로 확대
- setWeight: 50
- pause:
duration: 10m
- analysis:
templates:
- templateName: comprehensive-check
# 80%로 확대
- setWeight: 80
- pause:
duration: 5m
# 100% (프로모션 완료)
maxSurge: '25%'
maxUnavailable: 0
Istio와 연동한 트래픽 관리
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app-istio
spec:
replicas: 10
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: myorg/my-app:v2.0.0
strategy:
canary:
canaryService: my-app-canary
stableService: my-app-stable
trafficRouting:
istio:
virtualServices:
- name: my-app-vsvc
routes:
- primary
destinationRule:
name: my-app-destrule
canarySubsetName: canary
stableSubsetName: stable
steps:
- setWeight: 10
- pause: { duration: 5m }
- setWeight: 30
- pause: { duration: 5m }
- setWeight: 60
- pause: { duration: 5m }
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app-vsvc
spec:
hosts:
- my-app.example.com
http:
- name: primary
route:
- destination:
host: my-app-stable
weight: 100
- destination:
host: my-app-canary
weight: 0
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-app-destrule
spec:
host: my-app
subsets:
- name: stable
labels:
app: my-app
- name: canary
labels:
app: my-app
AnalysisTemplate — 자동 분석
Prometheus 기반 분석
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: error-rate-check
spec:
args:
- name: service-name
metrics:
- name: error-rate
interval: 60s
count: 5
successCondition: result[0] < 0.05
failureLimit: 3
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: latency-check
spec:
metrics:
- name: p99-latency
interval: 60s
count: 5
successCondition: result[0] < 500
failureLimit: 2
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.99,
sum(rate(http_request_duration_milliseconds_bucket{service="my-app"}[5m]))
by (le)
)
Webhook 기반 분석
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: smoke-test
spec:
args:
- name: service-name
metrics:
- name: smoke-test
count: 1
successCondition: result.status == "pass"
provider:
web:
url: 'http://test-runner.ci/api/v1/smoke-test'
method: POST
headers:
- key: Content-Type
value: application/json
body: |
{
"service": "{{args.service-name}}",
"tests": ["health", "basic-crud", "auth"]
}
jsonPath: '{$.result}'
timeoutSeconds: 120
Git 저장소 구조
k8s-manifests/
├── apps/
│ └── my-app/
│ ├── base/
│ │ ├── kustomization.yaml
│ │ ├── rollout.yaml
│ │ ├── service.yaml
│ │ └── analysis-templates.yaml
│ └── overlays/
│ ├── staging/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ │ └── rollout-strategy.yaml
│ └── production/
│ ├── kustomization.yaml
│ └── patches/
│ ├── rollout-strategy.yaml
│ └── replicas.yaml
├── infrastructure/
│ ├── argocd/
│ │ ├── argocd-cm.yaml
│ │ └── projects/
│ └── argo-rollouts/
│ └── install.yaml
└── applicationsets/
└── my-app.yaml
Kustomize 패치 예시
# overlays/production/patches/rollout-strategy.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 20
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 10m }
- analysis:
templates:
- templateName: error-rate-check
- setWeight: 25
- pause: { duration: 15m }
- setWeight: 50
- pause: { duration: 15m }
- setWeight: 75
- pause: { duration: 10m }
알림 설정
# ArgoCD Notification ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-sync-status: |
message: |
Application {{.app.metadata.name}} sync status: {{.app.status.sync.status}}
Health: {{.app.status.health.status}}
Revision: {{.app.status.sync.revision}}
trigger.on-sync-failed: |
- when: app.status.sync.status == 'OutOfSync' and app.status.health.status == 'Degraded'
send: [app-sync-status]
trigger.on-health-degraded: |
- when: app.status.health.status == 'Degraded'
send: [app-sync-status]
운영 베스트 프랙티스
1. Sync Wave로 배포 순서 제어
# ConfigMap 먼저 배포
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
argocd.argoproj.io/sync-wave: '-1'
---
# 그 다음 Rollout 배포
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
annotations:
argocd.argoproj.io/sync-wave: '0'
---
# 마지막으로 HPA 배포
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
annotations:
argocd.argoproj.io/sync-wave: '1'
2. 긴급 롤백 프로세스
# 방법 1: Argo Rollouts CLI
kubectl argo rollouts undo my-app -n production
# 방법 2: Git Revert (GitOps 방식)
git revert HEAD
git push origin main
# ArgoCD가 자동으로 이전 상태로 동기화
# 방법 3: ArgoCD UI에서 이전 리비전으로 Sync
argocd app sync my-app --revision <previous-commit-sha>
3. 시크릿 관리
# Sealed Secrets 사용
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-app-secrets
namespace: production
spec:
encryptedData:
DATABASE_URL: AgBy3i4OJSWK+PiTySYZZA9rO...
API_KEY: AgBy3i4OJSWK+PiTySYZZA9rO...
퀴즈
Q1. GitOps의 4가지 핵심 원칙은 무엇인가요?
선언적(Declarative), 버전 관리(Versioned), 자동 적용(Automated), 지속적 조정(Continuously Reconciled)입니다.
Q2. Blue-Green 배포에서 autoPromotionEnabled: false의 의미는?
새 버전(Green)이 준비되어도 자동으로 트래픽을 전환하지 않습니다. kubectl argo rollouts promote로 수동 승인이 필요합니다.
Q3. Canary 배포에서 AnalysisTemplate의 역할은?
각 Canary 단계에서 자동으로 메트릭(에러율, 레이턴시 등)을 분석하여 성공/실패를 판단합니다. 실패 시 자동 롤백됩니다.
Q4. ArgoCD의 selfHeal 옵션은 어떤 동작을 하나요?
누군가 kubectl로 직접 클러스터 리소스를 변경하면, ArgoCD가 이를 감지하고 Git에 정의된 상태로 자동 복원합니다.
Q5. Argo Rollouts에서 Istio와 연동하면 어떤 장점이 있나요?
Pod 수가 아닌 트래픽 비율로 정밀하게 Canary 트래픽을 제어할 수 있습니다. VirtualService의 weight를 Argo Rollouts가 자동 조정합니다.
Q6. Sync Wave 어노테이션의 용도는?
리소스 배포 순서를 제어합니다. 낮은 숫자가 먼저 배포됩니다 (예: ConfigMap(-1) → Rollout(0) → HPA(1)).
Q7. GitOps에서 시크릿을 안전하게 관리하는 방법은?
Sealed Secrets, SOPS, External Secrets Operator 등을 사용하여 암호화된 시크릿만 Git에 저장합니다. 평문 시크릿은 절대 커밋하지 않습니다.
마무리
ArgoCD와 Argo Rollouts의 조합은 Kubernetes 환경에서 가장 강력한 GitOps 배포 파이프라인을 제공합니다. Git을 기반으로 한 선언적 관리, 자동 분석 기반 프로모션/롤백, 그리고 Istio 연동을 통한 정밀한 트래픽 제어까지 — 프로덕션 배포의 안정성과 속도를 동시에 확보할 수 있습니다.