Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

リリース/ロールバックの自動判断&実施で運用コストを絶大削減「プログレッシブデリバリー」をArgo Rolloutsで実践しようCloud Nativeチートシート(28)

Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、先進的なリリース戦略「プロフレッシブデリバリー」を「Argo Rollouts」で実践する。

» 2023年06月15日 05時00分 公開
[飯野拓人, 岡本隆史, 正野勇嗣株式会社NTTデータ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する本連載「Cloud Nativeチートシート」。前回の記事「ブルーグリーンデプロイとカナリアリリースを理解したいならOSSの『Argo Rollouts』で実践しよう」では、Argo Rolloutsを利用して、ブルーグリーンデプロイとカナリアリリースを実践しました。今回は、プログレシッブデリバリー(Progressive Delivery)について解説し、Argo Rolloutsを用いて実践します。

プログレッシブデリバリーとは?

 「プログレッシブデリバリー」とは、RedMonkのJames Governor氏がMicrosoftのSam Guckenheimer氏のリリースモデル「Progressive Experimentation」を聞き、その話をLaunchDarklyのAdam Zimman氏に共有して議論したのをきっかけに生まれた言葉です。

 従って広義の意味でのプログレッシブデリバリーとは、ダークローンチ、フィーチャーフラグ、カナリアリリース、ブルーグリーンデプロイ、A/Bテストによって定義される新しいデリバリーモデルを指します。

 一方で、プログレッシブデリバリーは継続的デリバリー(Continuous Delivery)の進化系とも捉えることができます。継続的デリバリーが「より小さい機能でより頻繁にリリースを繰り返し、徐々に変更する」戦略を取るのに対し、プログレッシブデリバリーは「最初は少人数にリリースしながら、自動的にアプリケーションやサービスの状態を分析、評価し、徐々に大人数のユーザーにリリースする」戦略といえます。

 従って狭義の意味でのプログレッシブデリバリーとは、カナリアリリースを自動化し、分析と評価を用いてリリースとロールバックを自動化するデプロイ戦略を指します。

 具体的に継続的デリバリーと何が違うのか見ていきましょう。従来の継続的デリバリーにおけるデプロイフローがこちらです。

継続的デリバリーにおけるデプロイフロー

 それに対し、プログレッシブデリバリーはこちらです。

プログレッシブデリバリーにおけるデプロイフロー

 新バージョンをリリースする際には、まず一部のテストユーザーおよびトラフィックに対してのみ反映します。ここまでは一般的なカナリアリリースと同様です。

 異なる部分は、カナリアテストが完了した後に、エンドユーザーおよび本番トラフィックに対して反映する前段階として、デプロイされたアプリケーションに対してメトリクスなどを用いた「分析」を行い、問題なければデプロイの継続を、異常が見つかれば即座にロールバックを実行するという戦略を明示的に追加している点です。

 従来のデプロイフローの中に明示的に「分析」や「自動ロールバック」という観点を加えることで、パイプラインによるデプロイスピードと、デプロイに伴うリスクの軽減の両立を目指しています。

Argo Rolloutsのプログレッシブデリバリー機能

 Argo Rolloutsは、Kubernetes上のアプリケーションに対し、プログレッシブデリバリーの中でも、上記で述べた「分析」と「自動ロールバック」機能を提供します。

 リリースされたカナリアに対して、モニタリングツール、オブザーバビリティツールで取得されたメトリクス、あるいは、HTTP/HTTPSアクセスによって取得されたREST APIのレスポンスや「Kubernetes Job」を利用したテスト実行結果などを利用してアプリケーションの「分析」を行い、「分析」の結果から「リリースに異常がある」と判断した場合にはリリース作業を中断して「自動ロールバック」ができます。

 また、上記機能を応用してブルーグリーンデプロイやA/Bテストの自動化にも利用できます。

Argo Rolloutsによる自動化の範囲

 Argo Rolloutsは、前回の記事で紹介したカナリアリリースの機能を拡張して利用しているので、カナリアリリースと同様にトラフィックの制御も自動化ができます。下図で、前回利用したカナリアリリースのフローとプログレッシブデリバリーで自動化できる部分を示します。

Argo Rolloutsによる自動化の範囲

 アプリケーションの分析、カナリア比率の変更とトラフィック制御が自動化され、リリースが完全に自動化されていることを確認できます。

分析で利用できるツール、手段

 Argo Rolloutsでは、分析に下記のようなツールや手段を用いることができます。「Prometheus」「Amazon CloudWatch」のようなオブザーバビリティー/モニタリングツールのメトリクスを利用できる他、Kubernetes Jobを用いて独自のスクリプトで分析したり、Rest APIの返却するJSONの値を調べたり(Argo Rolloutsでは「Web Metrics」と表現されている)することもできます。「Datadog」「New Relic」など商用のオブザーバビリティーツールもサポートに含まれます。

  • Prometheus
  • Datadog
  • New Relic
  • Wavefront
  • Kubernetes Job
  • Web Metrics
  • Kayenta
  • Amazon CloudWatch
  • Graphite
  • InfluxDB
  • Apache SkyWalking

※最新情報は、Analysis & Progressive Deliver(画面左メニューのAnalysisのプラグイン一覧)をご覧ください。

 Argo Rolloutsでは、上記のツールからクエリによって値を取得し、その値が条件に一致するかどうかで、分析できます。例えば、Prometheusを利用した場合、「PromQL」によって、メトリクスを抽出し、抽出したメトリクスの条件を指定できます。

トラフィック制御で利用できるコントローラー

 Argo Rolloutsでは、トラフィック制御に「Ingress」を利用します。対応する「Ingress Controller」は次の通りです。

  • AWS Application Load Balancer (ALB)のIngress Controller
  • Ambassador Edge Stack
  • Apache APISIX
  • Google Cloud
  • Istio
  • Nginx Ingress Controller
  • Service Mesh Interface(SMI)
  • Traefik Proxy

 Argo Rollouts v1.4までは、トラフィック制御機能はArgo Rollouts本体に組み込まれていましたが、Argo Rollouts v1.5からは、プラグインを用いることで拡張できます。プラグイン拡張によって、Gateway APIなどIngress Controller以外のトラフィック制御も今後利用できるようになります。

 ただし、Gateway APIのサポートはまだ試験段階なので、商用環境で利用する場合は注意してください。

※最新動向については、Traffic management¶をご覧ください。

サンプルアプリケーションの概要

 ここからは、利用方法を交えながら、プログレッシブデリバリーを解説します。本稿で用いるサンプルアプリケーションは、エンドユーザーからHTTPリクエストが送信された際に、「Hello World!!!」と応答するシンプルなプログラムです。また、Ingressとして「Nginx Ingress Controller」を用いています。

Argo Rolloutsコントローラーの動き

 デプロイにおける各リソースの動きをArgo Rolloutsコントローラー視点で整理すると、次の通りです。

  • 【1】Rolloutに対して、新バージョン環境の作成を命令する
  • 【2】Rolloutに対して、「分析」開始を命令する
  • 以下工程を、「AnalysisRun」が正常に稼働し続けている状態かつ、カナリア環境に全てのトラフィックが流れるまで繰り返す
    1. 【3】【6】【9】Rolloutに対して、新バージョン環境のPod数増加を命令する
    2. 【4】【7】【10】Ingressコントローラーに対して、カナリア環境へのトラフィック割合増加を命令する
    3. 【5】【8】【11】Rolloutに対して、旧バージョン環境のPod数削減を命令する
  • 【12】Rolloutに対して、「分析」終了を命令する
概要図

 今回は、カナリアリリース後にアプリケーションを分析するのではなく、リリース前から継続的に分析するようにしています。これによって、リリース前は分析結果が正常になっていることを確認できる(リリース前の状態が問題ないことと、分析が間違っていないこと)他、リリース実行中のカナリアPodの作成/増加中やトラフィックの切り替え時などでも影響がないことを確認できます。

ダークカナリアリリースの採用

 また今回のサンプルでは、本番トラフィックは既にリリースされたバージョンに向けたままにし、「分析」で送信されるトラフィックのみカナリアに送信されるように設定する、「ダークカナリアリリース」という手法を採用しています。

 これを応用した例として、以下ユースケースを考えてみましょう。

  • サービス利用者には「個人利用目的の無料会員」「エンタープライズ契約中の有料会員」の2形態が存在している
  • 「個人利用目的の無料会員」に対してSLA(サービス品質保証)を明示していない
  • 「エンタープライズ契約をしている有料会員」に対してSLAを明示しており、問題が発生した際には迅速なサポートが求められる

 このようなサービスの場合「エンタープライズ契約中の有料会員」を初期段階でカナリア用トラフィックとして割り当てるのは、非常にリスクが高いので避けるべきです。一方で「個人利用目的の無料会員」はそういったリスクが比較的小さいので、カナリア用トラフィックとして適しています。

 そこで、あらかじめサービス利用形態を識別するHTTPリクエストヘッダ(例:「X-User-Type: Free-User」)を付与しておき、そのヘッダを参照してカナリア用トラフィックか否かを判断するように設定するといいでしょう。これによって「個人利用目的の無料会員」が新バージョンを先行利用し、問題なければ「エンタープライズ契約中の有料会員」に段階的に新バージョンを提供するといった、高品質なリリースを実現できます。

実装編――Argo Rolloutsによるプログレッシブデリバリー

 ここからは、サンプルを動かしてプログレッシブデリバリーの動作を確認します。手順は次の通りです。

  • A)Kubernetesマニフェストの準備
    Kubernetesにデプロイするマニフェストファイルを作成。ただし、「Deployment」リソースに対してはDeploymentの代わりに「Rollout」リソースを利用し、プログレッシブデリバリーを可能にする
  • B)Argo CDの設定
    本稿ではデプロイ自動化ツールとして「Argo CD」を利用するので、Argo CDにマニフェストファイルを格納したGitリポジトリを登録する
  • C)デプロイ時の挙動確認
    旧バージョン(v1)がデプロイされている状態の環境に対し、新バージョン(v2)をデプロイした際の挙動を確認する
  • D)ロールバック時の挙動確認
    旧バージョン(v2)がデプロイされている状態の環境に対し、新バージョン(error)をデプロイしたところ「分析」フェーズで「異常」と判断され、自動的に旧バージョン(v2)に戻される際の挙動を確認する

