Blue/Green 배포란?
구버전(Blue)과 새로운 버전(Green)을 동시에 유지하면서 배포하는 방식입니다. 이 배포 방식에서 구버전과 동일한 환경에 새로운 버전을 구성하고, 테스트 후 새로운 버전으로 트래픽을 전환합니다. 만약 문제가 발생하면 트래픽을 다시 구버전으로 돌려 빠른 롤백이 가능합니다.
장점
- 실제 운영 환경 테스트: 새로운 버전을 구버전과 동일한 환경에서 테스트할 수 있습니다.
- 빠른 롤백: 트래픽을 쉽게 구버전으로 전환할 수 있어 빠른 복구가 가능합니다.
단점
- 비용: 두 가지 환경(Blue와 Green)을 동시에 유지해야 하기 때문에 자원이 두 배로 필요합니다.
Argo CD를 이용한 Blue/Green 배포의 필요성
Kubernetes의 기본 배포 방식은 Rolling Update입니다. 롤링 업데이트는 새로운 버전의 파드를 하나씩 늘리고, 구버전 파드를 하나씩 줄여가는 방식으로, 무중단 배포가 가능합니다. 그러나 롤링 업데이트는 Blue/Green 방식만큼 빠른 롤백을 보장하지 못할 수 있습니다. Argo CD를 활용하면 GitOps 방식으로 배포를 관리하고, 선언형 방식으로 배포 상태를 관리하기 때문에 더 효율적이고 신뢰성 있는 Blue/Green 배포가 가능합니다.
장점
- 자동화된 배포 관리: Git에 저장된 선언형 매니페스트를 기반으로 자동화된 배포를 관리합니다.
- 롤백 기능 강화: 버전 관리 및 배포 기록이 남아 빠른 롤백이 가능합니다.
- 배포 상태 추적: 클러스터 상태와 선언한 배포 상태를 비교하여 실시간 모니터링 및 동기화를 지원합니다.
단점
- Rollout 속도 제어 어려움: 새로운 버전으로의 전환 속도를 세밀하게 제어하기가 어렵습니다.
- 트래픽 제어 한계: 새로운 버전으로 트래픽 흐름을 완전히 통제하는 기능이 부족합니다.
- 업데이트 중단 가능하나 롤백 자동화 부족: 수동으로 업데이트를 중단할 수는 있지만, 실패 시 자동으로 롤백하는 등의 고급 기능이 제공되지 않습니다.
Blue/Green 배포 시 발생하는 문제
- blast radius 제어 부족: 배포 실패 시 그로 인한 영향을 제한적으로 관리할 수 있는 기능이 부족합니다.
- 공격적 Rollout 가능성: 한 번에 대규모로 배포를 진행할 수 있어, 문제가 발생할 경우 큰 영향을 미칠 수 있습니다.
- 자동 롤백 미지원: 배포 실패 시 자동으로 롤백하는 기능이 없어, 수동으로 복구해야 할 위험이 있습니다.
Argo Rollouts의 Blue/Green 배포
Argo Rollouts를 사용하면 이러한 단점들을 해결할 수 있습니다. 주요 기능은 다음과 같습니다.
- Blue/Green 업데이트 전략: 새로운 버전을 배포한 후, 트래픽을 점진적으로 전환하고 테스트 후 문제가 없으면 새로운 버전을 활성화합니다.
- 자동 롤백 지원: 배포 실패 시 자동으로 이전 버전으로 롤백할 수 있는 기능을 제공해 위험을 줄입니다.
- 세밀한 트래픽 제어: Argo Rollouts는 트래픽을 분산하여 새로운 버전으로의 전환을 점진적으로 수행할 수 있습니다.
- blast radius 제어: 배포 중 문제가 발생한 경우 영향 범위를 제한하여 관리할 수 있는 기능을 제공합니다.
Installation
# ArgoCD 네임스페이스 생성
kubectl create namespace argocd
# ArgoCD 설치
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# ArgoCD 대시보드 접속
kubectl port-forward svc/argocd-server -n argocd 8080:443
브라우저에서 https://localhost:8080으로 접속하여 Argo CD 대시보드에 로그인합니다.
# ArgoCD 사용자명 admin 비밀번호 하단의 명령어로 확인
kubectl get pods -n argocd
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 --decode
vAHSasU-pTtmDcri
# Argo Rollouts 설치
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml
# Blue/Green 배포 테스트를 위한 네임스페이스 생성
kubectl create namespace bluegreen-test
이제 ArgoCD와 Argo Rollouts를 통해 Blue/Green 배포를 설정할 수 있습니다. 앞서 설명한 것 처럼 rollout.yaml 파일을 사용하여 배포를 진행합니다.
# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-bluegreen
namespace: bluegreen-test
spec:
replicas: 2
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollout-bluegreen
template:
metadata:
labels:
app: rollout-bluegreen
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
blueGreen:
activeService: rollout-bluegreen-active
previewService: rollout-bluegreen-preview
autoPromotionEnabled: false
---
kind: Service
# rollout.yaml
apiVersion: v1
metadata:
name: rollout-bluegreen-active
namespace: bluegreen-test
spec:
type: NodePort
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30081
---
kind: Service
apiVersion: v1
metadata:
name: rollout-bluegreen-preview
namespace: bluegreen-test
spec:
type: NodePort
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30082
ptty@pttyui-MacBookPro ~ % vi rollout.yaml
ptty@pttyui-MacBookPro ~ % k apply -f rollout.yaml
rollout.argoproj.io/rollout-bluegreen created
service/rollout-bluegreen-active created
service/rollout-bluegreen-preview created
위 매니페스트는 두 개의 서비스 rollout-bluegreen-active, rollout-bluegreen-preview를 정의하고 각각 현재 활성화된 애플리케이션과 미리보기 애플리케이션으로 구분됩니다.
Rollout 상태 확인
kubectl argo rollouts get rollout rollout-bluegreen -n bluegreen-test --watch
Name: rollout-bluegreen
Namespace: bluegreen-test
Status: ✔ Healthy
Strategy: BlueGreen
Images: argoproj/rollouts-demo:blue (stable, active)
Replicas:
Desired: 2
Current: 2
Updated: 2
Ready: 2
Available: 2
NAME KIND STATUS AGE INFO
⟳ rollout-bluegreen Rollout ✔ Healthy 4m9s
└──# revision:1
└──⧉ rollout-bluegreen-5ffd47b8d4 ReplicaSet ✔ Healthy 4m8s stable,active
├──□ rollout-bluegreen-5ffd47b8d4-82qzc Pod ✔ Running 4m8s ready:1/1
└──□ rollout-bluegreen-5ffd47b8d4-dsvkk Pod ✔ Running 4m8s ready:1/1
Rollout-pod-template-hash 를 나타냅니다. 두 개의 pod이 동일한 replicaset 과 연결된 것을 확인할 수 있습니다.
Service 확인
ptty@pttyui-MacBookPro ~ % k get svc -n bluegreen-test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rollout-bluegreen-active NodePort 192.168.135.80 <none> 80:30081/TCP 17m
rollout-bluegreen-preview NodePort 192.168.135.192 <none> 80:30082/TCP 17m
# Active 서비스 접근
kubectl port-forward svc/rollout-bluegreen-active 8080:80 -n bluegreen-test
# Preview 서비스 접근
kubectl port-forward svc/rollout-bluegreen-preview 8081:80 -n bluegreen-test
Active와 Preview 모두 Blue로 배포되어 있습니다.
이제 Rollout의 이미지 버전을 Blue -> Green 으로 변경하여 재배포합니다.
# rollout.yaml 에서 blue -> green 이미지로 변경
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-bluegreen
namespace: bluegreen-test
spec:
replicas: 2
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollout-bluegreen
template:
metadata:
labels:
app: rollout-bluegreen
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:green
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
blueGreen:
activeService: rollout-bluegreen-active
previewService: rollout-bluegreen-preview
autoPromotionEnabled: false
---
kind: Service
apiVersion: v1
metadata:
name: rollout-bluegreen-active
namespace: bluegreen-test
spec:
type: NodePort
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30081
---
kind: Service
apiVersion: v1
metadata:
name: rollout-bluegreen-preview
namespace: bluegreen-test
spec:
type: NodePort
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30082
ptty@pttyui-MacBookPro ~ % k apply -f rollout.yaml
rollout.argoproj.io/rollout-bluegreen configured
service/rollout-bluegreen-active unchanged
service/rollout-bluegreen-preview unchanged
Rollout 상태 확인
Name: rollout-bluegreen
Namespace: bluegreen-test
Status: ॥ Paused
Message: BlueGreenPause
Strategy: BlueGreen
Images: argoproj/rollouts-demo:blue (stable, active)
argoproj/rollouts-demo:green (preview)
Replicas:
Desired: 2
Current: 4
Updated: 2
Ready: 2
Available: 2
NAME KIND STATUS AGE INFO
⟳ rollout-bluegreen Rollout ॥ Paused 26m
├──# revision:2
│ └──⧉ rollout-bluegreen-75695867f ReplicaSet ✔ Healthy 2m7s preview
│ ├──□ rollout-bluegreen-75695867f-6flk8 Pod ✔ Running 2m7s ready:1/1
│ └──□ rollout-bluegreen-75695867f-f85rx Pod ✔ Running 2m7s ready:1/1
└──# revision:1
└──⧉ rollout-bluegreen-5ffd47b8d4 ReplicaSet ✔ Healthy 26m stable,active
├──□ rollout-bluegreen-5ffd47b8d4-82qzc Pod ✔ Running 26m ready:1/1
└──□ rollout-bluegreen-5ffd47b8d4-dsvkk Pod ✔ Running 26m ready:1/1
Preview가 Green으로 변경된 것을 확인할 수 있습니다.
현재 Rollout이 Paused 상태로 멈춰 있고 Status 또한 Paused, Message로 BlueGreenPause로 표시되고 있습니다.
Argo Rollouts가 새로운 Green 버전이 Preview 상태로 배포되었으나, 트래픽을 Green으로 자동으로 전환하지 않도록 설정되어 있기 때문입니다.
문제의 원인: AutoPromotionEnabled: false
rollout.yaml 파일에서 autoPromotionEnabled: false로 설정되어 있어, 새로운 Green 버전이 Preview 상태에서 자동으로 활성화(승격)되지 않고, 수동 승격을 기다리고 있는 상태입니다.
해결방안: 자동 승격 설정
만약 Green 버전이 테스트를 마친 후 자동으로 승격되기를 원한다면, autoPromotionEnabled: true로 설정할 수 있습니다. 또한, autoPromotionSeconds 옵션을 사용하여 일정 시간 후에 자동 승격되도록 설정할 수 있습니다. rollout.yaml 파일을 수정하여 20초 후 자동승격되도록 설정하였습니다.
# vi rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-bluegreen
namespace: bluegreen-test
spec:
replicas: 2
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollout-bluegreen
template:
metadata:
labels:
app: rollout-bluegreen
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:green
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
blueGreen:
activeService: rollout-bluegreen-active
previewService: rollout-bluegreen-preview
autoPromotionEnabled: true
autoPromotionSeconds: 20
상태확인
kubectl argo rollouts get rollout rollout-bluegreen -n bluegreen-test --watch
Revision:3 가 완전히 종료된 것을 볼 수 있습니다.
Active와 Preview 모두 Green 버전으로 배포된 것을 확인했습니다.
Rollback 롤백
배포 후 Green 버전에서 문제가 발견되는 경우, 안정성을 위해 Blue버전으로 롤백해야 합니다. 롤백은 배포 중 문제가 발생하거나, 배포 후 일정 시간이 지난 후에 버그가 발견될 때 사용됩니다.
Argo Rollouts는 이전 배포 기록을 관리하므로, 간단한 명령어로 이전 버전으로 쉽게 롤백할 수 있습니다.
# 롤백 명령어 실행
kubectl argo rollouts undo rollout rollout-bluegreen -n bluegreen-test
ptty@pttyui-MacBookPro ~ % kubectl argo rollouts undo rollout rollout-bluegreen -n bluegreen-test
Usage:
kubectl-argo-rollouts undo ROLLOUT_NAME [flags]
Examples:
# Undo a rollout
kubectl argo rollouts undo guestbook
# Undo a rollout revision 3
kubectl argo rollouts undo guestbook --to-revision=3
Flags:
-h, --help help for undo
--to-revision int The revision to rollback to. Default to 0 (last revision).
Global Flags:
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "/Users/ptty/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
-v, --kloglevel int Log level for kubernetes client library
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
--loglevel string Log level for kubectl argo rollouts (default "info")
-n, --namespace string If present, the namespace scope for this CLI request
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
롤백 정상적으로 완료
- Active 이미지: argoproj/rollouts-demo:blue
- 현재 활성 리비전: revision: 5 (Blue 버전)
- 이전 리비전: revision: 4 (Green 버전, ScaledDown 상태)
Green 버전은 더 이상 실행되지 않고, Blue 버전으로 트래픽이 다시 돌아갔습니다. 이전에 Green으로 배포된 파드는 Terminating 상태에 있거나 이미 종료되었습니다.
Green 버전에서 문제가 발생하면 kubectl argo rollouts undo 명령어를 통해 간단하게 Blue 버전으로 롤백할 수 있습니다.
References
https://argo-cd.readthedocs.io/en/stable/
https://argo-rollouts.readthedocs.io/en/stable/
https://codefresh.io/docs/docs/ci-cd-guides/progressive-delivery/
https://devocean.sk.com/blog/techBoardDetail.do?ID=165522&boardType=techBlog
'Kubernetes' 카테고리의 다른 글
Helm 기반 Jenkins 설치 시 InitContainer 실패 원인 분석 및 해결 (0) | 2025.04.01 |
---|---|
k6 + Grafana + Prometheus로 성능 테스트 환경 구축 및 시각화 (0) | 2025.01.17 |
CNCF란? Cloud Native란? (0) | 2024.09.25 |
[Docker] Docker 이미지 빌드, 배포, 백업 (0) | 2024.07.25 |
[Docker] Docker 소개 (1) | 2024.07.24 |