LoginSignup
0
0

ArgoRolloutsによるカナリアデプロイの動作検証メモ

Posted at

1. はじめに

以前ArgoRolloutsを利用したBlue/Greenデプロイの検証結果をまとめましたが、今回はカナリアデプロイの動作について検証します。
以前実施したBlue/Greenデプロイ方式の動作検証結果はこちらとなります。

環境はBlue/Greenデプロイ検証と同じmninikubeを利用します。
またアプリもBlue/Greenデプロイ検証で利用したアプリを利用するため、Blueアプリ・Greenアプリと呼びます。

2. ArgoRolloutsを利用したカナリアデプロイについて

ArgoRolloutsではデプロイ戦略にカナリアデプロイが利用できます。
カナリアデプロイでは指定した重みに基づいてリクエストを新旧のアプリに振り分けます。
通常のRolloutとServiceの構成では、リクエストの重みのみが設定可能ですが、Ingressを利用することでヘッダー情報によるリクエストの振り分けることも可能です。

今回は下記の方式について検証することにします。

  1. 通常の重み付けによるリクエストの振り分け方式
  2. Nginx Ingress Controllerによる振り分け方式

Ingressを利用するトラフィック制御はNginx以外にもALBやistioなども利用可能です。

3. 通常の重み付けによるリクエストの振り分け方式

3.1 概要

下図の順にカナリアデプロイが動作することを検証します。

カナリアデプロイフロー1.png

今回の例では下記の順でGreenアプリがデプロイされ、リクエストが振り分けられます。

(1). リクエストの20%をGreenアプリに振り分ける
(2). 手動でのPromote後にリクエストの50%をGreenアプリに振り分ける
(3). Promote完了の60秒後にリクエストの80%Greenアプリに振り分ける
(4). すべてのリクエストをGreenアプリに振り分ける

3.1 マニフェストファイルの作成

Rolloutリソースに対応するServiceリソースを作成します。

canary-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: rollout-canary-rest-api-app-svc
spec:
  selector:
    app: rollout-canary-rest-api-app
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

Blue/Greenデプロイと同様、マニフェストファイルのkindはDeploymentではなくRolloutになります。
また、Rolloutの構造はDeploymentとよく似ていますが、strategy:にデプロイ戦略の設定を追記します。
カナリアリリースの場合は、canary.stepsで各Stepでの操作を指定します。

canary-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-canary-rest-api-app
spec:
  replicas: 5
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-canary-rest-api-app
  template:
    metadata:
      labels:
        app: rollout-canary-rest-api-app
    spec:
      containers:
        - name: rollout-canary-rest-api-app
          image: rest-api-app:blue
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
  strategy:
    canary:
      steps:
        - setWeight: 20
        - pause: {}
        - setWeight: 50
        - pause: {duration: 60}
        - setWeight: 80
        - pause: {}

3.2 カナリアデプロイの実行

カナリアデプロイを実行するため、Serviceリソースを立ち上げます。
また、minikubeのコマンドを利用してServiceのURLを取得します。

$ kubectl apply -n sample canary-service.yaml

$ minikube service -n sample rollout-canary-rest-api-app-svc --url
http://192.168.49.2:30576

3.2.1 Blueアプリのリリース

Rolloutリソースをデプロイします。
Rolloutリソースのイメージタグはblueを指定しているため、レスポンスもblueとなります。

$ kubectl apply -n sample -f canary-rollout.yaml
$ curl http://192.168.49.2:30576/sample/version 
{"appVersion":"blue","env":" default"}

ArgoRolloutでのダッシュボードは下記のとおりとなります。

image.png

3.2.2 Greenアプリのリリース

canary-rollout.yamlのイメージタグをgreenに変更し、Rolloutリソースをデプロイします。
すでにBlueアプリがデプロイ済みのため、新規にGreenアプリのアプリが立ち上がります。
リクエストの振り分けは20%となっているため、1/5の確率でGreenアプリからレスポンスが返ります。

$ kubectl apply -n sample -f canary-rollout.yaml
$ curl http://192.168.49.2:30576/sample/version 
{"appVersion":"blue","env":" default"}
{"appVersion":"blue","env":" default"}
{"appVersion":"blue","env":" default"}
{"appVersion":"blue","env":" default"}
{"appVersion":"green","env":" default"}

ArgoRolloutでのダッシュボードでもGreenアプリのPodが立ち上がっていることがわかります。

image.png

その後、promoteコマンドを実行しGreenアプリのPod数を増やします。
リクエストを50%ずつに割り振るため、blue/greenそれぞれのアプリのPod数は3となります。

$  kubectl argo rollouts promote -n sample rollout-canary-rest-api-app

image.png