A)Kubernetesマニフェストの準備

 サンプルリポジトリの「manifests/04_Progressive」フォルダ配下にプログレッシブデリバリーに関連するサンプルがあります。

 ファイル構成は次の通りです。

04_Progressive
├── analysis-template.yaml  # AnalysisTemplate定義
├── ingress.yaml
├── kustomization.yaml
├── namespace.yaml
├── rollout.yaml  # Rollout定義
├── service-canary.yaml  # CanaryのService定義
└── service-stable.yaml  # StableのService定義

 Argo Rolloutsによるプログレッシブデリバリーのポイントは、次の通りです。

  • Deploymentリソースではなく、Rolloutリソースを利用すること
  • サービス定義は本番トラフィック用の「Stable」サービスと、カナリアトラフィック用の「Canary」サービスの2つを用意すること
  • どういった「分析」をするかが定義された「AnalysisTemplate」リソースを用意すること
  • 「どのリクエストをカナリア用トラフィック対象とするか」をRolloutリソースに設定すること

 特にRolloutリソース(rollout.yaml)はArgo Rollouts独自リソースで、今回のハンズオンの肝となるリソースです。プログレッシブデリバリーでは、下記のようにRolloutリソース(rollout.yaml)を定義します。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: progressive-demo
spec:
  replicas: 5
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: progressive-demo
  template:
    metadata:
      labels:
        app: progressive-demo
    spec:
      containers:
      - name: hello-world
        image: registry.gitlab.com/cloudnativetips/argorollouts-sample/hello-world:v1
        imagePullPolicy: Always
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 5m
  strategy:  # この部分が「Rollout」独自の拡張定義
    canary:
      stableService: progressive-demo-stable  # StableのService定義
      canaryService: progressive-demo-canary  # CanaryのService定義
      dynamicStableScale: true  # StableのPod数のトラフィックに比例した変動
      analysis:  # 「分析」定義(詳細は後述)
        templates:
        - templateName: progressive-analysis
        args:
        - name: ingress-ip
          value: "192.168.49.2"
        - name: target-endpoint
          value: pg.dev.sample.io
        - name: canary-flag
          value: "true"
        - name: error-threshold
          value: "5"
      steps:  # プログレッシブデリバリー工程(詳細は後述)
      - setCanaryScale:
          replicas: 1
      - pause: {duration: 3m}
      - setWeight: 40
      - setCanaryScale:
          matchTrafficWeight: true
      - pause: {duration: 1m}
      - setWeight: 60
      - pause: {duration: 1m}
      trafficRouting:
        nginx:
          stableIngress: progressive-demo  # Ingress定義
          additionalIngressAnnotations:  # カナリア用トラフィック対象となるリクエスト判定の定義
            canary-by-header: X-Canary
            canary-by-header-value: "true"

 前回の記事でも説明しましたが、定義をよく見ると、Deploymentリソースに似ていることが分かると思います。RolloutリソースはDeploymentリソースの拡張なので、strategy定義の部分でブルーグリーンデプロイやカナリアリリースなどのデプロイ戦略を定義します。今回利用するプログレッシブデリバリーはカナリアリリースを拡張したものなので、ここではカナリアリリースを設定しています。

 前回、Argo Rolloutsによる単純なカナリアリリースを紹介しましたが、前回のサンプルと比較すると、分析のためのanalysisの項目が異なります。

