Skip to content

4) Canary Deployment using Argo Rollouts

Alex, Lee edited this page Jun 23, 2022 · 9 revisions

2022.04. 이장재 📧 cine0831@gmail.com 📂 https://github.com/jangjaelee 📒 http://www.awx.kr


 

Overview

Argo Rollouts를 사용하여 Canary 배포 설정과 내장된 Traffic Management 기능에서 지원하는 Ingress Controller 및 Service Mesh 중 하나인 Nginx Ingress를 통해 새 버전과 이전 버전사이에 트래픽 비율 조정을 통해 트래픽을 점진적으로 새 애플리케이션으로 이동하는 방법을 알아봅니다.

canary.png

 

Prerequisites

 

Step 1. Deploy a Demo Application

Argo CD Application resource를 사용하여 Rollout resouce 배포하며, 이번 예제를 위해 *Argo Rollouts Demo Application*을 사용하겠습니다.

Demo Application에서는 Ingress의 API를 networking.k8s.io/v1beta1을 사용있으며, Kubernetes v1.22 이후로 extensions/v1beta1networking.k8s.io/v1beta1 은 더 이상 사용되지 않아 networking.k8s.io/v1 으로 마이그레이션 하여 사용했습니다.

🔗 https://github.com/jangjaelee/tutorials-argo-rollouts/tree/main/demo/canary

Step 1.1. using Argo CD Application resource

진행하기에 앞서 Argo CD에 로그인 합니다.

$ argo login argocd.awx.kr --grpc-web
Username: admin
Password:
'admin:login' logged in successfully
Context 'argocd.awx.kr' updated

Argo CD Application resource를 사용하여 Rollout resource를 배포 합니다.

$ cat <<EOF | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argo-rollouts-demo-canary
  namespace: argocd
spec:
  destination:
    name: in-cluster
    namespace: default
  project: default
  source:
    path: demo/canary
    repoURL: https://github.com/jangjaelee/tutorials-argo-rollouts.git
    targetRevision: HEAD
  syncPolicy: {}
EOF
application.argoproj.io/argo-rollouts-demo-canary created

$ argocd app list | egrep 'NAME|rollouts-demo-canary'
NAME                       CLUSTER                         NAMESPACE       PROJECT  STATUS     HEALTH   SYNCPOLICY  CONDITIONS          REPO                                                       PATH         TARGET
argo-rollouts-demo-canary                                  default         default  OutOfSync  Missing  <none>      <none>              https://github.com/jangjaelee/tutorials-argo-rollouts.git  demo/canary  HEAD

Demo Application을 배포하고 Application의 상태를 확인하면 OutOfSync 상태로 아직 배포가 진행되지 않고 있습니다.

Sync를 진행하여 리소스들이 배포될 수 있게 합니다.

$ argocd app sync argo-rollouts-demo-canary

만약, Argo CD를 설치하지 않았거나 또는 사용하지 않는 다면 이 단계는 건너띄고 Step 1.2. using Kustomize를 진행하시기 바랍니다.

Step 1.2. using Kustomize

Demo Application 저장소에서 파일들을 clone 합니다.

$ git clone https://github.com/jangjaelee/tutorials-argo-rollouts.git
$ cd tutorials-argo-rollouts/demo/canary

kustomize를 사용하여 Rollout resource를 배포 합니다.

$ kustomize build . | kubectl apply -f -
service/canary-demo created
service/canary-demo-preview created
rollout.argoproj.io/canary-demo created
ingress.networking.k8s.io/canary-demo created
ingress.networking.k8s.io/canary-demo-preview created

만약, kustomize를 사용하지 않는다면 Manifest를 사용하면 됩니다.

$ kubectl apply -f canary-ingress.yaml -f canary-preview-ingress.yaml -f canary-preview-service.yaml -f canary-rollout.yaml -f canary-service.yaml

또는

$ for i in $(ls); do if [ "${i}" != "kustomization.yaml" ]; then kubectl apply -f ${i}; fi; done

kustomization.yaml 파일은 kustomize를 사용할 때 필요하므로 사용하지 않습니다.

Step 1.3. see Resources

