Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、代表的なデプロイ戦略の「ブルーグリーンデプロイ」と「カナリアリリース」について「Argo Rollouts」で実践する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する本連載「Cloud Nativeチートシート」。前回から「Argo Rollouts」に触れ、シリーズを通して概要からハンズオンを交えた使い方までを紹介していきます。前回は第1弾として、Argo Rolloutsの概要とサポートされるデプロイ戦略について解説しました。
今回は、手を動かすハンズオンを交えて「Argo Rolloutsがどのように動くのか」について理解していただきたいと思います。具体的には、前回紹介した代表的なデプロイ戦略の内「ブルーグリーンデプロイ」と「カナリアリリース」を取り上げ、Argo Rolloutsで指定できるデプロイパラメーターの詳細についても解説します。なお、プログレッシブデリバリーについては次回紹介する予定です。
ハンズオンに当たり、実行環境の準備が必要です。本稿では下記バージョンのソフトウェアで動作を検証します。他のバージョンでも同様に動くと思いますが、全ての環境で検証していないことにご留意ください。
項目 | バージョン |
---|---|
Kubernetes | v1.26.2 |
Argo CD | v2.6.4 |
Argo Rollouts | v1.4.1 |
Argo Rolloutsの利用を始める前に、Argo RolloutsおよびアプリケーションをデプロイするKubernetesクラスタを用意してください。
本稿で利用するサンプルアプリでは「Ingress」を利用します。「minikube」の場合はデフォルトでIngress機能が有効化されていないので、Ingress拡張機能を有効化してください。
minikube addons enable ingress ingress-dns
作成したKubernetesクラスタ上に「argocd」ネームスペースを作成し、Argo CDをデプロイします。
kubectl create namespace argocd kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.6.4/manifests/install.yaml
次のコマンドを別ターミナルで実行します。
kubectl port-forward svc/argocd-server -n argocd 8080:443
ブラウザで「http://localhost:8080」にアクセスすると、Argo CDのダッシュボード画面にアクセスできます。
※なお、管理者ユーザー「admin」のパスワードは下記コマンドで確認できます。Argo CDにログインが必要になる際に利用してください。
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
作成したKubernetesクラスタ上に「argo-rollouts」ネームスペースを作成し、Argo Rolloutsをデプロイします。
kubectl create namespace argo-rollouts kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/download/v1.4.1/install.yaml
本稿で利用するサンプルを「GitLab」で公開しています。次のコマンド(あるいはご利用のIDE)でGitリポジトリをクローンしてください。
git clone https://gitlab.com/cloudnativetips/argorollouts-sample.git
前回のおさらいですが、ブルーグリーンデプロイは、新バージョンのアプリケーションを別の環境にデプロイし、トラフィックを瞬間的に切り替える方法です。旧バージョンと新バージョンが完全に分離しているので、問題が発生した際に迅速にロールバックできます。
デプロイ実行における各リソースの動きをArgo Rolloutsコントローラー視点で整理すると、次の通りです。
本稿では、ブルーグリーンデプロイの動作を次の手順で確認します。
サンプルリポジトリ「manifests/02_BlueGreen」フォルダ配下にブルーグリーンデプロイに関連するサンプルがあります。ファイル構成は次の通りです。
02_BlueGreen ├── ingress.yaml ├── kustomization.yaml ├── namespace.yaml ├── rollout.yaml # Rollout定義 ├── service-active.yaml # 本番トラフィック用Service定義 └── service-preview.yaml # 試験トラフィック用Service定義
Argo Rolloutsによるブルーグリーンデプロイのポイントは、次の2つです。
特に「Rollout」(rollout.yaml)はArgo Rolloutsの独自リソースであり、今回のハンズオンの肝です。ブルーグリーンデプロイ時は、次のようにRolloutリソース(rollout.yaml)を定義します。
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: bluegreen-demo labels: app: bluegreen-demo spec: replicas: 3 revisionHistoryLimit: 1 selector: matchLabels: app: bluegreen-demo template: metadata: labels: app: bluegreen-demo spec: containers: - name: bluegreen-demo image: registry.gitlab.com/h-meru/argorollouts-hands-on/hello-world:v1 imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP resources: requests: memory: 32Mi cpu: 5m strategy: # この部分が「Rollout」独自の拡張定義 blueGreen: activeService: bluegreen-demo-active # 本番トラフィック用Service定義 previewService: bluegreen-demo-preview # 試験トラフィック用Service定義 autoPromotionEnabled: false # 本番自動昇格の無効化 scaleDownDelaySeconds: 180 # 旧環境の削除猶予期間(秒)
定義をよく見ると、Deploymentリソースに似ていることが分かります。RolloutリソースはDeploymentリソースの拡張です。「strategy」定義の部分で、ブルーグリーンデプロイやカナリアリリースといったデプロイ戦略を定義します。ここではブルーグリーンデプロイを設定します。
これらのサンプルをArgo CDを用いてデプロイし、旧バージョン(v1)がデプロイされている初期状態を作ります。
今回はArgo CDに登録するための設定済み定義ファイルを「manifests/argocd/application-bluegreen.yaml」に用意しています。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: bluegreen-demo spec: project: default source: repoURL: https://gitlab.com/cloudnativetips/argorollouts-sample.git # 同期対象となるGitリポジトリURL targetRevision: main # 同期対象となるブランチ名 path: manifests/02_BlueGreen # 同期対象となるKustomizeファイルパス destination: server: https://kubernetes.default.svc
サンプルリポジトリを読者自身の環境にForkする場合は「repoURL」の部分を変更して利用してください。次のコマンドでデプロイできます。
kubectl -n argocd apply -f manifests/argocd/application-bluegreen.yaml
無事に設定が完了すると、下記画像のようなカードがArgo CDダッシュボード上に表示されていることを確認できます。
この状態では、まだArgo CDに登録されているだけです。デプロイされているわけではないので、先のカードの「Sync」ボタンから同期します。
同期が無事に完了すると、カード表示が切り替わることを確認できるので、カードを選択してデプロイされたサンプルを確認します。
ステータスが「Synced」となっており、旧バージョン(v1)のPodが3つ作られていることを確認できます。
デプロイ実行時の挙動は次の手順に沿って確認します。
・1. 初期状態の確認
エンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」と、非公開となるテスト用エンドポイント「bg.preview.dev.sample.io」に対してリクエストを送信します。
# エンドユーザーに公開されているエンドポイント curl -sS bg.active.dev.sample.io | jq # 非公開となるテスト用エンドポイント curl -sS bg.preview.dev.sample.io | jq
次のようなレスポンスが返されます。
{ "message": "Hello World!!!", "version": "v1" }
・2. 新バージョン環境の作成
デプロイ対象のイメージバージョンを新バージョン(v2)に変更します。ここでは、簡単に操作を試すためにArgo CDの機能を利用してイメージバージョンを変更します。プロジェクトで運用する際には、マニフェスト上(ここではrollout.yaml)のイメージバージョンを変更してGitリポジトリにコミットしてください。Argo CDはGitOpsツールなので、変更したマニフェストをコミットするだけでブルーグリーンデプロイが実施され環境に反映されます。
Argo CDダッシュボードから「App Details」ボタンを押し、「Parameters」タブの該当箇所を「v2」に変更し「Save」ボタンから保存します。
ステータスが「OutOfSync」に変わった後に「Sync」ボタンを押し、ステータスが「Suspended」に変わることを確認します。
この画像からも分かる通り、この時点で既に新バージョン(v2)の環境が作成されており、いつでもトラフィックを受け付けられる状態になっています。
・3. Previewサービス切り替えの確認
エンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」に対してリクエストを送信しても、前回と変わらず旧バージョン(v1)からレスポンスが返されます。
{ "message": "Hello World!!!", "version": "v1" }
一方で、非公開となるテスト用エンドポイント「bg.preview.dev.sample.io」に対してリクエストを送信してみると、新バージョン(v2)からレスポンスが返るように変わります。
{ "message": "Hello World!!!", "version": "v2" }
これはエンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」側のサービスの向き先は変更されずに、テスト用エンドポイント「bg.preview.dev.sample.io」側のサービスの向き先が新バージョン(v2)に切り替わったからです。この状態なら、エンドユーザーに影響を及ばさずに新バージョン(v2)の環境を検証できます。
・4. 昇格実行
「新バージョン(v2)の環境に問題がなかった」と仮定し、昇格します。手順はとても簡単で、Argo CDダッシュボードでRolloutリソースを選択した上で「Resume」を選択するだけです。
ステータスが「Synced」に変わったら、昇格完了です。
・5. Activeサービス切り替えの確認
エンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」と、非公開となるテスト用エンドポイント「bg.preview.dev.sample.io」に対してリクエストを送信すると、両方とも新バージョン(v2)からレスポンスが返るように変化します。
{ "message": "Hello World!!!", "version": "v2" }
これはエンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」側のサービスの向き先が新バージョン(v2)に切り替わったからです。この時点で全てのリクエストが新バージョン(v2)環境に到達するようになり、旧バージョン(v1)環境はサービスから切り離された状態になります。
・6. 旧バージョン環境の削除
今回は「scaleDownDelaySeconds: 180」と設定しているので、昇格完了から3分経過すると旧バージョン(v1)の環境が自動的に削除されるようになっています。Argo CDダッシュボード画面を確認すると、確かに新バージョン(v2)の環境のPodが3つある状態になっていることを確認できます。
以上、ブルーグリーンデプロイにおけるデプロイ実行時の挙動です。
Argo Rolloutsコントローラー側でReplicaSetの制御やServiceの制御を“よしな”にやってくれているので、運用作業者はデプロイ作業ではなくユーザーへの影響のみに集中できるようになりました。
先ほどは「新バージョンに問題がなかった」と仮定した際の動きでしたが、リリース作業は100%問題なくできるとは限りません。ここでは、「新バージョン(v3)に問題がある」と仮定し、エンドユーザーへの影響を最小限にするために、迅速に旧バージョン(v2)にロールバックした際の挙動を確認します。次の手順に沿ってロールバック実行時の動きを確認します。
・1. 新バージョン環境の作成
デプロイ実行時の挙動の確認と同じ手順で、Argo CDダッシュボードから「App Details」ボタンを押し、「Parameters」タブの該当箇所を「v3」に変更して「Save」ボタンで保存します。
ステータスが「OutOfSync」に変わるので、「Sync」ボタンを押してステータスが「Suspended」に変わることを確認します。
・2. Previewサービス切り替えの確認
エンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」に対してリクエストを送信しても、前回と変わらず旧バージョン(v2)からレスポンスが返却されます。
{ "message": "Hello World!!!", "version": "v2" }
一方で、非公開となるテスト用エンドポイント「bg.preview.dev.sample.io」に対してリクエストを送信すると、新バージョン(v3)からレスポンスが返却されるように変化します。
{ "message": "Hello World!!!", "version": "v3" }
・3. ロールバック実行
今回は「新バージョン(v3)に問題があった」と仮定するので、迅速に旧バージョン(v2)にロールバックする必要があります。手順はとても簡単で、Argo CDダッシュボードで「Abort」を選択するだけです。
ステータスが「Degraded」に変わったら、無事にロールバック作業が完了しました。
・4. 最終状態の確認
無事にロールバック作業が完了したので、エンドユーザーに公開されているエンドポイント「bg.active.dev.sample.io」に対してリクエストを送信してみると、旧バージョン(v2)からレスポンスが返却されます。
{ "message": "Hello World!!!", "version": "v2" }
一方でエンドユーザーに非公開となるテスト用エンドポイント「bg.preview.dev.sample.io」に対してリクエストを送信してみると、503エラーが返却されます。
これは本来存在するはずの新バージョン(v3)の環境がロールバックによって削除されたからです。
これは望ましい状態ではないので、ロールバックはあくまでも暫定処置として留意し、修正パッチ適用後の正しいアプリケーションを改めてデプロイすることで「Healthy」な状態を目指しましょう。
Argo Rolloutsにおけるブルーグリーンデプロイのパラメーターについて、参考までに紹介します。
Argo Rolloutsにおけるブルーグリーンデプロイでは次の項目を設定できます。
spec: strategy: blueGreen: activeService: string previewService: string activeMetadata: object previewMetadata: object autoPromotionEnabled: boolean autoPromotionSeconds: int32 maxUnavailable: stringOrInt prePromotionAnalysis: object postPromotionAnalysis: object previewReplicaCount: int32 scaleDownDelaySeconds: int32 scaleDownDelayRevisionLimit: int32 abortScaleDownDelaySeconds: int32 antiAffinity: object
公式HPに掲載されている項目に関しては参照リンクを添付し、掲載されていない項目に関してはGitソースコードから読み解いて解説します。
項目 (デフォルト値) |
解説 |
---|---|
activeService | 旧バージョンのReplicaSetのみにトラフィックを送信するServiceを設定する。これによって通常ユーザーのトラフィックが常に旧バージョンのReplicaSetに到達するようになる |
previewService | 新バージョンのReplicaSetのみにトラフィックを送信するServiceを設定する。これによって、新バージョンテスト用のエンドポイントが提供される。 新バージョン環境の昇格実行前にテスト用リクエストを送信できるので、基本的に設定することを推奨 |
activeMetadata | 新バージョンのPodが昇格した後に付与されるメタデータ |
previewMetadata | 新バージョンのPodがデプロイ作業中(昇格前)に付与されるメタデータ。昇格後にこのメタデータは削除される |
autoPromotionEnabled (true) |
新バージョンのReplicaSetが正常に起動したら自動的に昇格するようにする。このフィールドが指定されていない場合、デフォルトで有効となる。 ReplicaSetが正常に起動する場合もアプリケーションに問題がある可能性があるので、prePromotionAnalysisやpostPromotionAnalysisを構成しない場合は基本的に無効化を推奨 |
autoPromotionSeconds | ロールアウトが「Suspended」状態になってから指定時間が経過すると、新バージョンのReplicaSetを自動的に昇格する。AutoPromotionEnabledがtrueに設定されている場合、このフィールドは無視される |
maxUnavailable (25%) |
デプロイ中に利用できなくなる可能性のあるPodの最大数を定義する。この設定項目は整数値またはパーセンテージを文字列で指定する |
prePromotionAnalysis | トラフィックを新バージョンに切り替える前処理として「分析」フェーズを構成する。「分析」が正常に終了するまで、サービスの向き先変更を抑止できる。「分析」の成功または失敗によって、昇格作業に移るか、ロールバック作業に移るかが決定される |
postPromotionAnalysis | トラフィックを新バージョンに切り替えた後の処理として「分析」フェーズを構成する。「分析」が失敗またはエラーになった場合、トラフィックを以前の安定したReplicaSetに切り替える。scaleDownDelaySecondsが指定されている場合、「分析」途中でも実行が中断され、ReplicaSetをスケールダウンさせる |
previewReplicaCount | 基本的にプレビューのReplicaSetはRolloutで指定されたレプリカ総数に応じてスケールするが、テスト用に完全にスケールアップしたアプリケーションが不要な場合、この機能によってリソースを節約できる。 ブルーグリーンデプロイの良さが失われるので、よほどコスト削減を求められている環境でない限り、設定しないことを推奨 |
scaleDownDelaySeconds (30) |
アクティブServiceが新バージョンのReplicaSetに切り替わった後、旧バージョンのReplicaSetのスケールダウンを指定時間分だけ遅らせる。 0に設定することで自動スケールダウンを抑止できる |
≪scaleDownDelayRevisionLimit | scaleDownDelaySecondsを0に設定した場合、旧バージョンの全てのReplicaSetが残り続けてしまうので、本設定によって保持するReplicaSetの世代数を制限できる |
abortScaleDownDelaySeconds (30) |
デプロイ作業を中断した後、新バージョンのReplicaSetのスケールダウンを指定時間分だけ遅らせる。 ロールバック実行後にデプロイ予定だった新バージョン環境が自動的に削除されてしまうと、解析作業を追加できなくなる可能性があるので、適切な値にすることを推奨。 0に設定することで自動スケールダウンを抑止できる |
antiAffinity | Cluster構成によってはデプロイ完了後に旧バージョン環境が削除された場合、ノードがAutoScalerによって縮退し、縮退したノード上のPodが別のノードに移動されて再起動することがある。ワーカーノードのプールが十分に大きく、かつ、AntiAffinityを設定することで、この頻度を少なくできる |
前回のおさらいですが、カナリアリリースは、新バージョンのアプリケーションを一部のユーザー(カナリア)に対して展開し、徐々に全体に展開する方法です。新バージョンのアプリケーションの品質を評価して問題が発生した場合は迅速にロールバックできます。
デプロイ実行における各リソースの動きをRolloutコントローラー視点で整理すると、次の通りです。
今回は、段階的にカナリア側のトラフィック割合を増やしては都度問題ないことを確認する流れで説明していますが、初回テスト【2】の段階で問題がないことを確認した後に、そのままカナリア環境に全てのトラフィックを流す運用方法もあります。デプロイにかかる運用コストと品質でバランスを見て、どちらが適切かを判断するといいでしょう。
本稿では、カナリアリリースの動作を下記の手順で確認します。
ここからはサンプルを動かして動作を確認します。
サンプルリポジトリの「manifests/03_Canary」フォルダ配下にカナリアリリースに関連するサンプルがあります。ファイル構成は次の通りです。
03_Canary ├── ingress.yaml ├── kustomization.yaml ├── namespace.yaml ├── rollout.yaml # Rollout定義 ├── service-canary.yaml # Canary側Service定義 └── service-stable.yaml # Stable側Service定義
Argo Rolloutsによるカナリアリリースのポイントは、次の2点です。
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: canary-demo spec: replicas: 5 revisionHistoryLimit: 1 selector: matchLabels: app: canary-demo template: metadata: labels: app: canary-demo spec: containers: - name: canary-demo image: registry.gitlab.com/h-meru/argorollouts-hands-on/hello-world:v1 imagePullPolicy: Always ports: - name: http containerPort: 8080 protocol: TCP resources: requests: memory: 32Mi cpu: 5m strategy: # この部分が「Rollout」独自の拡張定義 canary: stableService: canary-demo-stable # Stable側Service定義 canaryService: canary-demo-canary # Canary側Service定義 dynamicStableScale: true # Stable側Pod数のトラフィックに比例した変動 minPodsPerReplicaSet: 2 # ReplicaSetにおける最小Pod数 steps: # カナリアリリース工程(詳細は後述) - setWeight: 20 - pause: {} - setWeight: 40 - pause: {duration: 10} - setWeight: 60 - pause: {duration: 10} - setWeight: 80 - pause: {duration: 10} trafficRouting: nginx: stableIngress: canary-demo # Ingress定義
ブルーグリーンデプロイと同様に、strategyでデプロイ戦略を設定します。ここではカナリアリリースを設定します。
これらのサンプルを、Argo CDを用いてデプロイし、旧バージョン(v1)がデプロイされている初期状態を作ります。今回はArgo CDに登録するための設定済み定義ファイルを「manifests/argocd/application-canary.yaml」に用意しています。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: canary-demo spec: project: default source: repoURL: https://gitlab.com/cloudnativetips/argorollouts-sample.git # 同期対象となるGitリポジトリURL targetRevision: main # 同期対象となるブランチ名 path: manifests/03_Canary # 同期対象となるKustomizeファイルパス destination: server: https://kubernetes.default.svc
もし、サンプルリポジトリを自分の環境にForkする場合は「repoURL」の部分を変更して利用してください。次のコマンドでデプロイできます。
kubectl -n argocd apply -f manifests/argocd/application-canary.yaml
無事に設定が完了すると、下記画像のようなカードがArgo CDダッシュボード上に表示されていることを確認できます。
この状態は、まだArgo CDに登録されているだけで、デプロイされているわけではありません。先のカードの「Sync」ボタンから同期します。
無事に同期が完了すると、カード表示が切り替わることを確認できるので、カードを選択してデプロイされたサンプルを確認します。
ステータスが「Synced」となっており、旧バージョン(v1)のPodが5つ作られていることを確認できます。
デプロイ実行時の挙動は次の手順に沿って確認します。
・1. 初期状態の確認
エンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを送信します。
curl -sS canary.dev.sample.io | jq
次のようなレスポンスが返却されます。
{ "message": "Hello World!!!", "version": "v1" }
・2. 新バージョン環境の作成
デプロイ対象のイメージバージョンを新バージョン(v2)に変更します。
ここでも、簡単に操作を試すためにArgo CDの機能を利用してイメージバージョンを変更します。開発現場で利用する場合は、Gitリポジトリに変更したマニフェストをコミットするようにしてください。
Argo CDダッシュボードから「App Details」ボタンを押し、「Parameters」タブの該当箇所を「v2」に変更して「Save」ボタンから保存します。
ステータスが「OutOfSync」に変わった後に「Sync」ボタンを押し、ステータスが「Suspended」に変わることを確認します。
本来ならカナリア側には2割のトラフィックが到達するので、望ましいカナリア側のPod数は「5 * 0.2 = 1」個のはずです。しかし、「minPodsPerReplicaSet: 2」の設定値によって、最小Pod数が2個と制限されているために上記画像のような構成となります。
・3. カナリアテストの確認
エンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを何回か送付します。
curl -sS canary.dev.sample.io | jq
2割の確率で次のようなレスポンスが返却されます。
{ "message": "Hello World!!!", "version": "v2" }
今回は検証の容易性を考慮して2割という大きな値を設定していますが、本番で利用する際はもっと小さな値を設定するといいでしょう。また、実運用ではカナリアの対象とするユーザーをHTTP Headerなどで区分するケースが多いです。今回は検証を簡略化するために省略しています。
・4. 昇格実行
「新バージョン(v2)の環境に問題がなかった」と仮定し、昇格します。手順はとても簡単で、Argo CDダッシュボードでRolloutリソースを選択した上で「Resume」を選択するだけです。
ここで、改めてRolloutの設定値を確認します。
steps: - setWeight: 20 - pause: {} - setWeight: 40 - pause: {duration: 10} - setWeight: 60 - pause: {duration: 10} - setWeight: 80 - pause: {duration: 10}
上記設定値は、以下のように読み替えることができます。
今回はArgo Rolloutsのサンプルとして上記のような動きに設定しましたが、実運用ではカナリアテスト後に段階的にトラフィックを増加させずに、全てのトラフィックをカナリア側に振り分ける手法もよく使われます。
Argo CDダッシュボード画面を確認すると、トラフィック割合に応じて旧バージョン(v1)と新バージョン(v2)の環境のPod数が変動していることが分かります。
またエンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを送信すると、デプロイ作業が進むにつれて段階的に次のようなレスポンスが返却される確率が高くなっていることを確認できます。
{ "message": "Hello World!!!", "version": "v2" }
・5. 最終状態の確認
先の行程によってトラフィックは全て新バージョン(v2)環境で処理されるようになったはずなので、リクエストを送付して確認します。
エンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを送信してみると、次のようなレスポンスが必ず返却されるように変化したことを確認できます。
{ "message": "Hello World!!!", "version": "v2" }
以上が、カナリアリリースにおけるデプロイ時の挙動です。
Argo Rolloutsコントローラー側でReplicaSetの制御やServiceの制御を“よしな”にやってくれているので、運用作業者はデプロイ作業ではなくユーザー影響のみに集中できるようになりました。
トラフィックの割合を詳細に制御できるので、アプリケーションの特性に合わせてカスタマイズしやすい点も分かったと思います。
先ほどは「新バージョンに問題がなかった」と仮定した際の動きでしたが、リリース作業では100%問題なくリリースできるとは限りません。ここでは「新バージョン(v3)に問題がある」と仮定し、エンドユーザーへの影響を最小限にするために迅速に旧バージョン(v2)にロールバックした際の挙動を確認します。次の手順に沿ってロールバック時の動きを確認します。
・1. カナリアテストの確認
デプロイ実行時の挙動の確認と同じ手順で、Argo CDダッシュボードから「App Details」ボタンを押し、「Parameters」タブの該当箇所を「v3」に変更し「Save」ボタンから保存します。ステータスが「OutOfSync」に変わるので、「Sync」ボタンから同期してステータスが「Suspended」に変わることを確認します。その後、エンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを何回か送付します。
curl -sS canary.dev.sample.io | jq
2割の確率で次のようなレスポンスが返却されます。
{ "message": "Hello World!!!", "version": "v3" }
・2. ロールバック実行
今回は新バージョン(v3)のカナリアテストで問題があったと仮定するので、迅速に旧バージョン(v2)にロールバックする必要があります。手順はとても簡単で、Argo CDダッシュボードで「Abort」を選択するだけです。
ステータスが「Degraded」に変わったら、無事にロールバック作業が完了しました。
・3. 最終状態の確認
トラフィックは全て新バージョン(v2)環境で処理されるようになったはずなので、リクエストを送付して確認します。
エンドユーザーに公開されているエンドポイント「canary.dev.sample.io」に対してリクエストを送信してみると、次のようなレスポンスが必ず返却されるように変化したことを確認できます。
{ "message": "Hello World!!!", "version": "v2" }
ロールバックの場合は、デプロイ実行時のように段階的にデプロイ状態を推移させるのではなく、迅速に環境が切り替わるかどうかを確認できたと思います。これによって、万が一カナリアテストまたはその後のデプロイ中であってもエンドユーザーへの影響を最小限にとどめることができます。
最後に参考までに、Argo Rolloutsにおけるカナリアリリースのパラメーターを紹介します。Argo Rolloutsにおけるカナリアリリースでは次の項目を設定できます。
spec: strategy: canary: stableService: string canaryService: string stableMetadata: object canaryMetadata: object dynamicStableScale: boolean maxSurge: stringOrInt maxUnavailable: stringOrInt minPodsPerReplicaSet: int32 scaleDownDelaySeconds: int32 scaleDownDelayRevisionLimit: int32 abortScaleDownDelaySeconds: int32 analysis: object steps: - setWeight: int32 - pause: object - setCanaryScale: object - setHeaderRoute: object - setMirrorRoute: object - analysis: object - experiment: object antiAffinity: object trafficRouting: object pingPong: object
公式HPに掲載されている項目に関しては参照リンクを添付し、掲載されていない項目に関してはGitソースコードから読み解いて解説します。
項目 (デフォルト値) |
解説 |
---|---|
stableService | 旧バージョンのReplicaSetのみにトラフィックを送信するServiceを設定する。これによって通常ユーザーのトラフィックが常に旧バージョンのReplicaSetに到達する |
canaryService | 新バージョンのReplicaSetのみにトラフィックを送信するServiceを設定する。これによってカナリアユーザーのトラフィックが常に新バージョンのReplicaSetに到達する |
stableMetadata | 新バージョンのPodが昇格後に付与されるメタデータ |
canaryMetadata | 新バージョンのPodがデプロイ作業中(昇格前)に付与されるメタデータ。昇格後にはこのメタデータは削除される |
dynamicStableScale (false) |
trafficRouting設定を利用した場合、デフォルトではデプロイ中は旧バージョンのReplicaSetを100%にスケールしたままにしておく。これには「デプロイ作業を中断する場合に、トラフィックを遅延なく直ちに旧バージョンのReplicaSetに戻すことができる」という利点がある。一方で、「デプロイ中は最大で2倍のPod数が稼働する」というデメリットもある(ブルーグリーンデプロイと同様)。 カナリアリリースにブルーグリーンデプロイの要素を足すことになるので、可用性という観点だけ見れば利点が多いように思えるが、一般的なカナリアリリースとは異なる挙動になるので、注意が必要 |
maxSurge (25%) |
最後のsetWeightで指定された割合に移行するためにRolloutが一度に作成できるPodの最大数を定義する。この設定項目は整数値またはパーセンテージを文字列で指定できる |
maxUnavailable (25%) |
デプロイ中に利用できなくなる可能性のあるPodの最大数を定義する。この設定項目は整数値またはパーセンテージを文字列で指定できる。MaxSurgeが0の場合、この設定項目値を0にできない |
minPodsPerReplicaSet (1) |
trafficRouting設定を利用した場合に利用できる設定項目。カナリア側のReplicaSetに要求されるPodの最小数。これによってカナリアリリース実行時の高可用性を確保できる |
scaleDownDelaySeconds (30) |
アクティブServiceが新バージョンのReplicaSetに切り替わった後、旧バージョンのReplicaSetのスケールダウンを指定時間分だけ遅らせる。 0に設定することで自動スケールダウンの抑止も可能 |
scaleDownDelayRevisionLimit | scaleDownDelaySecondsを0に設定した場合、旧バージョンの全てのReplicaSetが残り続けてしまうので、本設定によって保持するReplicaSetの世代数を制限できる |
abortScaleDownDelaySeconds (30) |
デプロイ作業を中断した後、新バージョンのReplicaSetのスケールダウンを指定時間分だけ遅らせる。 ロールバック実行後に、デプロイ予定であった新バージョン環境が自動的に削除されてしまうと、追加で解析できなくなる可能性があるので、適切な値にすることを推奨。 0に設定することで自動スケールダウンの抑止も可能 |
analysis | デプロイ時にバックグラウンドで実行する「分析」を定義する。初回デプロイ時にはスキップされる |
steps | デプロイにおけるReplicaSet制御やトラフィック制御、分析フェーズの追加などを自由にカスタマイズ可能にする項目。具体的な使用方法は本文の中で紹介している |
≪antiAffinity | Cluster構成によっては、デプロイ完了後旧バージョン環境が削除された際に、ノードがAutoScalerによって縮退し、縮退したノード上のPodが別のノードに移動されて再起動することがある。ワーカーノードのプールが十分に大きく、AntiAffinityを設定することで、この頻度を少なくできる |
trafficRouting | 新バージョン〜旧バージョン間のトラフィックの流れを制御するために適用するトラフィック管理ルール。設定しない場合は、デフォルトのPod数に比例したトラフィック比率のルーティングが使用される |
nil | Ingressコントローラーに応じた、より詳細なトラフィック管理ルールを定義できる。使っているIngressコントローラーが対応しているかどうかの確認が必要 |
pingPong | 「AWS LoadBalancer」をIPモードで利用している場合に、正しくデプロイできなかった問題に対処するために作られた項目。 詳細背景はこちらのリンクを参照 |
今回は、デプロイ確認としてArgo CDやArgo Rolloutsに標準で用意されているダッシュボード画面(GUI)にブラウザからアクセスしましたが、プロジェクトによってはブラウザでアクセスするのが手間となり、ターミナルからアクセスしたい場合もあると思います。
そのような場合は、Argo CDやArgo Rolloutsが公式にサポートしている「Kubectl」のプラグインを導入するといいでしょう。プラグインを導入することで、プロモートやロールバック実行やデプロイ状況確認をKubectlコマンドで確認できます。
インストール方法は次の通りです。
本ハンズオンで利用する場合、次のコマンドを実行します。
curl -LO https://github.com/argoproj/argo-cd/releases/download/v2.6.4/argocd-linux-amd64 sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd rm argocd-linux-amd64
本ハンズオンで利用する場合、次のコマンドを実行します。
curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.4.1/kubectl-argo-rollouts-linux-amd64 sudo install -m 555 kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts rm kubectl-argo-rollouts-linux-amd64
今回は、Argo Rolloutsを用いたブルーグリーンデプロイとカナリアリリースを紹介しました。Argo Rolloutsの要となるRolloutリソースとデプロイ、ロールバック操作について理解できたと思います。次回は、Argo Rolloutsの肝、プログレッシブデリバリーを実践します。
Copyright © ITmedia, Inc. All Rights Reserved.