B)Argo CDの設定

 Argo CDを用いてサンプルをデプロイし、旧バージョン(v1)がデプロイされている初期状態を作ります。

 今回はArgo CDに登録するための設定済み定義ファイルを「manifests/argocd/application-progressive.yaml」に用意しています。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: progressive-demo
spec:
  project: default
  source:
    repoURL: https://gitlab.com/cloudnativetips/argorollouts-sample.git  # 同期対象となるGitリポジトリのURL
    targetRevision: main  # 同期対象となるブランチ名
    path: manifests/04_Progressive  # 同期対象となる「Kustomize」のファイルパス
  destination:
    server: https://kubernetes.default.svc

 もし、サンプルリポジトリを自分の環境にForkする場合には「repoURL」の部分を変更して利用してください。

 下記コマンドでデプロイできます。

kubectl -n argocd apply -f manifests/argocd/application-progressive.yaml

 無事設定が完了すると下記画像のようなカードがArgo CDダッシュボード上に表示されていることを確認できます。

ダッシュボード画面

 この状態では、まだArgo CDに登録されているだけです。デプロイされているわけではないので、先のカードの「Sync」ボタンから同期します。

 無事同期が完了すると、カード表示が切り替わることを確認できるので、カードを選択してデプロイされたサンプルを確認します。

