ArgoCD Rollout Blue/Green, Canary
Blue/Green 및 Canary 배포 전략으로 무중단 배포, 롤백을 통해 서비스 안정성을 높일 수 있습니다.
개요
Blue/Green 배포
Blue/Green 배포는 동일한 프로덕션 환경을 두 벌로 구성하여 무중단 배포를 실현하는 전략입니다. 한 환경(Blue)이 실제 운영 중일 때 다른 환경(Green)에 새 버전을 배포하고 테스트한 후, 트래픽을 전환하는 방식입니다.
주요 특징
- 무중단 배포: 사용자 서비스 중단 없이 새 버전 배포 가능
- 빠른 롤백: 문제 발생 시 즉시 이전 환경으로 전환 가능
- 안전성: 새 버전을 실제 환경과 동일한 조건에서 완벽하게 테스트 가능
ArgoCD 구현 방식
- 두 개의 Deployment 관리
- Blue 환경용 Deployment
- Green 환경용 Deployment
- Service를 통한 트래픽 제어
- selector를 사용하여 활성 환경 지정
- 라벨링을 통한 트래픽 전환
- 배포 프로세스
- 비활성 환경에 새 버전 배포
- 새 버전 테스트 및 검증
- Service selector 변경으로 트래픽 전환
- 이전 환경 정리 또는 대기
Canary 배포
개요
Canary 배포는 새로운 버전을 점진적으로 도입하는 전략입니다. 소수의 사용자에게 새 버전을 먼저 제공하고, 모니터링을 통해 안정성을 확인한 후 점차 트래픽 비율을 늘려가는 방식입니다.
주요 특징
- 위험 최소화: 문제 발생 시 영향받는 사용자 수 제한
- 점진적 롤아웃: 트래픽을 단계적으로 전환
- 실시간 모니터링: 새 버전의 성능과 안정성을 실제 사용자 환경에서 검증
ArgoCD 구현 방식
- Argo Rollouts 사용
- Kubernetes native Rollout 리소스 활용
- 트래픽 가중치 설정 가능
- 배포 설정
- 초기 트래픽 비율 설정 (예: 10%)
- 단계별 증가 비율 정의
- 성공/실패 메트릭 설정
- 배포 프로세스
- 새 버전 초기 배포
- 메트릭 기반 모니터링
- 점진적 트래픽 증가
- 문제 발생 시 자동 롤백
전략 선택 기준
Blue/Green 배포 적합 상황
- 즉각적인 전체 롤백이 필요한 경우
- 새 버전 전체 테스트가 필요한 경우
- 리소스 여유가 충분한 경우
Canary 배포 적합 상황
- 점진적인 위험 관리가 필요한 경우
- 실제 사용자 피드백이 중요한 경우
- 리소스를 효율적으로 사용해야 하는 경우
구현 시 고려사항
- 배포 상태 모니터링
- 자동 롤백 조건 설정
- 배포 승인 프로세스
- 리소스 산정 및 비용 최적화
Preinstall
Package & Plugin Install
💡 Argo CD에 Argo Rollouts 라는 새로운 플러그인을 추가해야합니다.
- Docs & Repo
- kubectl 통합
brew install argoproj/tap/kubectl-argo-rollouts
# argo-rollout auto complete
sudo bash -c 'cat <<EOF >/usr/local/bin/kubectl_complete-argo-rollouts
#!/usr/bin/env sh
kubectl argo rollouts __complete "\$@"
EOF'
sudo chmod +x /usr/local/bin/kubectl_complete-argo-rollouts
echo "source <(kubectl-argo-rollouts completion zsh)" >> ~/.zshrc
source ~/.zshrc
테스트 코드
Deployment
를 모두 Argo Rollout API(argoproj.io/v1alpha1
)를 사용하여 전환하여야합니다.
Kustomize를 사용하고 있으며 각 배포별 strategy를 확인하면 됩니다. 예시는 다음과 같습니다.
#kustomize/base/rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: test-app
spec:
replicas: 1
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
app: test-app
spec:
containers:
- name: test-app
image: test-ecr
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"
Blue/Green 배포 전환
Blue/Green 작업을 진행하기 위해선 UI 작업, CLI 작업 등 다양한 방법이 가능합니다.
Blue/Green 작업 strategy는 다음과 같습니다.
# overlays/dev/strategy-patch.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: test-app
spec:
strategy:
blueGreen:
activeService: dev-test-app-active
previewService: dev-test-app-preview
scaleDownDelaySeconds: 300
autoPromotionEnabled: false # 수동 승인 필요
Argo Dashboard
kubectl
에서 argo rollouts 커맨드를 통합하였다면 아래 스크립트를 실행하게 된다면 localhost:3100
포트로 동작하게 됩니다.
$ k argo rollouts dashboard -n dev
INFO[0000] Argo Rollouts Dashboard is now available at http://localhost:3100/rollouts
ArgoCD rollout 대시보드 상에서 배포 전략과 Revision 정보들을 확인해볼 수 있습니다.
그냥 ArgoCD Dashboard에서도 마찬가지로 확인할 수 있습니다.

