이 포스팅에서는 GitOps 환경에서 Blue-Green 방식의 무중단 배포를 구성하는 과정을 다룹니다.
이전 포스팅들을 참고하시면 GitOps 환경에서 GitHub Actions + ArgoCD를 이용한 CI/CD 파이프라인을 구축하실 수 있습니다.
2025.01.04 - [DevOps] - GitOps와 ArgoCD
2025.01.05 - [DevOps] - GitHub Actions + ArgoCD로 k8s 클러스터 환경에서 CI/CD 구축하기
서론
쿠버네티스는 배포를 쉽게 해 줍니다. 하지만 GitOps 방식의 CI/CD 파이프라인을 구축한 후 무중단 배포를 위해 설정해야 하는 부분은 꽤나 까다로웠습니다. GitHub Actions 워크플로우 스크립트를 수정할 때 configMap 등을 이용해 현재 배포된 버전이 `Blue` 버전인지 `Green` 버전인지 체크를 해야 하고, Deployment 리소스를 2개 관리하는 부분에서 Helm 차트 도입을 고려했습니다.
하지만 Helm 차트를 작성하지 않더라도 쉽게 Blue-Green 배포를 가능하게 해주는 Argo Rollouts를 알게 되었고, 이를 이용해 손쉽게 Blue-Green 무중단 배포를 구축하는 방법에 대해 소개합니다.
Argo Rollouts?
쿠버네티스의 컨트롤러로서 canary, blue-green 배포를 쉽게 해줄뿐만 아니라 배포된 파드에 문제가 있을 때 손쉽게 롤백할 수 있는 CRD(Custom Resource Definition)입니다.
컨트롤러는 `Rollout` 리소스의 변경 사항을 감지해 클러스터와 Sync를 수행합니다. `Rollout` 리소스가 아닌 일반 리소스의 변경은 컨트롤러의 관심 대상이 아닙니다.
공식 문서(https://argo-rollouts.readthedocs.io/en/stable/)에서 더 많은 정보를 제공하며, 설치부터 적용까지 공식 문서를 참고해 작성했습니다.
쿠버네티스 클러스터 환경
적용할 쿠버네티스 클러스터 환경은 `Ingress - Service - Pod`로 구성되어 있습니다.
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /api/.*
pathType: ImplementationSpecific
backend:
service:
name: api-svc
port:
number: 8080
Service
apiVersion: v1
kind: Service
metadata:
name: api-svc
spec:
selector:
app: api
ports:
- protocol: TCP
port: 8080
targetPort: 8080
name: server
type: ClusterIP
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: backend
image: myRegistry/server
ports:
- containerPort: 8080
설치
쿠버네티스 클러스터에 설치
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
기본적으로 `argo-rollouts` 네임스페이스에 설치됩니다.
argo rollouts 플러그인 설치
추가로 argo rollouts 플러그인을 설치하면 배포 과정을 시각화해주는 대시보드를 이용할 수 있으니 설치합니다.
저는 mac os를 사용 중이므로 아래 명령어로 설치했습니다. 다른 OS를 사용 중이시라면 공식 문서 링크를 참고하시면 됩니다.
brew install argoproj/tap/kubectl-argo-rollouts
설치 후 아래 명령어로 플러그인 버전을 확인합니다.
kubectl argo rollouts version
# 실행 결과
kubectl-argo-rollouts: v1.7.2+59e5bd3
BuildDate: 2024-08-13T18:29:47Z
GitCommit: 59e5bd385c031600f86075beb9d77620f8d7915e
GitTreeState: clean
GoVersion: go1.21.13
Compiler: gc
Platform: darwin/amd64
롤아웃(Rollout) 리소스 작성
무중단 배포할 Deployment 매니페스트를 argo rollouts에서 제공하는 `Rollout` 리소스로 재작성합니다. 작성 형식은 Deployment와 거의 유사합니다.
기존 Deployment 리소스
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: backend
image: myRegistry/backend
imagePullPolicy: Always
ports:
- containerPort: 8080
재작성된 Rollout 리소스
apiVersion: argoproj.io/v1alpha1 # api 변경
kind: Rollout # Rollout 리소스
metadata:
name: api-deployment
spec:
replicas: 1
revisionHistoryLimit: 2 # 기록할 과거 버전의 개수
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: backend
image: myRegistry/backend
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
blueGreen:
activeService: api-svc # 새 파드가 트래픽을 받을 파드로 승격됐을 때 연결할 서비스의 이름
autoPromotionEnabled: true # 파드의 프로브 상태가 모두 `Success`일 때 자동 승격 허용
- `strategy.blueGreen.activeService`: (필수) 새 버전으로 배포된 파드가 트래픽을 받을 파드로 승격(promotion)됐을 때 연결할 서비스 리소스의 이름을 지정합니다.
- `strategy.blueGreen.previewService` 필드는 선택적으로 적용할 수 있습니다. 새 버전의 파드가 프로덕션의 트래픽을 받지 않고 테스트를 할 때 외부에서 접속할 수 있도록 연결하는 서비스를 연결할 때 사용합니다. (이름 그대로 미리보기 서비스)
저는 필요하지 않아 설정하지 않았습니다.
- `strategy.blueGreen.previewService` 필드는 선택적으로 적용할 수 있습니다. 새 버전의 파드가 프로덕션의 트래픽을 받지 않고 테스트를 할 때 외부에서 접속할 수 있도록 연결하는 서비스를 연결할 때 사용합니다. (이름 그대로 미리보기 서비스)
- `strategy.blueGreen.autoPromotionEnabled`: (선택) 파드의 프로브 상태가 모두 `Success`일 때 트래픽을 받을 파드로 자등 승격을 설정할지에 대한 설정입니다. 기본값은 `true`이며, 안정성을 위해 `false`로 설정할 시 수동으로 승격을 해야 합니다.
저는 파드의 프로브 상태를 체크하는 `readinessProbe`를 설정했기 때문에 `true`로 설정했습니다.- 파드의 프로브 상태는 kubernetes 공식 문서를 참고해 주세요.
- 파드의 프로브 상태를 체크하는 설정에 따라 트래픽이 유실될 수 있습니다.
트래픽이 유실되지 않는 무중단 배포 방법은 쿠버네티스에서 트래픽 유실 없는 무중단 배포 적용하기 에서 확인할 수 있습니다.
- 그 외에 선택적으로 적용할 수 있는 필드 옵션은 공식 문서를 참고해 주세요.
롤아웃(Rollout) 배포 및 Blue-Green 과정 확인하기
롤아웃(Rollout) 배포
아래 `kubectl` 명령어로 배포하겠습니다.
kubectl apply -f api-bluegreen-rollout.yaml
# 실행 결과
rollout.argoproj.io/api-deployment created
대시보드 확인
설치 단계에서 `argo rollouts` 플러그인을 설치했다면 Blue-Green 배포 과정을 시각화해 주는 대시보드로 배포 과정을 확인할 수 있습니다.
kubectl argo rollouts dashboard
# 실행 결과
INFO[0000] Argo Rollouts Dashboard is now available at http://localhost:3100/rollouts
`localhost:3100`으로 접속하면 대시보드로 배포 과정을 확인할 수 있습니다.
`Blue` 버전이라고 할 수 있는 롤아웃 리소스가 보입니다.
새 버전 배포 시 Blue-Green 배포 과정 확인
1. Green 버전 배포 시작
새 버전으로 배포 중인 `Green`에 해당하는 파드(Revision 2)가 보입니다.
아직 `Green` 파드가 준비되지 않아 `Blue` 파드에 트래픽이 인입됩니다.
2. Green 버전 배포 완료
`Green`에 해당하는 파드(Revision 2)가 완전히 준비 됐습니다.
이제 트래픽은 `Green` 파드에 인입되며 현재 활성화된 롤아웃이므로 `active` 표시가 생겼습니다.
이 순간에는 `Blue` 파드와 `Green` 파드가 동시에 존재하지만 `Blue` 파드에는 트래픽이 인입되지 않습니다.
3. Blue 버전 제거 시작
이제 `Blue` 파드(Revision 1)가 제거됩니다. 제거되는 동안 graceful shutdown이 구현되어 있다면 마지막 요청을 처리하고 파드가 죽습니다. graceful shutdown과 관련한 무중단 배포는 쿠버네티스에서 트래픽 유실 없는 무중단 배포 적용하기 포스팅을 참조해 주시길 바랍니다.
3. Blue 버전 제거 완료
`Blue` 파드가 완전히 제거됐습니다. 만약 `Green` 버전에 문제가 생겨 다른 버전으로 롤백이 필요하다면 원하는 Revision에서 `Rollback` 버튼을 통해 해당 롤아웃 버전으로 롤백을 손쉽게 할 수 있습니다.
도움이 되셨길 바라며 긴 글 읽어주셔서 감사합니다.
참고
'DevOps' 카테고리의 다른 글
GitHub Actions + ArgoCD로 k8s 클러스터 환경에서 CI/CD 구축하기 (0) | 2025.01.05 |
---|---|
GitOps에서 SealedSecret으로 안전하게 Secret 관리하기 (0) | 2025.01.04 |
GitOps와 ArgoCD (1) | 2025.01.04 |