同期完了

 ステータスが「Synced」となっており、旧バージョン(v1)のPodが5台稼働していることを確認できます。

C)デプロイ時の挙動確認

 デプロイ時の動きを確認します。今回は次の手順に沿って作業します。

  1. 初期状態の確認
    エンドユーザーに公開されているエンドポイント"pg.dev.sample.io"に対してリクエストを送信すると、必ず旧バージョン(v1)からレスポンスが返却されることを確認する
  2. プロモート実行
    Rolloutのイメージバージョンを新バージョン(v2)に切り替えた後にArgo CDで同期し、デプロイが開始されることを確認する。この時エンドユーザーに公開されているエンドポイント"pg.dev.sample.io"に対してリクエストを送信すると、段階的に新バージョン(v2)からのレスポンス返却割合が増加していることを確認する
  3. 最終状態の確認
    エンドユーザーに公開されているエンドポイント"pg.dev.sample.io"に対してリクエストを送信すると、必ず新バージョン(v2)からレスポンスが返却されることを確認する
デプロイ時フロー

・1. 初期状態の確認

 ノンストップデプロイを体感するために、今回はデプロイ実行中エンドユーザーに成り代わって常に本番トラフィックを流し続けます。次のコマンドによって、1秒間隔で本番トラフィック用リクエストの送信を開始します。

# 1秒間隔で本番トラフィック用リクエストを送信(「Ctrl」+「C」キーで停止)
TARGET_ENDPOINT=http://pg.dev.sample.io CANARY_FLAG=false ERROR_THRESHOLD=5 go run apps/analysis-job/cmd.go

 コマンド出力結果として、常に旧バージョン(v1)からレスポンスが返却されることを確認できれば準備万端です。

2023/05/01 00:00:00 [START] analysis-job
2023/05/01 00:00:00 Send request[1]
2023/05/01 00:00:00 Receive response[1]: {version: v1}
2023/05/01 00:00:01 Send request[2]
2023/05/01 00:00:01 Receive response[2]: {version: v1}
2023/05/01 00:00:02 Send request[3]
2023/05/01 00:00:02 Receive response[3]: {version: v1}
2023/05/01 00:00:03 Send request[4]
2023/05/01 00:00:03 Receive response[4]: {version: v1}
2023/05/01 00:00:04 Send request[5]
2023/05/01 00:00:04 Receive response[5]: {version: v1}
...

