Kubernetes Gateway API、Flagger、Google Cloud Deploy を使用したカナリア デプロイ
Google Cloud Japan Team
Cloud Deploy と新しい Gateway API を使用してアプリケーションのリリースを加速
※この投稿は米国時間 2023 年 1 月 20 日に、Google Cloud blog に投稿されたものの抄訳です。
カナリア デプロイとは、ユーザーベース全体に変更をロールアウトする前にごく一部のユーザーに段階的にロールアウトして、本番環境で変更をテストするために使用する高度な手法です。この手法を使用すれば、実環境で変更をテストして、なんらかの問題が見つかった場合にすばやくロールバックできます。カナリア デプロイが特に役立つのは、新機能の追加やデータベース スキーマの更新といったアプリケーションの重要な部分に対する変更をテストする場合です。カナリア デプロイを使用することで、確実に、ユーザーベース全体に影響を及ぼす問題を未然に修正し、新しい変更がユーザー エクスペリエンスに悪影響を与えないようにできます。
新しい Kubernetes Gateway API は、Google Kubernetes Engine クラスタ上で実行中のアプリケーションへのトラフィックを管理するうえで役立つ新たなツールです。この新しい管理機能を Google Cloud Deploy と併せて活用すれば、本番環境へのアプリケーションのリリースを加速できます。この投稿で説明する手順で作成する継続的デプロイ パイプラインでは、反復型のトラフィック移行パターンを使用してアプリケーションを本番環境にリリースするため、ダウンタイムなしで迅速にアプリケーションをデプロイできます。
Flagger という OSS ツールを使用すると、K8s クラスタを使ったカナリア リリースや A/B テストを宣言型で実施できます。このツールは、リリースの正常性を判断するための構成可能なアプリケーション指標をモニタリングし、それらの指標に基づいてリリース プロセスを制御します。このツールがサポートしている指標のソースは、Prometheus や Google Cloud Monitoring をはじめ多岐にわたります。この投稿で指標のソースとして使用するのは Google Managed Prometheus です。
Flagger は多くの場合、Istio や Anthos Service Mesh などのサービス メッシュで使用されますが、最近、トラフィック管理用の新しい Kubernetes Gateway API にも対応するようになりました。このブログ投稿ではこれを使用します。最新バージョン v1beta1 に対応するよう Flagger での Gateway API の実装を更新したので、このブログ投稿でまとめてご説明します。
設計の概要
以下のアーキテクチャ図は、このブログ投稿で説明する例でのコンポーネントの相互接続を示しています。
この例での Google Cloud の設定に必要なリソースについて説明します。まず、コンテナ イメージの保存場所として Artifact Registry を使用します。トラフィックをアプリケーションにルーティングするための Cloud Load Balancing も必要です。また、アプリケーションをさまざまな環境にデプロイするマネージド型の継続的デリバリー パイプラインを構築するために、Cloud Deploy を使用します。さらに、カナリア戦略をデータドリブンなものにするために、Google Managed Prometheus を使用してアプリケーションのオブザーバビリティを確保します。
GKE クラスタには 2 つの Namespace を設定します。一方は、開発環境用の dev という Namespace です。ここには、Cloud Deploy から直接アプリケーションがデプロイされます。もう一方は、Flagger を使用した段階的なトラフィック移行による K8s デプロイが行われる、prod という Namespace です。prod Namespace には Google Managed Prometheus(GMP)クエリ インターフェースもデプロイします。
内部 Cloud ロードバランサを使用することから、実際にアプリケーションにアクセスするには、Compute Engine 上にジャンプホスト VM が必要になります。
環境の設定
まずは、環境を設定しましょう。この投稿の手順に沿うには、ご使用のマシンに kubectl、gcloud、jq、skaffold がインストールされている必要があります。あるいは、これらすべてがインストールされている Cloud Shell を使用することもできます。いくつかの変数も設定します。これらの変数を設定しておくと、次のステップで役立ちます。
あらかじめ、いくつかの API を有効にしておく必要もあります。
Artifact Registry を設定して、環境を構成するために、次のコマンドを実行します。
VPC 内にはロードバランサ向けプロキシ専用サブネットが存在している必要があります。まだ存在していなければ、次のコマンドを使用して作成してください。この例での IP 範囲が使用中の場合は、ネットワーク内の未使用の範囲に変更する必要があります。この例ではデフォルト VPC を使用していますが、必要に応じて任意の VPC を使用できます。
Gateway API、水平 Pod 自動スケーリング、および Workload Identity が有効にされた GKE クラスタが必要です。また、バージョン 1.24 以降の GKE を使用する必要もあります。次のコマンドで、この条件を満たすクラスタを作成しましょう。
クラスタの作成が完了したら、そのクラスタにローカルマシンを接続します。
最後に、サンプルアプリが必要です。Golang で小規模なサンプルアプリを作成しておいたので、それをチェックアウトして使用できます。
これで、すべての準備が整いました。
クラスタに Google Managed Prometheus(GMP)クエリ インターフェースをデプロイする
Flagger はテレメトリー データを使用してデプロイのステータスを把握します。このデモのためにデプロイしたサンプル Golang アプリケーションからは、Prometheus 指標が渡されるようになっています。すでにクラスタでマネージド モードでの収集を有効にしてあるので、アプリからの指標は Cloud Monitoring で使用可能になっているはずです。このデモでは、Flagger がデプロイの正常性をチェックできるようにするために、クラスタ内部の GMP クエリ インターフェースを使用します。Flagger は Google Cloud Operations に対して直接クエリを実行することもできますが、PromQL を使って成功率を計算するほうが簡単だからです。
Kubernetes クラスタに Flagger をインストールする
カナリア デプロイに取り掛かるには、クラスタに Gateway API を有効にした Flagger をインストールする必要があります。それには、次のコマンドを実行するだけです。
このコマンドにより、Flagger コンポーネントと CRD が flagger-system 名前空間にインストールされます。
環境をブートストラップする
続いて、次の要素を使用して環境をブートストラップします。
開発環境と本番環境の K8s ゲートウェイ(内部 L7 LB を使用)
成功率のクエリに使用する指標テンプレート(後ほど確認します)
Flagger 用のカナリア リリース オブジェクト(これも後ほど説明します)
DNS 設定に使用するゲートウェイ IP アドレスをフェッチする必要があります(表示されるまでに数分かかる場合があります)。
この時点で、Skaffold から直接デプロイしてみることもできます。
これで、同じ VPC 内にある VM からサービスを呼び出せるようになりました。
「Hello World!」というレスポンスが表示されるはずです。状態を調整し、バックエンドが正常になるまで数秒かかる場合があります。
Cloud Deploy パイプラインを作成する
まず、Cloud Deploy の権限を設定して、パイプラインを適用します。この例では複雑さを軽減するために、デフォルトのコンピューティング サービス アカウントを使ったシンプルな IAM 構成を使用します。本番環境で使用するようにこの設定をする際は、カスタム サービス アカウントを使用してセキュリティを強化してください。
次に、Cloud Deploy で本番環境にデプロイする新しいリリースを作成します。
続いて、作成したリリースを本番環境にプロモートします。このステップも、完了するまでに時間がかかる場合があります。
本番環境のゲートウェイの IP をフェッチしましょう。
クラスタ VPC 内にある VM から本番環境のゲートウェイに対して curl コマンドを実行します。
デプロイが完了すると、再び「Hello World!」と表示されるはずです。本番環境バージョンのデプロイはまだ実行されていないため、カナリア ステップは「スキップ」されています。
カナリア デプロイ
次は、カナリア処理機能を試しましょう。そのために、「app/main.go」ファイルに小さな変更を加えます。たとえば、27 行目の出力文字列に自分の名前を追加します。この新しいバージョンを、開発環境にデプロイするステップをスキップして(実際の本番環境のシナリオでは、当然スキップすべきではありません)本番環境に直接デプロイします。
カナリア プロセスを確認するには、次のコマンドを使用します。
本番環境のゲートウェイに対して再度 curl コマンドを実行すると、さまざまなメッセージが表示されるはずです。これらのメッセージに、新しいバージョンのリリースがどこまで進んでいるのかを表す比率が示されます。
GCLB の URL マップでトラフィック分割を直接確認することもできます。
次のような結果が表示されます。
このアプリケーションには失敗するエンドポイントも含まれているため、500 - Internal Server Error
というレスポンスが返されます。別の小さな変更を app/main.go
に加えて新しいデプロイをトリガーし、リクエストの成功率が低いと、Flagger は新しいバージョンのロールアウトを停止することを確認してください。
仕組み
bootstrap.yaml
内に、アプリの成功率を調べるための単純な PromQL クエリを定義しました。200 ステータス コードが返されない場合、リクエストは失敗したと見なされます。Flagger カナリア オブジェクトには、成功率の目標を 60% として定義しています。
この成功率のクエリが参照される、Flagger カナリア オブジェクトも定義しました。このカナリア オブジェクトは新しいアプリのデプロイをモニタリングし、新しいバージョンに一度にすべてのトラフィックを移行するのではなく段階的に移行するために、ルーティング構成をインターセプトします。
以上で完了です。新しい Gateway API と Google Cloud Deploy を使用してカナリア デプロイに対処する、軽量の継続的デプロイ パイプラインが Google Cloud で稼働中になりました。
次のステップ
Google Cloud 上での CI / CD について詳しく学ぶには、以下の記事をおすすめします。
Google Cloud 組み込みサービスを使用した安全な CI / CD パイプラインの構築: Google Cloud 上でエンドツーエンドの CI / CD を実施する手順をわかりやすく説明しています。
ソフトウェア サプライ チェーンのエンドツーエンドのセキュリティを提供するソフトウェア デリバリー シールドのご紹介: Google がソフトウェア デリバリーを保護する仕組みを紹介しています。
GKE Gateway Controller による Kubernetes ネットワーキングの進化: GKE Gateway API とその機能の概要を把握できます。
- 戦略的クラウド エンジニア Christoph Grotz