このドキュメントでは、カナリア デプロイ戦略を構成して使用する方法について説明します。
カナリア デプロイとは
カナリア デプロイとは、すでにデプロイされているバージョンと新しいバージョンの間でトラフィックを分割し、ユーザーのサブセットに展開して完全にロールアウトするアプリケーションの段階的なロールアウトです。
サポートされているターゲット タイプ
Cloud Deploy のカナリア デプロイでは、次のようなすべてのターゲット タイプがサポートされます。
- Google Kubernetes Engine
- Cloud Run(サービスのみ。ジョブは対象外。)
- GKE Enterprise
Canary 環境は、マルチターゲットでも機能します。
カナリア デプロイ戦略を使用する理由
カナリア デプロイでは、アプリケーションを部分的にリリースできます。これにより、すべてのユーザーにアプリケーションを提供する前に、アプリケーションの信頼性を確保できます。
たとえば、GKE または GKE Enterprise にデプロイする場合、新しいバージョンのアプリケーションを限られた数の Pod にデプロイします。古いバージョンは引き続き実行されますが、より多くのトラフィックが新しい Pod に送信されます。
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/GKE Enterprise(ネットワーク)
ネットワーク ベース GKE と GKE Enterprise で Cloud Deploy がカナリア デプロイを実行する方法を次に示します。
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 のオーバープロビジョニングを有効または無効にすることができます。以降のセクションでは、Cloud Deploy でカナリア フェーズごとにカナリア デプロイにプロビジョニングされる Pod の数を計算する方法について説明します。
オーバープロビジョニングを有効にした 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/GKE Enterprise(ゲートウェイ)
Gateway API を使用して GKE と GKE Enterprise でカナリア デプロイを実行する方法を以下に示します。
Deployment と Service のリファレンスに加えて、Service を参照する
backendRefs
ルールを含む HTTPRoute リソースを指定します。Cloud Deploy は、元の Deployment の名前と
-canary
に加えて、元の 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
構成を参照するgatewayServiceMesh
スタンザ、Deployment、Service が含まれます。strategy: canary: runtimeConfig: kubernetes: gatewayServiceMesh: httpRoute: "ROUTE" service: "SERVICE" deployment: "DEPLOYMENT" routeUpdateWaitTime: "WAIT_TIME" canaryDeployment: percentages: - 50
ここで...
ROUTE は、必要なルーティング動作を定義する httpRoute 構成です。
SERVICE は、GKE と GKE Enterprise へのカナリア デプロイに必要な Cloud Deploy です。
DEPLOYMENT は、GKE と GKE Enterprise へのカナリア デプロイに必要な Cloud Deploy 構成です。
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
フェーズがあります。ロールアウトには、より多くのフェーズやフェーズがある場合があります。[Advance rollout] をクリックします。
ロールアウトが次のフェーズに進みます。
スキップしたフェーズ
カナリアをデプロイするときに、アプリケーションがそのランタイムにデプロイされていない場合、Cloud Deploy はカナリア フェーズをスキップして安定フェーズを実行します。理由については、最初のフェーズのスキップをご覧ください。
次のステップ
カナリア ロールアウトのライフサイクルを管理する方法を確認する。
並列デプロイの詳細を確認する。