・2. プロモート実行

 次に、デプロイ対象のイメージバージョンを新バージョン(v2)に変更します。

 Argo CDはGitOpsツールなので書き換えたRolloutリソースを通常はGitにPushしますが、筆者が利用したGitリポジトリを利用してもらう関係上、今回はArgo CDの機能を使ってイメージバージョンを一時的に変更します。

 Argo CDダッシュボードから「App Details」ボタンをクリックし、「Parameters」タブの該当箇所を「v2」に変更し「Save」ボタンで保存します。

イメージタグ変更

 ステータスが「OutOfSync」に変わった後に「Sync」ボタンをクリックし、デプロイが開始されることを確認します。

同期実行

 デプロイが開始されると、既存の旧バージョン(v1)リソースに加えて新たに新バージョン(v2)リソースが作成され、旧バージョン(v1)Podが5台と新バージョン(v2)Podが1台稼働している状態になります。

 それと同時にAnalysisTemplateリソースからAnalysisRunリソース、AnalysisRunリソースからKubernetes Jobリソースが生成されて「分析」が開始することを確認します。

分析実行

 これらの挙動は、次の定義によります。

   ...
   spec:
     strategy:
       canary:
         ...
         analysis:  # AnalysisTemplate呼び出し
           templates:  # 「分析」に用いるAnalysisTemplate名
           - templateName: progressive-analysis
           args:  # AnalysisTemplateに渡す引数
           - name: ingress-ip
             value: "192.168.49.2"
           - name: target-endpoint
             value: pg.dev.sample.io
           - name: canary-flag
             value: "true"
           - name: error-threshold
             value: "5"
   ...
Rolloutリソース(rollout.yaml)
   apiversion: argoproj.io/v1alpha1
   kind: AnalysisTemplate
   metadata:
     name: progressive-analysis
   spec:  # AnalysisTemplate/AnalysisRun定義
     args:  # AnalysisTemplateで用いる引数定義
     - name: ingress-ip
     - name: target-endpoint
     - name: canary-flag
     - name: error-threshold
     metrics:
     - name: success-rate
       initialDelay: 10s  # 遅延時間(カナリア用Podの作成完了を待つ)
       provider:
         job:  # Analysis種別
           spec:  # Kubernetes Job定義
             backoffLimit: 1
             template:
               spec:
                 hostAliases:
                 - ip: "{{ args.ingress-ip }}"
                   hostnames:
                   - "{{ args.target-endpoint }}"
                 containers:
                 - name: analysis-job
                   image: registry.gitlab.com/cloudnativetips/argorollouts-sample/analysis-job:latest
                   imagePullPolicy: Always
                   env:
                   - name: TARGET_ENDPOINT
                     value: "http://{{ args.target-endpoint }}/"
                   - name: CANARY_FLAG
                     value: "{{ args.canary-flag }}"
                   - name: ERROR_THRESHOLD
                     value: "{{ args.error-threshold }}"
                 restartPolicy: Never
AnalysisTemplateリソース(analysis-template.yaml)

 デプロイを開始して3分経過すると、いよいよ本番トラフィックの一部(40%)をカナリアに流し始めます。本番トラフィック用のリクエスト結果を確認すると、上記変更によって旧バージョン(v1)と新バージョン(v2)からのレスポンスが混ざり合っていることを確認します。

2023/05/01 00:03:20 Send request[200]
2023/05/01 00:03:20 Receive response[200]: {version: v1}
2023/05/01 00:03:21 Send request[201]
2023/05/01 00:03:21 Receive response[201]: {version: v1}
2023/05/01 00:03:22 Send request[202]
2023/05/01 00:03:22 Receive response[202]: {version: v2}  # 新バージョンからのレスポンス
2023/05/01 00:03:23 Send request[203]
2023/05/01 00:03:23 Receive response[203]: {version: v1}
2023/05/01 00:03:24 Send request[204]
2023/05/01 00:03:24 Receive response[204]: {version: v2}  # 新バージョンからのレスポンス
...

 Argo Rolloutsコントローラーはトラフィック割合に応じて適切にReplicasを設定するので、旧バージョン(v1)Podの台数が5から3に減少し、新バージョン(v2)Podの台数が1から2に増加します。

デプロイ実行 40%段階

 その後1分経過すると、もう1段階カナリア側のトラフィック割合が増加(+20%)します。

 先ほどと同様に、旧バージョン(v1)Podの台数が3から2に減少、新バージョン(v2)Podの台数が2から3に増加します。

