このドキュメントでは、カナリア デプロイ戦略を構成および使用する方法について説明します。
カナリア デプロイとは
カナリア デプロイとは、すでにデプロイされているバージョンと新しいバージョンの間でトラフィックを分割するアプリケーションの段階的なロールアウトです。完全にロールアウトする前にユーザーのサブセットにロールアウトします。
サポート対象のターゲット タイプ
Cloud Deploy のカナリア デプロイは、次のようなすべてのターゲット タイプをサポートしています。
- Google Kubernetes Engine
- Cloud Run(サービスのみ。ジョブは対象外。)
- GKE Enterprise
Canary 環境は、マルチターゲットでも機能します。
カナリア デプロイ戦略を使用する理由
カナリア デプロイでは、アプリケーションを部分的にリリースできます。この方法により、アプリケーションの新しいバージョンをすべてのユーザーに配布する前に、そのバージョンの信頼性を確認できます。
たとえば、GKE または GKE Enterprise にデプロイする場合は、限られた数の Pod に新しいバージョンのアプリケーションをデプロイします。古いバージョンは引き続き実行されますが、より多くのトラフィックが新しい Pod に送信されます。
Cloud Run にデプロイする場合、Cloud Run 自体が、構成した割合に従って古いリビジョンと新しいリビジョンの間でトラフィックを分割します。
カナリアの種類
Cloud Deploy では、次の種類のカナリア デプロイを構成できます。
自動
自動カナリア デプロイでは、段階的なデプロイを表す一連の割合で Cloud Deploy を構成します。Cloud Deploy は、古いバージョンと新しいバージョンにトラフィックの割合を分配して、ユーザーに代わって追加のオペレーションを実行します。
カスタム自動
カスタム自動カナリアの場合、次の情報を指定できます。
- フェーズ名
- パーセンテージ目標
- このフェーズで使用する Skaffold プロファイル
- 確認ジョブを含めるかどうか
ただし、トラフィック負荷分散情報を提供する必要はありません。こちらで説明されているように、Cloud Deploy が必要なリソースを作成します。
カスタム
カスタム カナリアでは、以下のような各カナリア フェーズを個別に構成します。
- フェーズ名
- パーセンテージ目標
- このフェーズで使用する Skaffold プロファイル
- 確認ジョブを含めるかどうか
さらに、完全なカスタム カナリアの場合、こちらで説明されているように、すべてのトラフィック バランシング構成を指定します。
カナリア デプロイのフェーズ
カナリア デプロイのリリースを作成すると、カナリアの増分ごとのフェーズと、100% の最終 stable
フェーズのロールアウトが作成されます。
たとえば、カナリアを 25%、50%、75% の各増分で構成した場合、ロールアウトは次のフェーズになります。
canary-25
canary-50
canary-75
stable
ロールアウト フェーズ、ジョブ、ジョブ実行の詳細については、ロールアウトの管理をご覧ください。
自動カナリアまたはカスタム自動カナリアの動作
カナリア デプロイをサポートするために、Cloud Deploy には、Kubernetes マニフェストまたは Cloud Run サービス構成をレンダリングするときに特別な処理手順が含まれています。
ゲートウェイ GKE / Enterprise
Cloud Deploy がネットワーク ベースの GKE と GKE Enterprise でカナリア デプロイを実行する方法を次に示します。
Deployment リソース名と Service リソース名を指定します。
Cloud Deploy は、現在の Deployment の名前に
-canary
を追加した追加の Deployment リソースを作成します。Cloud Deploy は、現在の Deployment とカナリア Pod の Pod を選択するためにセレクタを調整する Service を変更します。
Cloud Deploy では、こちらで説明されている計算に基づいて、カナリアに使用する Pod の数を計算します。この計算は、Pod のオーバープロビジョニングが有効か無効かによって異なります。
stable
フェーズにスキップすると、Cloud Deploy は Pod の照合に使用するラベルを追加し、後続のカナリア実行で使用できるようにします。Cloud Deploy は、フェーズに固有の割合の Pod を含む Deployment を作成し、フェーズごとに更新します。これを行うには、Pod の数を元の Pod 数に対する割合として計算します。これにより、トラフィック分割が不正確になる可能性があります。正確なトラフィック分割が必要な場合は、Gateway API を使用します。
また、Secret と ConfigMap もコピーされ、
-canary
で名前が変更されます。stable
フェーズで、-canary
Deployment がゼロにスケールダウンされ、元の Deployment が新しい Deployment に置き換えられます。Cloud Deploy は、
stable
フェーズまで元の Deployment を変更しません。
Cloud Deploy は、リクエストされたカナリア率を可能な限り達成するように Pod をプロビジョニングします。これは、Pod へのトラフィックではなく、Pod の数に基づきます。トラフィックに基づいてカナリアを作成する場合は、Gateway API を使用する必要があります。
GKE ネットワーク ベースのカナリアでは、Pod のオーバープロビジョニングを有効または無効にできます。以下のセクションでは、各カナリア フェーズのカナリア デプロイにプロビジョニングする Pod の数を Cloud Deploy で計算する方法について説明します。
オーバープロビジョニングを有効にした Pod のプロビジョニング
オーバープロビジョニング(disablePodOverprovisioning: false
)を有効にすると、既存のデプロイを実行している Pod の数に基づいて、必要なカナリア率を実行するのに十分な追加の Pod を Cloud Deploy で作成できます。次の式は、Pod のオーバープロビジョニングが有効になっている場合に、各カナリア フェーズのカナリア デプロイにプロビジョニングする Pod の数を Cloud Deploy がどのように計算するかを示しています。
math.Ceil( percentage * ReplicaCountOfDeploymentOnCluster / (100-percentage))
この式では、現在のレプリカ数(このカナリアの前に存在する Pod の数)にフェーズのカナリア率を掛けて、その結果を(100 - カナリア率)で割ります。
たとえば、すでに Pod が 4 つあり、カナリア フェーズが 50% の場合、カナリア Pod の数は 4 になります。(100-percentage
の結果は .50
として扱われる割合 100-50=50
として使用されます。)
Pod のオーバープロビジョニングはデフォルトの動作です。
オーバープロビジョニングを無効にした Pod のプロビジョニング
オーバープロビジョニング(disablePodOverprovisioning: true
)を無効にして、Cloud Deploy によってレプリカ数が増加しないようにします。
次の式は、Pod のオーバープロビジョニングが無効になっている場合に、各カナリア フェーズのカナリア デプロイにおける Pod のプロビジョニングを Cloud Deploy がどのように計算するかを示しています。
math.Ceil( (ReplicaCountOfDeploymentOnCluster + ReplicaCountOfCanaryDeploymentOnCluster) * percentage)
この数式では、すでにカナリア フェーズが存在する場合にのみ ReplicaCountOfCanaryDeploymentOnCluster
が存在します。これが最初のカナリア フェーズの場合、ReplicaCountOfCanaryDeploymentOnCluster
は存在しません。
4 つの Pod で開始する場合は、その数値にカナリア率(たとえば、50%、.5
)を掛けて 2
を取得します。このため、元の Deployment は 2 にスケールダウンされ、カナリア デプロイ用に 2 つの新しい Pod が作成されます。カナリア ステージが 75% の場合、2
(元の Deployment)+2
(最初のカナリア ステージ)*.75
で 3
個のカナリア Pod と元の Deployment を実行する 1
個のPod を取得します。
ゲートウェイ GKE / Enterprise
Cloud Deploy が Gateway API を使用して GKE と GKE Enterprise でカナリア デプロイを実行する方法を次に示します。
Deployment と Service の参照に加えて、Service を参照する
backendRefs
ルールで HTTPRoute リソースを指定します。Cloud Deploy は、元の Deployment の名前に
-canary
を加えた新しい Deployment と、元の Service 名に-canary
を加えた新しい Service を作成します。また、Secret、ConfigMap、HorizontalPodAutoscaler もコピーされ、
-canary
で名前が変更されます。カナリア フェーズごとに、Cloud Deploy は HTTPRoute を変更し、元の Deployment の Pod とカナリア デプロイの Pod の間の重みを、そのフェーズの割合に基づいて更新します。
HTTPRoute
リソースへの変更の伝播には遅延が生じる可能性があるため、構成にrouteUpdateWaitTime
プロパティを含めることで、システムがこの伝播に要する一定の時間待機するようにできます。stable
フェーズでは、-canary
Deployment がゼロにスケールダウンされ、元の Deployment が新しいリリースの Deployment を使用するように更新されます。また、HTTPRoute は指定した元の状態に戻されます。
Cloud Deploy は、
stable
フェーズまで元の Deployment または Service を変更しません。
Cloud Run
Cloud Deploy が Cloud Run のカナリア デプロイを実行する方法を次に示します。
Cloud Run へのカナリア デプロイでは、サービス YAML で
traffic
スタンザを指定しないでください。カナリアの新しいロールアウトを作成すると、Cloud Deploy は、Cloud Deploy で正常にデプロイされた以前のリビジョンと新しいリビジョンとの間でトラフィックを分割します。
カナリア デプロイのフェーズ間の違いを確認する場合は、リリース インスペクタで使用可能なフェーズごとにレンダリングされたマニフェストの変更を表示できます。これは、ロールアウトの開始前でも行うことができます。また、並行デプロイを使用している場合は、レンダリングされた各子マニフェストを検査することもできます。
カナリア デプロイを構成する
このセクションでは、カナリア デプロイ用にデリバリー パイプラインとターゲットを構成する方法について説明します。
この手順には、カナリア構成に固有の内容のみが含まれます。アプリケーションのデプロイのドキュメントに、デプロイ パイプラインを構成して実行するための一般的な手順が記載されています。
必要な権限があることを確認してください
Cloud Deploy の使用に必要なその他の Identity and Access Management 権限に加えて、カナリア デプロイに必要な追加のアクションを実行するには、次の権限が必要です。
clouddeploy.rollouts.advance
clouddeploy.rollouts.ignoreJob
clouddeploy.rollouts.cancel
clouddeploy.rollouts.retryJob
clouddeploy.jobRuns.get
clouddeploy.jobRuns.list
clouddeploy.jobRuns.terminate
これらの権限を含む使用可能なロールの詳細については、IAM のロールと権限をご覧ください。
skaffold.yaml
を準備する
標準デプロイと同様に、カナリアには skaffold.yaml
ファイルが必要です。このファイルは、マニフェストとサービス定義をレンダリングしてデプロイする方法を定義します。
カナリア デプロイ用に作成する skaffold.yaml
には、標準デプロイに必要なもの以外の特別な要件はありません。
マニフェストまたはサービス定義を準備する
標準デプロイと同様に、カナリアには Kubernetes マニフェストまたは Cloud Run サービス定義が必要です。
GKE と GKE Enterprise
カナリアの場合、マニフェストには次のものが必要です。
Deployment と Service。
この Service では
app
セレクタを定義し、指定した Deployment の Pod を選択する必要があります。Gateway API ベースのカナリアを使用している場合は、マニフェストに HTTPRoute も必要です。
Cloud Run
Cloud Run のカナリアの場合、通常の Cloud Run サービス定義ファイルで十分ですが、traffic
スタンザはありません。Cloud Deploy では、最後に成功したリビジョンと新しいリビジョンの間のトラフィック分割を管理します。
自動カナリアを構成する
次の手順は、Cloud Run、GKE、GKE Enterprise のサービスベースのネットワーキング ターゲットを対象としています。GKE または GKE Enterprise で Kubernetes Gateway API を使用している場合は、このドキュメントをご覧ください。
デリバリー パイプラインの定義で自動カナリアを構成します。
GKE と GKE Enterprise
パイプライン ステージで、次のように strategy
プロパティを含めます。
serialPipeline:
stages:
- targetId: prod
profiles: []
strategy:
canary:
runtimeConfig:
kubernetes:
serviceNetworking:
service: "SERVICE_NAME"
deployment: "DEPLOYMENT_NAME"
canaryDeployment:
percentages: [PERCENTAGES]
verify: true|false
この設定は以下のようなものです...
SERVICE_NAME は、マニフェストで定義されている Kubernetes Service の名前です。
DEPLOYMENT_NAME は、マニフェストで定義されている Kubernetes Deployment の名前です。
PERCENTAGES は、カナリアの増分を表すパーセント値のカンマ区切りのリストです(例:
[5, 25, 50]
)。これには
100
は含まれません。デプロイの 100% が想定カナリアで、stable
フェーズで使用されているからです。デプロイ検証(
verify: true
)を有効にできます。有効にすると、各フェーズでverify
ジョブが有効になります。
Cloud Run
パイプライン ステージで、次のように strategy
プロパティを含めます。
serialPipeline:
stages:
- targetId: prod
profiles: []
strategy:
canary:
runtimeConfig:
cloudRun:
automaticTrafficControl: true
canaryDeployment:
percentages: [PERCENTAGES]
verify: true|false
この設定は以下のようなものです...
- PERCENTAGES は、カナリアの増分を表すパーセント値のカンマ区切りのリストです(例:
[25, 50, 75]
)。なお、これには100
は含まれません。デプロイの 100% が想定カナリアで、stable
フェーズで使用されるためです。 - デプロイ検証(
verify: true
)を有効にできます。有効にすると、各カナリア フェーズにverify
ジョブが追加されます。
カスタム カナリアを構成する
Cloud Deploy が提供する自動化に完全に依存する代わりに、カナリアを手動で構成することもできます。カスタム カナリア構成では、デリバリー パイプラインの定義で次の項目を指定します。
ロールアウト フェーズ名
完全に自動化されたカナリアでは、Cloud Deploy がフェーズに名前を付けます(
canary-25
、canary-75
、stable
など)。ただし、カスタム カナリアでは、このカナリア ステージのすべてのフェーズで一意であり、リソース名の制限を満たす限り、各フェーズに任意の名前を付けることができます。ただし、最終(100%)フェーズ名はstable
にする必要があります。各フェーズの割合の目標
フェーズごとに割合を個別に指定します。
このフェーズで使用する Skaffold プロファイル
フェーズごとに個別の Skaffold プロファイル、または同じプロファイル、または任意の組み合わせを使用できます。プロファイルは、それぞれ異なる Kubernetes マニフェストや Cloud Run サービス定義を使用できます。特定のフェーズに複数のプロファイルを使用することもできます。Cloud Deploy では、これらを組み合わせています。
そのフェーズの確認ジョブがあるかどうか
確認を有効にする場合は、確認用に
skaffold.yaml
も構成する必要があるので注意してください。
カスタム カナリアでは、すべてのターゲット タイプがサポートされます。
カスタム カナリアの構成要素
次の YAML は、完全なカスタム カナリア デプロイのフェーズの構成を示しています。
strategy:
canary:
# Custom configuration for each canary phase
customCanaryDeployment:
phaseConfigs:
- phaseId: "PHASE1_NAME"
percentage: PERCENTAGE1
profiles: [ "PROFILE_NAME" ]
verify: true | false
- …
- phaseId: "stable"
percentage: 100
profiles: [ "LAST_PROFILE_NAME" ]
verify: true|false
この YAML の内容は以下のとおりです。
PHASE1_NAME
フェーズの名前。各フェーズ名は一意である必要があります。
[ "PROFILE_NAME" ]
このフェーズで使用するプロファイルの名前です。フェーズごとに同じプロファイル、フェーズごとに異なるプロファイル、または任意の組み合わせで使用することもできます。また、複数のプロファイルを指定することもできます。Cloud Deploy では、指定したすべてのプロファイルと、ステージ全体で使用されるプロファイルまたはマニフェストを使用します。
PERCENTAGE1
最初のフェーズでデプロイする割合です。各フェーズは一意の割合値を持つ必要があり、その値は全体の割合である必要があります(たとえば、
10.5
ではありません)。フェーズは昇順である必要があります。verify: true|false
このフェーズの確認ジョブを含めるかどうかを Cloud Deploy に指示します。確認を使用する各フェーズで、Skaffold は、そのフェーズのレンダリングとデプロイに指定された確認と同じプロファイルを使用します。
stable
最終フェーズは
stable
という名前にする必要があります。
最終フェーズの割合は 100
にする必要があります。フェーズは、この customCanaryDeployment
スタンザで構成した順序に従って実行されますが、割合の値が昇順でない場合は、デリバリー パイプラインを登録するコマンドはエラーで失敗します。
なお、カスタム カナリアの構成には runtimeConfig
スタンザが含まれていないことに注意してください。runtimeConfig
を含めると、カスタム自動カナリアとみなされます。
カスタム自動カナリアを構成する
カスタム自動カナリアはカスタム カナリアに類似しています。カスタム フェーズ名、割合値、Skaffold プロファイルで個別のカナリア フェーズを指定し、ジョブを検証するためです。しかし、カスタム カナリアでは、トラフィック割り当てを定義する構成を指定しません。これは Cloud Deploy により自動的に行われます。ただし、各ステージで使用される Skaffold プロファイルを指定します。
カスタム自動カナリアを構成するには、ここに示すように runtimeConfig
スタンザを含め、ここに示すように customCanaryDeployment
スタンザを含めます。
Kubernetes Gateway API サービス メッシュを使用してカナリア デプロイを構成する
Cloud Deploy のカナリア デプロイを使用して、アプリケーションを Kubernetes サービスベースのネットワーキングにデプロイすることができますが、代替は、Kubernetes の Gateway API サービス メッシュを使用することです。 このセクションでは、その方法について説明します。
Gateway API は、Istio またはサポートされている実装で使用できます。
Gateway API リソースを設定します。
これらは一例にすぎません。
リリースの作成時に Cloud Deploy に指定した Kubernetes マニフェストに、次の内容を含めます。
Gateway リソースを参照する
HTTPRoute
A. Deployment
サービス
デリバリー パイプラインとカナリア デプロイ先のターゲットを構成します。
ターゲットの構成は、他のターゲットと同じです。
特定のターゲットの進行シーケンスにあるデリバリー パイプライン構成には、Kubernetes Gateway API の
HTTPRoute
構成、Deployment および Service を参照するgatewayServiceMesh
スタンザが含まれています。strategy: canary: runtimeConfig: kubernetes: gatewayServiceMesh: httpRoute: "ROUTE" service: "SERVICE" deployment: "DEPLOYMENT" routeUpdateWaitTime: "WAIT_TIME" canaryDeployment: percentages: - 50
ここで...
ROUTE は、必要なルーティング動作を定義する httpRoute 構成です。
SERVICE は、Cloud Deploy が GKE と GKE Enterprise へのカナリア デプロイに必要とする Service の構成です。
DEPLOYMENT は、Cloud Deploy が GKE と GKE Enterprise へのカナリア デプロイに必要とする Deployment の構成です。
WAIT_TIME は、リクエストのドロップを回避するために
HTTPRoute
リソースへの変更の伝播が完了するまで Cloud Deploy が待機する時間です。例:routeUpdateWaitTime: 60s
。Istio を使用せずに Gateway API を使用してカナリアを実行し、Gateway API が Google Cloud ロードバランサに接続されている場合は、カナリア インスタンスをスケールダウンすると、少量のトラフィックが失われる可能性があります。この動作が見られた場合は、この設定を構成できます。
カナリア デプロイ戦略で並列デプロイを使用する
並行デプロイを使用してカナリア デプロイを実行できます。つまり、段階的にデプロイするターゲットは、2 つ以上の子ターゲットを含むことができます。たとえば、同時に、別々のリージョンのクラスタに段階的にデプロイできます。
並列カナリアと単一ターゲット カナリアの違い
単一ターゲットのカナリア デプロイと同様に、GKE ターゲットにデプロイする場合は、マニフェストに Kubernetes Deployment 構成と Kubernetes Service 構成が必要です。
単一ターゲットのカナリア デプロイと同様に、デリバリー パイプラインの構成には、該当するステージのステージ定義内に
strategy.canary
スタンザが含まれている必要があります。また、マルチターゲットを構成し、そのマルチターゲット参照を子ターゲットに構成する必要があります。
リリースを作成すると、コントローラのロールアウトと子ロールアウトが作成されます。
両方のタイプのロールアウト(コントローラと子)には、構成されているカナリア率ごとに個別のフェーズ
stable
とカナリア 100% のフェーズがあります。子ロールアウトを進めることはできません。
コントローラのロールアウトのみを進められます。コントローラのロールアウトを次のステージに進めると、子のロールアウトも Cloud Deploy によって次に進められます。
コントローラのロールアウトで、失敗したジョブを再試行することはできません。
ジョブは子ロールアウトでのみ再試行できます。
コントローラのロールアウトで失敗したジョブを無視することはできません。
子ロールアウトでのみ、失敗したジョブを無視できます。
コントローラのロールアウトをキャンセルすることはできますが、子ロールアウトをキャンセルすることはできません。
コントローラのロールアウトではなく、子ロールアウトでのみジョブ実行を終了できます。
カナリアで並列ロールアウトが失敗した場合の対応
子ロールアウトが失敗すると、子ロールアウトの状況に応じて、コントローラのロールアウトが異なる状態に遷移します。
1 つ以上の子ロールアウトが失敗しても、少なくとも 1 つの子ロールアウトがまだ
IN_PROGRESS
の場合、コントローラのロールアウトはIN_PROGRESS
のままです。1 つ以上の子ロールアウトが失敗し、少なくとも 1 つの子ロールアウトが成功した場合、現在のフェーズよりも後のフェーズがある場合、コントローラのロールアウトは
HALTED
になります。これが
stable
フェーズの場合、コントローラのロールアウトはFAILED
です。HALTED
を使用すると、失敗した子ロールアウト内で失敗したジョブを無視、再試行、または コントローラのロールアウトをキャンセルし、子ロールアウトに対してそれ以上の操作を禁止します。子ロールアウトの失敗によりコントローラのロールアウトが
HALTED
状態になっている場合、子ロールアウトで失敗したジョブを無視すると、コントローラのロールアウトはIN_PROGRESS
状態に戻ります。
構成されたカナリアを実行する
カナリア デプロイを実行するには:
構成されたデリバリー パイプラインとターゲットを登録します。
gcloud deploy apply --file=PIPELINE
デリバリー パイプラインには、選択したランタイムの自動カナリア構成またはカスタム カナリア構成が含まれます。
このコマンドは、ターゲットが同じファイルで定義されているか、すでに登録されていることを前提としています。登録されていない場合は、ターゲットも必ず登録してください。
リリースを作成する:
gcloud deploy releases create RELEASE_NAME \ --delivery-pipeline=PIPELINE_NAME \ --region=REGION
PIPELINE_NAME
によって識別されるデリバリー パイプラインには、このドキュメントで説明する自動カナリア構成またはカスタム カナリア構成が含まれています。カナリアを進める:
gcloud CLI
gcloud deploy rollouts advance ROLLOUT_NAME \ --release=RELEASE_NAME \ --delivery-pipeline=PIPELINE_NAME \ --region=REGION
ここで
ROLLOUT_NAME
は、次のフェーズに進む現在のロールアウトの名前です。RELEASE_NAME
は、このロールアウトが属するリリースの名前です。PIPELINE_NAME
は、このリリースのデプロイを管理するために使用するデリバリー パイプラインの名前です。REGION
は、リリースが作成されたリージョンの名前です(例:us-central1
)。必須入力項目です。gcloud deploy rollouts advance
コマンドの詳細については、Google Cloud SDK リファレンスをご覧ください。Google Cloud コンソール
デリバリー パイプラインのリストに表示されているパイプラインをクリックします。
デリバリー パイプラインの詳細ページには、デリバリー パイプラインの進行状況がグラフィカルに表示されます。
[ロールアウト] タブの [デリバリー パイプラインの詳細] で、ロールアウトの名前をクリックします。
そのロールアウトのロールアウト詳細ページが表示されます。
この例では、ロールアウトに
canary-50
フェーズとstable
フェーズがあることに注目してください。ロールアウトには、複数のフェーズや、さまざまなフェーズが存在する場合があります。[ロールアウトを進める] をクリックします。
ロールアウトを次のフェーズに進めます。
スキップされるフェーズ
カナリアをデプロイするときに、アプリケーションがそのランタイムにデプロイされていない場合、Cloud Deploy はカナリア フェーズをスキップして安定フェーズを実行します。これが発生する理由を確認するには、フェーズを初めてスキップするをご覧ください。
次のステップ
カナリアのロールアウトのライフサイクルを管理する方法を確認する。
並行デプロイの詳細を確認する。