Kubernetes

Kubernetes Cluster 에서 Blue/Green 배포하기 (Argo Rollout 버전)

seungkyua@gmail.com 2023. 2. 10. 09:04
반응형

이전 글에서는 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/hostsnginx-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 를 참조하게 정의했다.

마지막 라인의 autoPromotionEnabledfalse 로 하여 수동으로 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 리소스 배포 시에 autoPromotionEnabledfalse 로 하였기 때문이다)

$ 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 에서 이를 지원하는 방법은 추가로 고민해야 한다.

반응형