デプロイ実行 60%段階

 これらの挙動は、次の定義によります。

steps:
- setCanaryScale:
    replicas: 1  # カナリアのReplicasを固定値で指定
- pause: {duration: 3m}  # 3分間待機
- setWeight: 40  # 全体トラフィックのうち40%をカナリアに流す
- setCanaryScale:
    matchTrafficWeight: true  # カナリアのReplicasをトラフィック割合から自動計算
- pause: {duration: 1m}  # 1分間待機
- setWeight: 60  # 全体トラフィックのうち60%をカナリアに流す
- pause: {duration: 1m}  # 1分間待機

コラム プロジェクト横断でAnalysisTemplateを使うには?

 サンプルでは、ネームスペースごとに定義されるAnalysisTemplateを利用しましたが、クラスタ全体で定義できる「ClusterAnalysisTemplate」も提供されています。

 プロダクトごとではなく複数プロダクト横断で標準的な分析方法を管理したい場合に有用なリソースです。ClusterAnalysisTemplateを利用するには、AnalysisTemplateをClusterAnalysisTemplateとして定義し、Rolloutリソースのテンプレート指定で下記のようにclusterScopeオプションを指定します。

analysis:  
  templates:  
  - templateName: progressive-analysis
    clusterScope: true # この行を追加

・3. 最終状態の確認

 デプロイが完了したので、トラフィックは全て新バージョン(v2)環境で処理されるようになりました。

 デプロイ前には存在していた旧バージョン(v1)のリソースならびにデプロイ作業中に存在していた「分析」リソースは削除され、新バージョン(v2)のリソースのみが存在している状態です。

デプロイ完了

 本番トラフィック用のリクエスト結果を確認すると、確かに新バージョン(v2)からレスポンスが返却されることを確認できます。

2023/05/01 00:06:00 Send request[360]
2023/05/01 00:06:00 Receive response[360]: {version: v2}
2023/05/01 00:06:01 Send request[361]
2023/05/01 00:06:01 Receive response[361]: {version: v2}
2023/05/01 00:06:02 Send request[362]
2023/05/01 00:06:02 Receive response[362]: {version: v2}
2023/05/01 00:06:03 Send request[363]
2023/05/01 00:06:03 Receive response[363]: {version: v2}
2023/05/01 00:06:04 Send request[364]
2023/05/01 00:06:04 Receive response[364]: {version: v2}
...

 以上が、プログレッシブデリバリーにおけるデプロイ実行時の動きです。

D)ロールバック時の挙動確認

 先ほどは新バージョンに異常がなかった際の動きでしたが、100%問題なくリリースできるとは限りません。ここでは新バージョンに異常があり、エンドユーザーへの影響を最小限にするために迅速に旧バージョンにロールバックされた際の動きを確認します。次の手順に沿って作業します。

  1. 初期状態の確認
    エンドユーザーに公開されているエンドポイント"pg.dev.sample.io"に対してリクエストを送信すると、必ず旧バージョン(v2)からレスポンス返却されることを確認する
  2. プロモート実行
    Rolloutのイメージバージョンを新バージョン(error)に切り替えた後にArgo CDで同期し、デプロイが開始されることを確認する。その後「分析」実行によって新バージョン(error)に異常が見つかり、自動的にロールバックが実行されることを確認する
  3. 最終状態の確認
    エンドユーザーに公開されているエンドポイント"pg.dev.sample.io"に対してリクエストを送信すると、必ず旧バージョン(v2)からレスポンスが返却されることを確認する
ロールバック時フロー

 各ステップでの動作を詳しく見ていきましょう。

・1. 初期状態の確認

 今回は、ロールバックされた際でもノンストップであることを体感するために、エンドユーザーに成り代わって常に本番トラフィックを流し続けておきます。次のコマンドによって、1秒間隔で本番トラフィック用リクエストの送信を開始します。

# 1秒間隔で本番トラフィック用リクエストを送信(「Ctrl」+「C」キーで停止)
TARGET_ENDPOINT=http://pg.dev.sample.io CANARY_FLAG=false ERROR_THRESHOLD=5 go run apps/analysis-job/cmd.go

 常に旧バージョン(v2)からレスポンスが返却されることを確認できれば準備万端です。