필자는 애플리케이션 접속을 위한 canary-demo와 canary-demo-review Ingress resource에서 canary-demo.awx.kr, canary-preview.awx.kr 호스트를 지정하여 사용하였습니다. 본인의 환경에 맞게 호스트를 변경하여 사용하시기 바랍니다.

  • canary-ingress.yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: canary-demo
      annotations:
        ingress.kubernetes.io/proxy-body-size: 100M
        ingress.kubernetes.io/app-root: /
        nginx.ingress.kubernetes.io/backend-protocol: HTTP
    spec:
      ingressClassName: nginx
      rules:
      - host: canary-demo.awx.kr
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-demo
                port:
                  number: 80
  • canary-preview-ingress.yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: canary-demo-preview
      annotations:
        ingress.kubernetes.io/proxy-body-size: 100M
        ingress.kubernetes.io/app-root: /
        nginx.ingress.kubernetes.io/backend-protocol: HTTP
    spec:
      ingressClassName: nginx
      rules:
      - host: canary-preview.awx.kr
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: canary-demo-preview
                port:
                  number: 80

다음은 배포된 애플리케이션의 resources 입니다.

$ kubectl get all,ing,rollouts
NAME                              READY   STATUS    RESTARTS   AGE
pod/canary-demo-6f8b8d584-dpfp6   1/1     Running   0          34s
pod/canary-demo-6f8b8d584-hn6h7   1/1     Running   0          34s
pod/canary-demo-6f8b8d584-ltthv   1/1     Running   0          34s
pod/canary-demo-6f8b8d584-rzmz4   1/1     Running   0          34s
pod/canary-demo-6f8b8d584-xppkk   1/1     Running   0          34s

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/canary-demo           ClusterIP   10.101.254.186   <none>        80/TCP    34s
service/canary-demo-preview   ClusterIP   10.104.57.203    <none>        80/TCP    34s
service/kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP   34d

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/canary-demo-6f8b8d584   5         5         5       34s

NAME                                            CLASS   HOSTS                   ADDRESS         PORTS   AGE
ingress.networking.k8s.io/canary-demo           nginx   canary-demo.awx.kr      192.168.1.181   80      34s
ingress.networking.k8s.io/canary-demo-preview   nginx   canary-preview.awx.kr   192.168.1.181   80      34s

NAME                              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
rollout.argoproj.io/canary-demo   5         5         5            5           34s

Argo Rollouts Kubectl Plugin을 사용하면 release에 대한 세부정보와 시각적 표현을 트리 보기로 확인할 수 있습니다.

$ kubectl argo rollouts get rollout canary-demo -w
Name:            canary-demo
Namespace:       default
Status:          ✔ Healthy
Strategy:        Canary
  Step:          8/8
  SetWeight:     100
  ActualWeight:  100
Images:          argoproj/rollouts-demo:blue (stable)
Replicas:
  Desired:       5
  Current:       5
  Updated:       5
  Ready:         5
  Available:     5

NAME                                    KIND        STATUS     AGE    INFO
⟳ canary-demo                          Rollout     ✔ Healthy  6m14s
└──# revision:1
   └──⧉ canary-demo-6f8b8d584          ReplicaSet  ✔ Healthy  6m14s  stable
      ├──□ canary-demo-6f8b8d584-qbzv9  Pod         ✔ Running  6m14s  ready:1/1
      ├──□ canary-demo-6f8b8d584-rbt6b  Pod         ✔ Running  6m14s  ready:1/1
      ├──□ canary-demo-6f8b8d584-rtqtt  Pod         ✔ Running  6m14s  ready:1/1
      ├──□ canary-demo-6f8b8d584-tww9q  Pod         ✔ Running  6m14s  ready:1/1
      └──□ canary-demo-6f8b8d584-vdkjr  Pod         ✔ Running  6m14s  ready:1/1

Argo CD UI와 Argo Rollout UI에서도 배포된 resources와 Network Traffic이 Pod까지 어떻게 전달되는지 볼 수 있습니다.

  • Argo CD UI 접속 화면

argo-rollouts-demo-argocd-01.png

argo-rollouts-demo-argocd-animate-01.gif

  • Argo Rollouts UI 접속 화면

