Study_note
[CICD] ArgoCD rollout사용한 Bule/Green, Canry 배포 본문
Blue / Green란?
이전 버전에서 새로운 버전으로 한번에 배포하는 방식이며, 이전버전을 Blue, 새로운 버전을 Green 이라고 칭한다.
Blue / Green 배포방식은 이전 버전과 새로운 버전을 모두 존재하기에 롤백이 쉬우며 Downtime을 없앨 수 있다.
또한, Rolling Update 방식에서 이전버전과 새로운 버전의 공존하는 시간이 존재한다는 단점을 커버할 수 있다.
하지만 Rolling Update 방식보다 2배의 자원을 사용해야 하므로 더 많은 비용이 발생하게 된다.
쿠버네티스에서는 ArgoCD를 사용하지 않고 Blue / Green 배포를 할 수 있다.
Deployment를 2개 운영하고, Service에서 Selector를 변경하는 방법으로 간단하게 Blue / Green 배포를할 수 있는데
ArgoCD를 사용하면 더 편리하게 Blue/Green 방식으로 배포할 수 있다.
우선 Blue/Green 방식으로 배포를 할려면 argo-rollout가 필요하다
argo-rollout란
blue-green, canary등과 같은 고급 배포를 지원하는 쿠버네티스 컨트롤러로 CRD형태로 생성되어지낟.
argo-rollout 공식문서 https://argoproj.github.io/argo-rollouts
우선 위에 문서를 참조하고 argo-rollout의 namespace 및 설치
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
위에서 argo-rollouts을 설치하였으면 kubectl용 plugin 설치
# curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
# chmod +x ./kubectl-argo-rollouts-linux-amd64
# mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
# kubectl argo rollouts version
Bule/Green yaml 파일 배포
아래 예제를 사용하여 Blue/Green 배포할 Rollout과 Service를 생성
apiVersion: argoproj.io/v1alpha1
kind: Rollout # Deplyment 대신 Rollout을 사용한다
metadata:
name: rollout-bluegreen
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
# image: argoproj/rollouts-demo:green
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
blueGreen:
activeService: rollout-bluegreen-active
previewService: rollout-bluegreen-preview
#autoPromotioEnabled 옵션은 Blue/Green 배포를 자동으로 진행할 것인지 여부. false 옵션을 사용해 수동으로 지정
autoPromotionEnabled: false
---
kind: Service
apiVersion: v1
metadata:
name: rollout-bluegreen-active
spec:
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30081
type: NodePort
---
kind: Service
apiVersion: v1
metadata:
name: rollout-bluegreen-preview
spec:
selector:
app: rollout-bluegreen
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30082
type: NodePort
여기서 주의 해야할 부분은 strategy 옵션으로
Rollout은 2개의 서비스를 이용해 preview와 active로 나누어서 Blue와 Green을 구분하며,
active 에서는 blue가 보이고, preview에서는 green이 보이게 지정한다.
autoPromotionEnabled 옵션은 자동으로 배포할 것인지, 관리자가 수동으로 승인할 것인지에 대한 여부를 묻는 옵션이다. 필자는 false를 주어 수동으로 만들고 변하는 과정을 보려한다.
repository에 push 후 해당 레포지토리를 argoCD에 배포 필자는 blue-green 디렉토리 만들어 롤아웃 파일을 내부에 생성하고 네임스페이스 없이 rollout-bluegreen yaml 파일을 배포했다 (ArgoCD 기본배포 참고)
아래처럼 제대로 배포된것을 확인 가능 하며 각 service 타입을 nodeport로 주었기 때문에 nodeport를 통해서 접속 가능하며 처음에는 active (blue)만 배포했기 때문에 양쪽 포트로 들어가도 파란색 화면 밖에 안보인다.
active (blue) 접속 : 워커노드 ip:30081
preview (green) 접속 : 워커노드 ip:30082
green 워커노드 ip:30082로 들어가도 파란색
배포과정을 모니터링 하면 다음과 같이 지금은 블루 파드 2개만 배포된것을 확인 가능하며 리스트 또한 2/2개로 블루 파드 2개만 생성된것을 확인 가능
# rollouts list 확인
kubectl argo rollouts list rollout
# rollout-bluegreen rollouts을 모니터링
kubectl argo rollouts get rollout rollout-bluegreen -w
# rollout-bluegreen에서 수동으로 green으로 배포
kubectl argo rollouts promote rollout-bluegreen
다음으로 이전에 배포했던 yaml파일에서 주석처리 되어있던 Green 이미지의 주석을 지워주고 Blue의 주석을 달아준 후 다시 재배포하면 아래와 같다.
위에 그림 처럼 2개의 블루 파드와 2개의 그린 파드가 생성된것을 확인 가능하며 2/4로 총 4개의 파드가 생성되고 2개가 블루로 제공되는것을 확인할 수 있다.
green 워커노드 ip:30082 접속 시 그린 화면 확인 가능
promte 명령어를 통해 수동 배포하면 아래처럼 블루 파드는 제거되고 그린 파드만 남는것을 확인 가능
blue 워커노드 ip:30081 접속 시 그린 화면 확인 가능
Canary 란
'카나리아'라는 새를 모티브로 만들어졌는데 어원은 아래와 같다.
"카나리아는 메탄, 일산화탄소에 매우 민감한 새라 가스에 노출되면 죽어버리게 된다. 그래서 옛날에 광부들이 안전하게 일 할 수 있도록 카나리아를 이용하였다. 카나리아가 노래를 계속하고 있는 동안 광부들은 안전함을 느낀 채 일 할 수 있었으며, 만약 카나리아가 죽게 되면 곧바로 탄광을 탈출함으로써 광부들의 생명을 보존할 수 있었다."
즉 특정 서버나 소수의 유저들만 먼저 새로운 버전을 배포하고 사용하고 나서 안전하다고 판단이 되면 그 후에 모든 서버들에 새로운 버전을 배포하는 방식이다.
우선 아래 공식 문서에서 카나리에 대해 자세하기 설명되어있다 한번 읽어보면 좋다
ArgoCD rollout Canary 공식 문서 : https://argoproj.github.io/argo-rollouts/features/canary/
우선 아래 yaml 파일을 특정 git repo에 push 후 ArgoCD에 배포 (ArgoCD 배포 방법)
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 20
- pause: {}
- setWeight: 40
- pause: {duration: 10}
- setWeight: 60
- pause: {duration: 10}
- setWeight: 80
- pause: {duration: 10}
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
# image: argoproj/rollouts-demo:yellow
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
---
apiVersion: v1
kind: Service
metadata:
name: rollouts-demo
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
nodePort: 30083
type: NodePort
selector:
app: rollouts-demo
여기서 주의해야하는 부분은 setWeight와 pause다.
setWeight필드는 카나리아로 보내야 하는 트래픽의 비율을 나타내고 pause는 롤아웃을 일시 중지하도록 지시한다.
pause에 정의된 시간에 도달하면 설정부분 만큼 추가한다.
pause가 설정되면 카나리는 duration을 기다릴 때까지 다음 단계로 진행되지 않는다
duration을 사용하지않으면 카나리는 해당 일시 중지 조건이 제거될 때까지 무기한 대기한다.
setWeight및 필드 를 사용하여 pause사용자는 새 버전으로 진행하려는 방법을 선언적으로 설명할 수 있다.
유효한 시간 단위는 "s", "m", "h"이며 지정하지 않으면 기본값은 "s"이다.
spec:
strategy:
canary:
steps:
- pause: { duration: 10 } # 10 seconds
- pause: { duration: 10s } # 10 seconds
- pause: { duration: 10m } # 10 minutes
- pause: { duration: 10h } # 10 hours
- pause: {} # pause indefinitely
일시중지 단계인 no duration를 지정하면 무기한 일시중지되는데 일시 중지를 해제하려면 promote 명령을 사용하면 된다.
promote to the next step
kubectl argo rollouts promote <rollout>
우선 위에 파일을 ArgoCD에 배포하면 아래와 같이 제대로 배포된것을 확인할 수 있다.
이제 주석처리됐던 yellow 이미지를 해체하고 블루를 주석 처리하고 다시 배포해보면 아래와 같다.
여기서 rollout은 argocd, 모니터링, list를 보면 처음 설정한 setWeight 20으로 설정했기 때문에 5개의 파드중 20프로 즉 1개이기 때문에 1개의 yellow 파드가 배포된것을 확인할 수 있고 현재 duration을 지정하지 않았기 때문에 paused 상태로 멈춰있는것을 확인할 수 있다.
pause 상태를 해제하고 다시 배포를 하기 위해 promote 명령을 사용하면 아래 처럼 setweight가 지정한 만큼 증가하는것을 확인 가능하면 모니터링에서도 기존파드가 삭제되고 yellow 파드가 생성되고 마침내 모든 파드가 yellow로 생성되는것을 확인가능하다.