2023/05/01 01:00:00 [START] analysis-job
2023/05/01 01:00:00 Send request[1]
2023/05/01 01:00:00 Receive response[1]: {version: v2}
2023/05/01 01:00:01 Send request[2]
2023/05/01 01:00:01 Receive response[2]: {version: v2}
2023/05/01 01:00:02 Send request[3]
2023/05/01 01:00:02 Receive response[3]: {version: v2}
2023/05/01 01:00:03 Send request[4]
2023/05/01 01:00:03 Receive response[4]: {version: v2}
2023/05/01 01:00:04 Send request[5]
2023/05/01 01:00:04 Receive response[5]: {version: v2}
...

・2. プロモート実行

 次に、デプロイ対象のイメージバージョンを新バージョン(error)に変更します。

 Argo CDはGitOpsツールなので、書き換えたRolloutリソースを通常はGitにPushしますが、筆者が利用したGitリポジトリを利用するために、今回はArgo CDの機能を使ってイメージバージョンを一時的に変更します。

 Argo CDダッシュボードから「App Details」ボタンをクリックし、「Parameters」タブの該当箇所を「error」に変更して「Save」ボタンで保存します。

イメージタグ変更

 ステータスが「OutOfSync」に変わった後に「Sync」ボタンをクリックし、デプロイが開始されることを確認します。

同期実行

 デプロイが開始されると、既存の旧バージョン(v2)リソースに加えて新たに新バージョン(error)リソースが作成され、旧バージョン(v2)Podが5台と新バージョン(error)Podが1台稼働している状態になります。

 それと同時にAnalysisTemplateリソースからAnalysisRunリソース、AnalysisRunリソースからKubernetes Jobリソースが生成されて「分析」が開始することを確認します。

分析実行

 本稿では「分析」としてKubernetes Jobを用いたカナリアテスト用独自スクリプトを実行しており、1分間の内HTTPステータスコードが正常(200)ではないレスポンス総数が5回超過した場合に対象サーバを「異常」と判断しています。

※Argo Rolloutsでは他にも外部サービスと連携したメトリクスベースの「分析」が可能です。詳細については前述の通りです。

 Kubernetes Jobのログを確認すると、1分間の内HTTPステータスコードが異常(500)となるレスポンス総数が6回となり、異常終了しているのが分かります。

分析ログ

 しばらくすると「分析」の結果、「新バージョンに異常がある」と判断されて自動的にロールバックされます。

ロールバック実行

・3. 最終状態の確認

 先の工程でロールバックされたことによってトラフィックは全て旧バージョン(v2)環境で変わらず処理されます。

 従って本番トラフィック用のリクエスト結果を確認すると、本来であれば新バージョン(error)からレスポンスが返ってくるはずですが、ロールバックされたことで初期状態と変わらず旧バージョン(v2)からレスポンスが返ることを確認します。

2023/05/01 01:02:00 Send request[120]
2023/05/01 01:02:00 Receive response[120]: {version: v2}
2023/05/01 01:02:01 Send request[121]
2023/05/01 01:02:01 Receive response[121]: {version: v2}
2023/05/01 01:02:02 Send request[122]
2023/05/01 01:02:02 Receive response[122]: {version: v2}
2023/05/01 01:02:03 Send request[123]
2023/05/01 01:02:03 Receive response[123]: {version: v2}
2023/05/01 01:02:04 Send request[124]
2023/05/01 01:02:04 Receive response[124]: {version: v2}
...

 以上が、プログレッシブデリバリーにおけるロールバック時の動きです。いかがでしたでしょうか。

 カナリアリリースをベースとしつつも、デプロイの正当性を「分析」という形で常時モニタリングすることで、従来、運用作業者が手作業で確認していた項目が自動化されて運用負荷の軽減につながります。

自動化でリリースプロセスを見直し、組織の文化も変えるチャレンジを

 多くのプロジェクトでは、アプリケーションやサービスを商用環境にリリースする際にリリース審査などの人手を介したフローを通してリリースしていると思います。プログレッシブデリバリーではそういったフローが人手を介さず自動化されるので「リリースプロセス」も見直す必要があり、「ツールを導入すればいい」という単純な話ではなくなります。

 それに関連して「組織の文化」も変える必要があるでしょう。

 プログレッシブデリバリーは、従来のデリバリーとは一線を画す非常にチャレンジングなデプロイ戦略ですが、上手に運用できればその効果は絶大です。読者の皆さんにはぜひチャレンジしてもらえればと思いますし、本稿がその手助けとなれば幸いです。

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。