argo-rollouts-demo-canary-UI-01.png

  • Demo Application (Blue) 접속 화면

argo-rollouts-demo_canary-01.gif

Step 2. Update Application

Demo Application을 업데이트 하면 Rollout이 어떻게 Canary 배포를 진행하는지 알아보겠습니다.

다음은 Rollout resource에 명시한 canary strategy 이며, 4단계로 진행 됩니다.

strategy:
    canary:
      canaryService: canary-demo-preview
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 40
      - pause: {duration: 10}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}
  • strategy.canary.steps의 첫번째 setWeight: 20필드지시에 따라 트래픽의 20%는 새 버전으로 리다이렉션 합니다. setWeight 필드는 Canary로 보내야 하는 트래픽의 비율을 나타냅니다.
  • pause 구조체 지시에 따라 Rollout이 일시 중지되며, 관리자(또는 사용자)가 수동으로 해제를 하여야 다음 단계로 진행할 수 있습니다. 일시 중지 해제는 argo kubectl plugin의 promote 명령을 사용하게 됩니다.
  • 세번째 setWeight: 40 필드지시에 따라 트래픽의 40%를 새 버전으로 리다이렉션 합니다.
  • Pause Duration 필드지시에 따라 10초간 일시 중지후 다음 단계로 자동으로 진행하게 됩니다. 유효한 시간 단위는 “s”, “m”, “h” 이며, 지정하지 않으면 기본값은 “s” 입니다.
  • 다음으로 setWeight 필드 지시에 따라 60% 그리고 80%를 새 버전으로 리다이렉션 하게 됩니다.
  • 마지막으로 지정하지 되어 있지 않지만 암시적 단계로 트래픽의 100%를 새 버전으로 리다이렉션하여 Canary Update를 종료합니다.

다음과 같이 컨테이너 이미지를 새 이미지 태그(blue에서 yellow로 변경)로 업데이트 해보겠습니다.

$ kubectl argo rollouts set image canary-demo "*=argoproj/rollouts-demo:yellow"
rollout "canary-demo" image updated

argo kubectl plugin을 사용하여 업데이트 상황을 시각적으로 확인 할 수 있습니다.

$ kubectl argo rollouts get rollout canary-demo -w
Name:            canary-demo
Namespace:       default
Status:          ॥ Paused
Message:         CanaryPauseStep
Strategy:        Canary
  Step:          1/8
  SetWeight:     20
  ActualWeight:  20
Images:          argoproj/rollouts-demo:blue (stable)
                 argoproj/rollouts-demo:yellow (canary)
Replicas:
  Desired:       5
  Current:       5
  Updated:       1
  Ready:         5
  Available:     5

NAME                                     KIND        STATUS     AGE    INFO
⟳ canary-demo                           Rollout     ॥ Paused   8m51s
├──# revision:2
│  └──⧉ canary-demo-689684c976          ReplicaSet  ✔ Healthy  19s    canary
│     └──□ canary-demo-689684c976-c6947  Pod         ✔ Running  19s    ready:1/1
└──# revision:1
   └──⧉ canary-demo-6f8b8d584            ReplicaSet  ✔ Healthy  8m51s  stable
      ├──□ canary-demo-6f8b8d584-qbzv9   Pod         ✔ Running  8m51s  ready:1/1
      ├──□ canary-demo-6f8b8d584-rbt6b   Pod         ✔ Running  8m51s  ready:1/1
      ├──□ canary-demo-6f8b8d584-tww9q   Pod         ✔ Running  8m51s  ready:1/1
      └──□ canary-demo-6f8b8d584-vdkjr   Pod         ✔ Running  8m51s  ready:1/1

canary-demo의 rollout이 revision: 2가 새로 생긴 것이 보이시죠?

strategy.canary.steps.setWeight: 20 필드지시에 따라 새 애플리케이션이 생성되고 트래픽의 20%는 새 버전으로 유입되게 됩니다.

새 애플리케이셔 Pod는 새 replicaset resource에 생성이 되며, 트래픽의 분할은 metadata.labelspod-template-hash 필드 지시어를 사용하여 기존 애플리케이션과 새 애플리케이션에 전달하게 됩니다.

Pod Template Hash에 대해서는 다음에 자세하게 다루기로 하겠습니다.

