Help us understand the problem. What is going on with this article?

Argo Rollouts と ALB Ingress Controller による Canary デプロイメント

概要

Kubernetes で GitOps を実現するツールである Argo CDと、Kubernetes で blue/grenn デプロイや canary リリースを実現するためのデプロイメントコントローラーであるArgo Rolloutsを使用して、canaryリリースの動作検証をしてみます。

前回 Argo Rollouts(以下 Rollouts とします。) と Nginx Ingress Controller(以下 Nginx とします。) の連携の記事を書きました。今回は ALB Ingress Controller(以下 ALB とします。)版となります。

説明が Nginx とかぶる部分があるので、ここでは ALB 特有の設定について説明します。

前回の記事(Argo Rollouts と Nginx Ingress Controller による Canary デプロイメント)
https://qiita.com/tomozo6/items/1bfc65a86a528f63d205

各マニフェスト

Ingress

ALB用の Ingress です。
Nginx と Rollouts を連携させたときは、 ingress についてはあまり特殊な設定をすることは無かったのですが、 ALB の場合は ingress の設定がキモになります。

ing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: tomozo
  namespace: tomozo
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/security-groups: tomozo-securitygroup-arn
    alb.ingress.kubernetes.io/certificate-arn: tomozo-certificate-arn
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_302"}}'
    alb.ingress.kubernetes.io/conditions.x-canary-header: '[{"Field":"http-header","HttpHeaderConfig":{"HttpHeaderName": "X-Canary", "Values":["true"]}}]'
    alb.ingress.kubernetes.io/actions.x-canary-header: '{"Type":"forward","ForwardConfig":{"TargetGroups":[{"ServiceName":"tomozo-canary","ServicePort":"8080"}]}}'
spec:
  rules:
  - host: tomozo.tokyo
    http:
      paths:
      - path: /*
        backend:
          serviceName: ssl-redirect
          servicePort: use-annotation
      - path: /*
        backend:
          serviceName: x-canary-header
          servicePort: use-annotation
      - path: /*
        backend:
          serviceName: tomozo-stable
          servicePort: use-annotation

細かく解説していきます。

ALB の基本的な設定(Rollouts関係無し)

annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/security-groups: tomozo-securitygroup-arn
    alb.ingress.kubernetes.io/certificate-arn: tomozo-certificate-arn

これは Rollouts 連携が無くても必要な、ALB自体の設定となります。そのため特にここでは解説しません。

http -> https リダイレクト設定(Rollouts関係無し)

annotations:
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_302"}}'
~
spec:
  rules:
  - host: tomozo.tokyo
    http:
      paths:
      - path: /*
        backend:
          serviceName: ssl-redirect
          servicePort: use-annotation

これも Rollouts 連携とは関係ありません。 http -> https への強制リダイレクト設定となります。詳しくは ALB のドキュメントを参考にしてください。

特定のリクエストヘッダーを付与してアクセスすると必ず Canary サービスにルーティングされるようにする

annotations:
    alb.ingress.kubernetes.io/conditions.x-canary-header: '[{"Field":"http-header","HttpHeaderConfig":{"HttpHeaderName": "X-Canary", "Values":["true"]}}]'
    alb.ingress.kubernetes.io/actions.x-canary-header: '{"Type":"forward","ForwardConfig":{"TargetGroups":[{"ServiceName":"tomozo-canary","ServicePort":"8080"}]}}'
~
spec:
  rules:
  - host: tomozo.tokyo
    http:
      paths:
      - path: /*
        backend:
          serviceName: x-canary-header
          servicePort: use-annotation

Canaryリリースは本来stablecanaryに決めた割合でルーティングされますが、この仕組みを入れることで開発者側からは必ずcanary側にルーティングされるようにできます。canary側へ振られる割合を 0% にすれば、ヘッダールーティングによる Blue/Green デプロイにもなります。

Nginx のときは、Rollouts の strategy.canary.trafficRouting.nginx.additionalIngressAnnotationsにて、ヘッダールーティング(canary-by-header)の設定できたのですが、ALB用の strategy ではそのような設定が無かったのでだいぶ悩みました。まあおそらく Rollouts の開発者も「ALBのingressでできるからそっちでよしなにやってよ」ということなんだと思います。

ここでの設定は、リクエストヘッダーX-Canaryの値がtrueの場合は、tomozo-canaryにルーティングさるという設定になっています。

Rollouts との連携箇所

spec:
  rules:
  - host: tomozo.tokyo
    http:
      paths:
      - path: /*
        backend:
          serviceName: tomozo-stable
          servicePort: use-annotation

ここが今回理解が難しかったです。ここに記載している tomozo-stable は、Kubernetesのsvcを指しているのではなく、 annotation名(alb.ingress.kubernetes.io/actions.tomozo-stable)を指しているのです。なので servicePortがuser-annotationになっているのです。
alb.ingress.kubernetes.io/actions.tomozo-stable は Rollouts が Kubernetes上 で追記するので、現時点では存在しないのです。だから結構混乱しました…

Service

通常(安定版)用の Service として tomozo-stable。Canary用の Service として tomozo-canaryを定義します。名前以外は全て同じ設定値で問題ありません。

---
kind: Service
apiVersion: v1
metadata:
  name: tomozo-stable
spec:
  type: NodePort
  selector:
    app: tomozo
  ports:
    - port: 8080
---
kind: Service
apiVersion: v1
metadata:
  name: tomozo-canary
spec:
  type: NodePort
  selector:
    app: tomozo
  ports:
    - port: 8080

rollout

strategy:より上は deployment と書き方変わりません。大事なのは trafficRouting で alb を指定しているところです。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: tomozo
  labels:
    app: tomozo
spec:
  selector:
    matchLabels:
      app: tomozo
  template:
    metadata:
      labels:
        app: tomozo
    spec:
      serviceAccountName: tomozo
      containers:
        - name: tomozo
          image: tomozo-repo/tomozo:0.0.1
# -----この行から上は元のDeploymentと一緒------
# -----この行から下はRolloutの拡張部分------
  strategy:
    canary:
      stableService: tomozo-stable  # ingressに actions.tomozo-stable が作成される
      canaryService: tomozo-canary
      trafficRouting:
        alb:
           ingress: tomozo      # ingress名を指定する
           servicePort: 8080
      steps:
        - setWeight: 10
        - pause: {}

このように tomozo-stable を設定することで、 ingress に以下のアノテーションが追加されます。

    alb.ingress.kubernetes.io/actions.tomozo-stable: |
      {
        "Type":"forward",
        "ForwardConfig":{
          "TargetGroups":[
            {
                "Weight":0,
                "ServiceName":"tomozo-canary",
                "ServicePort":"8080"
            },
            {
                "Weight":100,
                "ServiceName":"tomozo-stable",
                "ServicePort":"8080"
            }
          ]
        }
      }

新しいコンテナイメージをリリースすると、 tomozo-stable.steps.setWeightに合わせて、 上記アノテーションの Weight を調整することで Canaryデプロイメントを実現しています。

tomozo6
元Cobolerで金融系案件のPM。 インフラの技術に興味があって転職。 オンプレのホスティングサービスの構築,保守,運用を担当。 現在、時代の流れによりオンプレ環境を全てAWSへ移設する作業中。 全体改善,効率化,DevOpsが最近の興味関心。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away