ArgoCD Dashboard를 확인해봤을 때 총 12개의 Replicaset을 확인할 수 있습니다.

Dashboard

대시보드상에서는 배포하려는 rollout을 Promote하면 됩니다.

Promote 하게 된다면 해당 작업은 scaleDownDelaySeconds에 따라 시간이 지난 후 종료되며 옵션은 다음과 같습니다.
strategy:
blueGreen:
activeService: dev-test-app-active
previewService: dev-test-app-preview
scaleDownDelaySeconds: 300 # 스메일 다운 지연시간
autoPromotionEnabled: false # Auto Promotion Off
배포가 완료되면 정상적으로 리소스가 전환 후 삭제되는 것을 확인해볼 수 있습니다.

CLI
명령어는 아래와 같이 실행되며 Status
에 집중해야합니다.
Status가 "Paused" 상태인 것은 새로운 버전(Green)이 배포되어 준비는 되었지만, 실제 트래픽 전환을 위해 사용자의 승인(promote)을 기다리고 있다는 의미입니다.
$ kubectl argo rollouts get rollout <ROLLOUT_NAME> -n <NAMESPACE>
# 예시와 같이 출력됩니다.
Name: dev-test-app
Namespace: dev
Status: ॥ Paused
Message: BlueGreenPause
Strategy: BlueGreen
Images: 759320821027.dkr.ecr.ap-northeast-2.amazonaws.com/bjchoi/test-ecr:20241205.0323.dcb1ce3 (stable, active)
759320821027.dkr.ecr.ap-northeast-2.amazonaws.com/bjchoi/test-ecr:20241205.0421.c1dd96e (preview)
Replicas:
Desired: 6
Current: 12
Updated: 6
Ready: 6
Available: 6
NAME KIND STATUS AGE INFO
⟳ dev-test-app Rollout ॥ Paused 170m
├──# revision:5
│ └──⧉
dev-test-app-69bd9b9df7
ReplicaSet ✔ Healthy 58s preview
│ ├──□ dev-test-app-69bd9b9df7-2wxlm Pod ✔ Running 58s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-mcmqg Pod ✔ Running 58s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-skhls Pod ✔ Running 58s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-th2cj Pod ✔ Running 58s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-vcxzp Pod ✔ Running 58s ready:1/1
│ └──□ dev-test-app-69bd9b9df7-xd9j2 Pod ✔ Running 58s ready:1/1
├──# revision:4
│ └──⧉
dev-test-app-696b6f9c6f
ReplicaSet ✔ Healthy 57m stable,active
│ ├──□ dev-test-app-696b6f9c6f-2gg9z Pod ✔ Running 57m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-4sln2 Pod ✔ Running 57m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-7q4pf Pod ✔ Running 57m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-8cqdx Pod ✔ Running 57m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-n2mw6 Pod ✔ Running 57m ready:1/1
│ └──□ dev-test-app-696b6f9c6f-tnkr5 Pod ✔ Running 57m ready:1/1
├──# revision:3
│ └──⧉ dev-test-app-5b494976c4 ReplicaSet • ScaledDown 132m
├──# revision:2
│ └──⧉ dev-test-app-6954c64b9c ReplicaSet • ScaledDown 137m
└──# revision:1
└──⧉ dev-test-app-7bdb9dc4fd ReplicaSet • ScaledDown 143m
정상적으로 올라온게 확인되었다면 Promote 합니다
argo rollouts promote -n dev dev-test-app
rollout 'dev-test-app' promoted
Promote가 실행되었다면 새 버전(revision:5)이 현재 stable과 active 상태로 변경되었다는 것을 확인할 수 있고 전체적인 Rollout 상태가 "✔ Healthy"로 표시되어 있습니다.
이전 버전(revision:4)은 아직 실행 중(Delay)이지만 delay:4m4s
로 표시되어 있는 것을 보아 곧 Scale Down될 예정입니다
Name: dev-test-app
Namespace: dev
Status: ✔ Healthy
Strategy: BlueGreen
Images: 759320821027.dkr.ecr.ap-northeast-2.amazonaws.com/bjchoi/test-ecr:20241205.0323.dcb1ce3
759320821027.dkr.ecr.ap-northeast-2.amazonaws.com/bjchoi/test-ecr:20241205.0421.c1dd96e (stable, active)
Replicas:
Desired: 6
Current: 12
Updated: 6
Ready: 6
Available: 6
NAME KIND STATUS AGE INFO
⟳ dev-test-app Rollout ✔ Healthy 173m
├──# revision:5
│ └──⧉ dev-test-app-69bd9b9df7 ReplicaSet ✔ Healthy 3m36s stable,active
│ ├──□ dev-test-app-69bd9b9df7-2wxlm Pod ✔ Running 3m36s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-mcmqg Pod ✔ Running 3m36s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-skhls Pod ✔ Running 3m36s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-th2cj Pod ✔ Running 3m36s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-vcxzp Pod ✔ Running 3m36s ready:1/1
│ └──□ dev-test-app-69bd9b9df7-xd9j2 Pod ✔ Running 3m36s ready:1/1
├──# revision:4
│ └──⧉ dev-test-app-696b6f9c6f ReplicaSet ✔ Healthy 59m delay:4m4s
│ ├──□ dev-test-app-696b6f9c6f-2gg9z Pod ✔ Running 59m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-4sln2 Pod ✔ Running 59m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-7q4pf Pod ✔ Running 59m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-8cqdx Pod ✔ Running 59m ready:1/1
│ ├──□ dev-test-app-696b6f9c6f-n2mw6 Pod ✔ Running 59m ready:1/1
│ └──□ dev-test-app-696b6f9c6f-tnkr5 Pod ✔ Running 59m ready:1/1
├──# revision:3
│ └──⧉ dev-test-app-5b494976c4 ReplicaSet • ScaledDown 134m
├──# revision:2
│ └──⧉ dev-test-app-6954c64b9c ReplicaSet • ScaledDown 140m
└──# revision:1
└──⧉ dev-test-app-7bdb9dc4fd ReplicaSet • ScaledDown 146m
정상적으로 원복된 것을 확인할 수 있습니다.
Name: dev-test-app
Namespace: dev
Status: ✔ Healthy
Strategy: BlueGreen
Images: 759320821027.dkr.ecr.ap-northeast-2.amazonaws.com/bjchoi/test-ecr:20241205.0421.c1dd96e (stable, active)
Replicas:
Desired: 6
Current: 6
Updated: 6
Ready: 6
Available: 6
NAME KIND STATUS AGE INFO
⟳ dev-test-app Rollout ✔ Healthy 177m
├──# revision:5
│ └──⧉ dev-test-app-69bd9b9df7 ReplicaSet ✔ Healthy 8m26s stable,active
│ ├──□ dev-test-app-69bd9b9df7-2wxlm Pod ✔ Running 8m26s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-mcmqg Pod ✔ Running 8m26s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-skhls Pod ✔ Running 8m26s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-th2cj Pod ✔ Running 8m26s ready:1/1
│ ├──□ dev-test-app-69bd9b9df7-vcxzp Pod ✔ Running 8m26s ready:1/1
│ └──□ dev-test-app-69bd9b9df7-xd9j2 Pod ✔ Running 8m26s ready:1/1
├──# revision:4
│ └──⧉ dev-test-app-696b6f9c6f ReplicaSet • ScaledDown 64m
├──# revision:3
│ └──⧉ dev-test-app-5b494976c4 ReplicaSet • ScaledDown 139m
├──# revision:2
│ └──⧉ dev-test-app-6954c64b9c ReplicaSet • ScaledDown 144m
└──# revision:1
└──⧉ dev-test-app-7bdb9dc4fd ReplicaSet • ScaledDown 150m
Blue/Green Fallback
Fallback의 경우도 동일하게 동작합니다.
단 그린 인스턴스가 모두 Health가 되었을 때 동작합니다. 하지만 주의할 점은 직접적으로 자동 Rollback을 제어하는 설정은 현재 Argo Rollouts 설정에 없으므로 만약 Rollback 해야하는 경우가 있다면 관리자가 판단 후 진행해야하며 이를 위해 scaleDownDelaySeconds을 설정하여 작업 중 자유로운 작업 전환이 가능해집니다.

