Kubernetes Cluster 에서 Blue/Green 배포하기 (Argo Rollout 버전)
이전 글에서는 Kubernetes Cluster 상에서 App 을 Scratch 방식으로 Blue/Green 배포를 하였다. 이번에는 Argo Rollout 을 사용한 Blue/Green 배포하는 방식을 살표보자.
Nginx 혹은 AWS ALB 를 직접 연결하여 사용할 수 있지만, Blue/Green 배포는 Traffic Shifting 이 필요하지 않으므로 AWS LB → Ingress Controller 를 연결한 상태를 만들어 놓고 배포하는 방식을 설명한다.
1. Argo Rollout 설치
helm chart 를 이용하여 argo rollout 을 설치한다.
argo rollout dashboard 를 포햄하여 설치하고 싶으면 dashboard.enabled=true
를 추가하면 된다.
$ helm repo add argo https://argoproj.github.io/argo-helm
$ helm repo update
$ helm search repo argo/argo-rollouts -l
NAME CHART VERSION APP VERSION DESCRIPTION
argo/argo-rollouts 2.22.2 v1.4.0 A Helm chart for Argo Rollouts
argo/argo-rollouts 2.22.1 v1.4.0 A Helm chart for Argo Rollouts
$ helm upgrade -i argo-rollout argo/argo-rollouts --version 2.22.2 -n argo --set dashboard.enabled=true --create-namespace
argo rollout dashboard 는 인증 체계가 없다. 그러므로 포트 포워딩으로 dashboard 에 접속 하는 것을 추천한다.
$ kubectl port-forward service/argo-rollouts-dashboard 31000:3100
2. Argo Rollout kubectl plugin 설치
kubectl 로 cli 호출이 가능하도록 plugin 을 설치한다.
$ curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.4.0/kubectl-argo-rollouts-linux-amd64
$ chmod +x kubectl-argo-rollouts-linux-amd64
$ sudo mv kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts
$ kubectl argo rollouts version
--- output ---
kubectl-argo-rollouts: v1.4.0+e40c9fe
BuildDate: 2023-01-09T20:20:38Z
GitCommit: e40c9fe8a2f7fee9d8ee1c56b4c6c7b983fce135
GitTreeState: clean
GoVersion: go1.19.4
Compiler: gc
Platform: linux/amd64
argo rollout bash complete 도 설치한다.
$ kubectl argo rollouts completion bash | tee /home/ubuntu/.kube/kubectl-argo-rollouts > /dev/null
$ vi ~/.bash_profile
source '/home/ubuntu/.kube/completion.bash.inc'
source '/home/ubuntu/.kube/kubectl-argo-rollouts'
PATH=/home/ubuntu/bin:$PATH
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
3. 최초 App 배포 (Blue Deployment)
초기 app (blue)을 배포한다. 이전 글에서 사용된 seungkyua/nginx:blue
이미지를 배포한다. 단 replicas 를 0
으로 배포한다. 이렇게 배포하면 실제 pod 는 실행되지 않지만 pod template 은 배포된 상태가 된다. pod template 은 나중에 rollout 에서 참조하여 사용한다.
$ cat nginx-blue-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-blue-green
name: nginx-blue-green
spec:
replicas: 0
selector:
matchLabels:
app: nginx-blue-green
version: blue-green
template:
metadata:
labels:
app: nginx-blue-green
version: blue-green
spec:
containers:
- image: seungkyua/nginx:blue
name: nginx
$ kubectl apply -f nginx-blue-deploy.yaml
$ kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-blue-green 0/0 0 0 11s
Service 를 배포한다.
$ cat nginx-blue-green-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-blue-green
name: nginx-blue-green-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-blue-green
version: blue-green
type: ClusterIP
$ kubectl apply -f nginx-blue-green-svc.yaml
그리고 blue deployment app 에 웹접속이 가능하게 ingress 를 배포한다. ingress 를 배포하더라도 아직 웹 접속은 불가능하다. 앞에서 deployment 의 replicas 를 0 으로 생성했기 때문에 실행되고 있는 pod 가 없기 때문이다. (나중에 접속을 위해서 /etc/hosts
에 nginx-blue-green.taco-cat.xyz
를 등록해 놓자)
$ cat nginx-blue-green-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-blue-green-ingress
spec:
ingressClassName: nginx
rules:
- host: nginx-blue-green.taco-cat.xyz
http:
paths:
- pathType: ImplementationSpecific
backend:
service:
name: nginx-blue-green-svc
port:
number: 80
$ kubectl apply -f nginx-blue-green-ingress.yaml
Rollout 커스텀 리소스 배포
이제 초기 환경으로 Rollout 을 배포한다. Rollout 을 배포하면 pod 가 생성된다. workloadRef
영역은 Deployment 에서 Pod Template
영역과 일치한다. 그래서 이미 배포된 Deployment 를 참조하게 정의했다.
마지막 라인의 autoPromotionEnabled
는 false
로 하여 수동으로 Blue/Green 을 확인하면서 배포를 할 수 있게 한다.
$ cat nginx-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: nginx-rollout
spec:
replicas: 2
revisionHistoryLimit: 5
selector:
matchLabels:
app: nginx-blue-green
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: nginx-blue-green
strategy:
blueGreen:
activeService: nginx-blue-green-svc
autoPromotionEnabled: false
$ kubectl apply -f nginx-rollout.yaml
이제 배포가 완료되면 아래와 같이 리소스가 생성되었음을 확인할 수 있다. rollout pod 와 rollout 에서 사용하는 ReplicaSet 이 생성되어 있음을 알 수 있다.
$ kubectl argo rollouts list rollout
NAME STRATEGY STATUS STEP SET-WEIGHT READY DESIRED UP-TO-DATE AVAILABLE
nginx-rollout BlueGreen Healthy - - 2/2 2 2 2
$ kubectl get pods,deploy,rs
NAME READY STATUS RESTARTS AGE
pod/nginx-rollout-85c4bfb654-jmts7 1/1 Running 0 2m29s
pod/nginx-rollout-85c4bfb654-s46sm 1/1 Running 0 2m29s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-blue-green 0/0 0 0 4m50s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-blue-green-8b4f9cddb 0 0 0 4m50s
replicaset.apps/nginx-rollout-85c4bfb654 2 2 2 2m29s
웹으로 접속하면 아래와 같은 화면을 볼 수 있다.
혹은 curl 로도 확인할 수 있다.
$ curl nginx-blue-green.taco-cat.xyz
--- output ---
<!DOCTYPE html>
<html>
<body style="background-color:blue;">
<h1>This is a blue webserver</h1>
</body>
</html>
Rollout dashboard 에는 아래와 같이 나온다.
4. App 업그레이드 배포 (Green Deployment)
app 을 수정하여 배포해 보자. app 은 Deployment 를 수정해서 배포하면 된다.
$ cat nginx-green-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-blue-green
name: nginx-blue-green
spec:
replicas: 0
selector:
matchLabels:
app: nginx-blue-green
version: blue-green
template:
metadata:
labels:
app: nginx-blue-green
version: blue-green
spec:
containers:
- image: seungkyua/nginx:green
name: nginx
$ kubectl apply -f nginx-green-deploy.yaml
Deployment 가 업그레이드 되어 배포했기 때문에 Rollout 이 이를 인식하고 Green 에 해당하는 추가 Pod 와 ReplicaSet 을 생성한다. 그리고 Rollout 리소스의 상태는 Paused
가 된. (앞에서 Rollout 리소스 배포 시에 autoPromotionEnabled
는 false
로 하였기 때문이다)
$ kubectl argo rollouts list rollout
NAME STRATEGY STATUS STEP SET-WEIGHT READY DESIRED UP-TO-DATE AVAILABLE
nginx-rollout BlueGreen Paused - - 2/4 2 2 2
Pod 와 ReplicaSet 을 조회해 보면 아래와 같다. Blue 해당하는 ReplicaSet 1 개, Pod 2개, Green 에 해당하는 ReplicaSet 1개 Pod 2 개가 떠 있는 것을 알 수 있다.
Rollout Dashboar 는 아래와 같은 Pause 상태이다.
5. Rollout 진행 완료 (promote)
완전히 Green 으로 변경하려면 Rollout 을 promote
하여 최종 적용을 하던지 abort
하여 중단, 혹은 undo
하여 Pause 보다 이전 단계이 최초 Blue app 배포 단계로 돌아가는 방법이 있다.
Green 으로 진행하는 promote 를 해보자.
$ kubectl argo rollouts promote nginx-rollout
--- output ---
rollout 'nginx-rollout' promoted
ReplicaSet 은 남아 있지만 Pod 는 Green 으로 배포된 것만 남아있는 것을 확인할 수 있다.
$ kubectl get pods,rs -l rollouts-pod-template-hash --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod/nginx-rollout-569b8595bf-8s94v 1/1 Running 0 10m app=nginx-blue-green,rollouts-pod-template-hash=569b8595bf,version=blue-green
pod/nginx-rollout-569b8595bf-c7fgg 1/1 Running 0 10m app=nginx-blue-green,rollouts-pod-template-hash=569b8595bf,version=blue-green
NAME DESIRED CURRENT READY AGE LABELS
replicaset.apps/nginx-rollout-569b8595bf 2 2 2 10m app=nginx-blue-green,rollouts-pod-template-hash=569b8595bf,version=blue-green
replicaset.apps/nginx-rollout-85c4bfb654 0 0 0 19m app=nginx-blue-green,rollouts-pod-template-hash=85c4bfb654,version=blue-green
Rollout Dashboard 에서도 완료된 것을 알 수 있다.
마지막으로 웹 화면으로 확인한다.
마치며…
Argo Rollout 은 Deployment 변경에서만 인식을 한다. ConfigMap 이나 Secret 과 같은 다른 리소스는 지원하지 않으니 Rollout 에서 이를 지원하는 방법은 추가로 고민해야 한다.