$ kubectl get rollouts,replicaset
NAME                              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
rollout.argoproj.io/canary-demo   5         5         1            5           9m

NAME                                     DESIRED   CURRENT   READY   AGE    CONTAINERS    IMAGES                          SELECTOR
replicaset.apps/canary-demo-689684c976   1         1         1       3m     canary-demo   argoproj/rollouts-demo:yellow   app=canary-demo,rollouts-pod-template-hash=689684c976
replicaset.apps/canary-demo-6f8b8d584    4         4         4       9m     canary-demo   argoproj/rollouts-demo:blue     app=canary-demo,rollouts-pod-template-hash=6f8b8d584
  • Argo Rollouts UI 접속 화면

argo-rollouts-demo-canary-UI-02.png

  • Argo CD UI 접속 화면

argo-rollouts-demo-argocd-animate-02.gif

  • canary-preview-demo 접속 화면

argo-rollouts-demo_canary-03.gif

  • canary-demo trafficWeight 20% 적용후 접속 화면

argo-rollouts-demo_canary-02.gif

Weight 20% 적용후 일시 중단 되어 있는 현 상태를 Promote 명령어를 사용하여 new ReplicaSet을 stable 버전으로 승격 될수 있게 중단된 업데이트를 계속 진행합니다.

$ kubectl argo rollouts promote canary-demo
rollout 'canary-demo' promoted

모든 업데이트가 잘 완료 되었는지 확인합니다.

$ kubectl argo rollouts get rollout canary-demo -w
Name:            canary-demo
Namespace:       default
Status:          ✔ Healthy
Strategy:        Canary
  Step:          8/8
  SetWeight:     100
  ActualWeight:  100
Images:          argoproj/rollouts-demo:yellow (stable)
Replicas:
  Desired:       5
  Current:       5
  Updated:       5
  Ready:         5
  Available:     5

NAME                                     KIND        STATUS        AGE  INFO
⟳ canary-demo                            Rollout     ✔ Healthy     28m
├──# revision:2
│  └──⧉ canary-demo-689684c976           ReplicaSet  ✔ Healthy     19m  stable
│     ├──□ canary-demo-689684c976-c6947   Pod         ✔ Running     19m  ready:1/1
│     ├──□ canary-demo-689684c976-f5zkc   Pod         ✔ Running     60s  ready:1/1
│     ├──□ canary-demo-689684c976-hzgmv   Pod         ✔ Running     47s  ready:1/1
│     ├──□ canary-demo-689684c976-6ffxx   Pod         ✔ Running     34s  ready:1/1
│     └──□ canary-demo-689684c976-97q4d   Pod         ✔ Running     21s  ready:1/1
└──# revision:1
   └──⧉ canary-demo-6f8b8d584            ReplicaSet  • ScaledDown  28m

canary-demo Rollout이 revision: 2 새 버전의 ReplicaSet으로 모두 업데이트 되면서 기존의 ReplicaSet은 ScaleDown 상태로 변경되었습니다. ScaleDown에 대해서는 다루지 않으며 아래의 링크에서 확인하시기 바랍니다.

🔗 https://argoproj.github.io/argo-rollouts/features/scaledown-aborted-rs/

Argo CD UI와 Argo Rollouts UI에서 Pod가 new ReplicaSet으로 업데이트 되는 상황을 시각화를 통해 확인할 수 있습니다.

  • Argo CD UI

argo-rollouts-demo-argocd-animate-03.gif

  • Argo Rollouts UI

argo-rollouts-demo-canary-UI-03.png

argo-rollouts-demo-canary-UI-04.png

  • canary-demo trafficWeight 20 ~ 80% 적용후 접속화면

argo-rollouts-demo_canary-04.gif

  • new Demo Application (yellow) 접속 화면

argo-rollouts-demo_canary-03.gif

지금까지 Argo Rollouts을 사용한 Canary Deployment에 대해서 알아 보았습니다.

Rollout resource에 대한 추가적인 옵션과 설명은 다음 링크에서 확인하여 고급 배포 전략을 구현해보시기 바랍니다.

Rollouts Specification

 

Official Website

 

Reference

 

END