カナリア デプロイ戦略を使用する

このドキュメントでは、カナリア デプロイ戦略を構成および使用する方法について説明します。

カナリア デプロイとは

カナリア デプロイとは、すでにデプロイされているバージョンと新しいバージョンの間でトラフィックを分割するアプリケーションの段階的なロールアウトです。完全にロールアウトする前にユーザーのサブセットにロールアウトします。

サポート対象のターゲット タイプ

Cloud Deploy のカナリア デプロイは、次のようなすべてのターゲット タイプをサポートしています。

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 でカナリア デプロイを実行する方法を次に示します。

  1. Deployment リソース名と Service リソース名を指定します。

  2. Cloud Deploy は、現在の Deployment の名前に -canary を追加した追加の Deployment リソースを作成します。

  3. 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 で名前が変更されます。

  4. 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(最初のカナリア ステージ)*.753 個のカナリア Pod と元の Deployment を実行する 1 個のPod を取得します。

ゲートウェイ GKE / Enterprise

Cloud Deploy が Gateway API を使用して GKE と GKE Enterprise でカナリア デプロイを実行する方法を次に示します。

  1. Deployment と Service の参照に加えて、Service を参照する backendRefs ルールで HTTPRoute リソースを指定します。

  2. Cloud Deploy は、元の Deployment の名前に -canary を加えた新しい Deployment と、元の Service 名に -canary を加えた新しい Service を作成します。

    また、Secret、ConfigMap、HorizontalPodAutoscaler もコピーされ、-canary で名前が変更されます。

  3. カナリア フェーズごとに、Cloud Deploy は HTTPRoute を変更し、元の Deployment の Pod とカナリア デプロイの Pod の間の重みを、そのフェーズの割合に基づいて更新します。

    HTTPRoute リソースへの変更の伝播には遅延が生じる可能性があるため、構成に routeUpdateWaitTime プロパティを含めることで、システムがこの伝播に要する一定の時間待機するようにできます。

  4. 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

カナリアの場合、マニフェストには次のものが必要です。

  • DeploymentService。

  • この 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-25canary-75stable など)。ただし、カスタム カナリアでは、このカナリア ステージのすべてのフェーズで一意であり、リソース名の制限を満たす限り、各フェーズに任意の名前を付けることができます。ただし、最終(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 またはサポートされている実装で使用できます。

  1. Gateway API リソースを設定します。

    これらは一例にすぎません。

  2. リリースの作成時に Cloud Deploy に指定した Kubernetes マニフェストに、次の内容を含めます。

    • Gateway リソースを参照する HTTPRoute

    • A. Deployment

    • サービス

  3. デリバリー パイプラインとカナリア デプロイ先のターゲットを構成します。

    • ターゲットの構成は、他のターゲットと同じです。

    • 特定のターゲットの進行シーケンスにあるデリバリー パイプライン構成には、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 状態に戻ります。

構成されたカナリアを実行する

カナリア デプロイを実行するには:

  1. 構成されたデリバリー パイプラインとターゲットを登録します。

    gcloud deploy apply --file=PIPELINE
    

    デリバリー パイプラインには、選択したランタイムの自動カナリア構成またはカスタム カナリア構成が含まれます。

    このコマンドは、ターゲットが同じファイルで定義されているか、すでに登録されていることを前提としています。登録されていない場合は、ターゲットも必ず登録してください。

  2. リリースを作成する:

    gcloud deploy releases create RELEASE_NAME \
                                  --delivery-pipeline=PIPELINE_NAME \
                                  --region=REGION
    

    PIPELINE_NAME によって識別されるデリバリー パイプラインには、このドキュメントで説明する自動カナリア構成またはカスタム カナリア構成が含まれています。

  3. カナリアを進める:

    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 コンソール

    1. [デリバリー パイプライン] ページを開く

    2. デリバリー パイプラインのリストに表示されているパイプラインをクリックします。

      デリバリー パイプラインの詳細ページには、デリバリー パイプラインの進行状況がグラフィカルに表示されます。

    3. [ロールアウト] タブの [デリバリー パイプラインの詳細] で、ロールアウトの名前をクリックします。

      そのロールアウトのロールアウト詳細ページが表示されます。

      Google Cloud コンソールでのロールアウトの詳細

      この例では、ロールアウトに canary-50 フェーズと stable フェーズがあることに注目してください。ロールアウトには、複数のフェーズや、さまざまなフェーズが存在する場合があります。

    4. [ロールアウトを進める] をクリックします。

      ロールアウトを次のフェーズに進めます。

スキップされるフェーズ

カナリアをデプロイするときに、アプリケーションがそのランタイムにデプロイされていない場合、Cloud Deploy はカナリア フェーズをスキップして安定フェーズを実行します。これが発生する理由を確認するには、フェーズを初めてスキップするをご覧ください。

次のステップ