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

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

カナリア デプロイとは

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

サポートされているターゲット タイプ

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

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

  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 のオーバープロビジョニングを有効または無効にすることができます。以降のセクションでは、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(最初のカナリア ステージ)*.753 個のカナリア Pod と元の Deployment を実行する 1 個のPod を取得します。

GKE/GKE Enterprise(ゲートウェイ)

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

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

  2. Cloud Deploy は、元の Deployment の名前と -canary に加えて、元の 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 構成を参照する 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 状態に戻ります。

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

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

  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. [Advance rollout] をクリックします。

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

スキップしたフェーズ

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

次のステップ