Canary
Canary 작업 strategy는 다음과 같습니다.
Argo Rollouts의 Canary 배포에서는 단계별로 새로운 버전의 파드를 생성하고 이전 버전의 파드를 축소합니다. 이를 확인해보기 위해 파드를 10개로 조절하고 2개씩 조절되는지 확인해보도록 하겠습니다.
- 20% → 2분 대기
- 40% → 2분 대기
- 60% → 2분 대기
- 80% → 2분 대기
pause: {}
→ 100% 전환을 위해 수동 승인이 필요
# overlays/dev/strategy-patch.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: test-app
spec:
strategy:
canary:
stableService: dev-test-app-active # 기존 activeService가 stableService로 변경
canaryService: dev-test-app-preview # 기존 previewService가 canaryService로 변경
steps:
- setWeight: 20 # 첫 단계: 트래픽 20% 전환
- pause: {duration: 2m} # 10분 대기
- setWeight: 40 # 트래픽 40%로 증가
- pause: {duration: 2m}
- setWeight: 60 # 트래픽 60%로 증가
- pause: {duration: 2m}
- setWeight: 80 # 트래픽 80%로 증가
- pause: {duration: 2m}
# 수동 승인이 필요한 최종 단계
- pause: {} # 100% 전환 (수동 승인 필요)
Canary Dashboard
카나리 배포가 시작되면 다음과 같이 Strategy와 Weight을 확인할 수 있습니다.
20% 씩 트래픽이 전환되며 자세한 내용은 상세 페이지에서 확인할 수 있습니다.