promoteコマンド実行完了の60秒後にリクエストの振り分けを80%にするためPod数の調整が自動で実行されます。

image.png

Pod数の自動調整後promoteコマンドを実行します。
promoteコマンド実行によりblueバージョンのPodは縮退し、すべてのPodがgreenバージョンに切り替わります。

image.png

4. Nginx Ingress Controllerによる振り分け方式

4.1 概要 {#nginx-abstract}

Nginx Ingress Controllerによりリクエストを振り分けます。
Nginx Ingress Controllerによるトラッフィク制御については下記に記載されています。

今回検証したアプリの構成は下図のとおりです。

nginx-ingress-controller.png

また、今回の検証に当たりこちらの記事を参考にしました。

4.2 MinikubeのIngress設定

Minikube環境を利用しているのでIngressを有効化する必要があります。
下記コマンドによりIngressを有効化します。

$ minikube addons enable ingress

4.3 マニフェストファイルの作成

Serviceのマニフェストを下記のように定義します。
4.1 概要に記載した通り、Serviceは2つ必要となります。

rollouts-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: rollout-canary-rest-api-app-svc-stable
spec:
  selector:
    app: rollout-canary-rest-api-app
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: rollout-canary-rest-api-app-svc-canary
spec:
  selector:
    app: rollout-canary-rest-api-app
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

次にNginx Ingress Controllerリソースをデプロイする必要があります。
Ingressのマニフェストは下記のとおりです。

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rollout-canary-stable-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: rollout-canary-rest-api-app.info
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: rollout-canary-rest-api-app-svc-stable
                port:
                  number: 8080

最後にRolloutリソースを定義します。

rollout-canary.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-canary-rest-api-app
spec:
  replicas: 4
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollout-canary-rest-api-app
  template:
    metadata:
      labels:
        app: rollout-canary-rest-api-app
    spec:
      containers:
        - name: rollout-canary-rest-api-app
          image: rest-api-app:blue
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
  strategy:
    canary:
      stableService: rollout-canary-rest-api-app-svc-stable
      canaryService: rollout-canary-rest-api-app-svc-canary
      trafficRouting:
        nginx:
          stableIngress: rollout-canary-stable-ingress
          annotationPrefix: nginx.ingress.kubernetes.io
          additionalIngressAnnotations:
            canary-by-header: 'X-Canary'
            canary-by-header-value: 'true'
            canary-weight: '0'
      steps:
        - setWeight: 10
        - pause: {}

strategy:canary:に2つのServiceを設定します。
また、trafficRoutingにリクエストの振り分けルールを定義します。
そして、stepsに重みを設定します。

この設定により、リクエストのヘッダにX-Canary:trueが設定されたリクエストはカナリア面に振り分けられます。
一方でヘッダが設定されていないリクエストは重みの設定に従い、10%の確率でカナリア面に振り分けられます。
また、これら以外にもCookieによるリクエストの振り分けも可能です。

ルーティングの制御ルールには優先度があり、canary-by-headerが最も優先度高くcanary-by-cookiecanary-weightの順となります。

詳細は下記を参照ください。

4.4 カナリアデプロイの実行

4.4.1 Blueアプリのリリース

Nginxを利用するため、IPではなくホスト名でアクセスする必要があります。
まずはMinikubeが公開しているIPを下記コマンドで調べます。

$ minikube ip

判明したIPを/etc/hostsに設定します。
ホスト名にはIngressのマニフェストに記載したhost部となります。

/etc/hosts
# Ingress hosts configuration
192.168.49.2   rollout-canary-rest-api-app.info

Rolloutリソースをデプロイします。
Rolloutリソースのイメージタグはblueを指定しているため、レスポンスもblueとなります。

$ curl http://rollout-canary-rest-api-app.info/sample/version
{"appVersion":"blue","env":" default"}

image.png

4.4.2 Greenアプリのリリース

canary-rollout.yamlのイメージタグをgreenに変更し、Rolloutリソースをデプロイします。
すでにBlueアプリがデプロイ済みのため、新規にGreenアプリが立ち上がります。
Podの数は下図のとおりです。

image.png

リクエストの振り分けは10%となっているため、1/10の確率でGreenアプリからレスポンスが返ります。

$ curl http://rollout-canary-rest-api-app.info/sample/version
{"appVersion":"blue","env":" default"}
{"appVersion":"blue","env":" default"}
  ・・・
{"appVersion":"green","env":" default"}

次に、リクエストヘッダーを付与してリクエストすると、Greenアプリからレスポンスが返ります。

$ curl -H 'X-Canary:true' http://rollout-canary-rest-api-app.info/sample/version
{"appVersion":"green","env":" default"}

以上のことからNginx Ingress Controllerによる振り分け制御が有効化されていることがわかります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0