현재 어느 단계를 수행하고 있는지 확인할 수 있습니다.


최종 단계는 Pause되어있기 때문에 앞선 Blue/Green 작업처럼 Promote해야 배포될 수 있습니다.

하지만 실제 테스트해보면 트래픽은 새로운 카나리 배포로 라우팅되지 않습니다.
왜냐하면 Load Balancer에서는 새로운 파드를 새로운 리소스로 인식하기 때문입니다. 이럴 때는 Canary 배포임에도 불구하고 Blue/Green처럼 동작하며 실제 리소스는 축소되기 때문에 trafficRouting
을 추가하여 기존의 ingress 설정에 리소스를 추가해야한다고 명시하여야 합니다.
canary:
maxSurge: "20%" # 최대 초과 생성 허용 Pod 수 (백분율 또는 정수)
maxUnavailable: 0 # 동시에 사용 불가능한 최대 Pod 수
stableService: dev-test-app-active
canaryService: dev-test-app-preview
trafficRouting:
alb:
ingress: dev-test-app
servicePort: 80
rootService: dev-test-app-active
steps:
- setWeight: 20 # 트래픽 20% 전환
- pause: {duration: 1m}
- setWeight: 40 # 트래픽 40%로 증가
- pause: {duration: 1m}
- setWeight: 60 # 트래픽 60%로 증가
- pause: {duration: 30s}
- setWeight: 80 # 트래픽 80%로 증가
- pause: {duration: 30s}
# 수동 승인이 필요한 최종 단계
- pause: {} # 무기한 일시 중지 (수동 승인 필요)
- Ingress 수정
- port로
use-annotation
을 추가합니다.- 해당 port는
Rollout
yaml에서 servicePort로 사용하게 됩니다.
- 해당 port는
- 카나리 배포가 시작됩니다.
- port로
rootService 지정 및 annotation으로 설정
# overlay/dev/ingress-patch.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-app
spec:
rules:
- host: bjchoi.saops.smileshark.help
http:
paths:
- path: /
pathType: Prefix
backend:
service: name: dev-test-app-active # rootService 지정이 필요합니다 port:
name: use-annotation
자세한 내용은 아래 링크를 통해 확인할 수 있으며 Application Load Balancer의 기본 기능들도 활용 가능합니다.
최종 트래픽이 전환되는 과정입니다.
이때 각 파드는 모두 축소되지 않고 동작하며 단순 트래픽만 가중치에 따라 전달됩니다. Promote시 최종적으로 모든 트래픽이 전환되며 종료됩니다.




또한 최종적으로 대상그룹은 삭제되지 않습니다. 이후 새로운 파드가 추가되면 기존 대상 그룹에 리소스가 추가되고 가중치가 조절되는 방식으로 진행되며, 이후 진행 방식은 동일합니다.
- 트래픽 분배는 ALB의 action annotation을 통해 이루어지게 됩니다.
결론
이러한 배포 방식 외에도 Argo Rollouts의 abort
명령어 등을 통해 진행 중인 Rollout을 중단하고 이전 stable 버전으로 돌아가거나 배포 과정 중 에러 메시지 확인을 통해 수월하게 CI/CD 작업을 진행할 수 있습니다.