k8sからマルチコンテナ構成のCloudRunに移行できるか検証してみた

こんにちは、henzaiです。今回はSREのyoshizawaがCloudRunのマルチコンテナ構成について検証を進めてくれたネタがあったので、それを紹介したいと思います。

検証のモチベーション

弊社ではアプリケーションの実行プラットフォームとして主にGoogle Kubernetes Engine(GKE)とCloud Runを使用しています。1 主にGKEには常にリクエストを受け待つようなサーバー類をデプロイし、Cloud Runにはイベント駆動系の処理をデプロイしています。

最近ではよくある構成かなと思うのですが、一方で弊社の組織規模においてk8sの運用を続けていくのはコストが掛かりすぎるという課題感もあり、Cloud Runへの全面移行も選択肢の1つだよねというのが現状の認識です。

そこで、k8sからCloud Runに移行を進めるうえでマルチコンテナ構成によって何が可能になるか、何が課題になるかを知りたいというのが今回の検証のモチベーションになります。

実は検証はプレビュー時代におこなっていたのですが、現在はGAになっています。 GAになるにあたって、コマンド類が使いやすくなっていたのでその点についても触れようと思います。

検証環境

今回は弊社のGKE上にデプロイされている社内サービス(frontend)をマルチコンテナ構成のCloud Runに移行できるかを検証します。 frontendはGoのhtml/template パッケージを用いて実装されたフロントエンドです。 バックエンドにはGKE上にgRPCサーバーの別サービスがあるものとします。

frontendはユーザーの所属する部署ごとに実行できる操作を制限しています。この制限を実現するために、IAPを利用したアクセスコントロール用のプロキシ(proxy)をfrontendと同じpodにデプロイしています。

現状のfrontendの構成

frontendとproxyを1つのCloud Runにデプロイし、k8sのバックエンドと疎通できれば移行できるぞ、ということになりそうです。

Cloud Runのマルチコンテナ構成の基本

GCPのガイドの中では「Deploying multiple containers to a service (sidecars)」2と記されているように、サイドカーパターンの構成をCloudRunで実現出来るというものになります。

具体的には、1つのingressコンテナと1つ以上のサイドカーコンテナをCloud Runインスタンス内へ立ち上げられるようになります。ingressコンテナは外からのリクエストを受け付け、ingressコンテナとサイドカーコンテナはポートを介して通信します。

今回の機能追加によって、これまでk8sのpod内で複数のコンテナを立ち上げているような構成をCloud Runにそのまま持ってくるということが可能になってきました。 検証ではproxyをingressコンテナとし、frontendをサイドカーコンテナとしてデプロイします。proxyからfrontendへは9000番ポートで通信します。

さて、Cloud Runでマルチコンテナ構成をデプロイするには serving.knative.dev/v1 の形式のYAMLファイルを用意し、gcloud run services replace する必要がプレビュー時ではありましたが、GAになってからは gcloud beta run deploy でデプロイできるようになりました!

これまで gcloud run services replace FILE 以外の方法でマルチコンテナ構成のCloud Runをデプロイできなかったためデプロイフローがやや複雑になってしまう問題がありましたが、これが解消されたのは嬉しいですね。

具体的には以下のように書くことができます。

gcloud beta run deploy service_name \
 --container proxy --image=proxy --port=8080 \
 --container frontend --image=frontend

1回目に出てくるimageオプションがingressコンテナのイメージ名で、2回目以降のimageオプションがsidecarコンテナの名前を示すようです。

弊社ではプルリクエストのマージをトリガーにしてCloud Build上で gcloud run deploy SERVICE するようなデプロイフローにしているため、そのまま流用できそうです。これは嬉しい。

コンテナの起動順序とヘルスチェック

サイドカーパターンをCloud Runで構成する場合、サイドカーのコンテナが起動したのを確認してからingressコンテナを起動したい場合が多いと思います。

以下のようなコマンドでproxyが起動した後にfrontendを起動できます。3

gcloud beta run deploy service_name \
 --container proxy --image=proxy --port=8080 \
 --container frontend --image=frontend --depends-on=proxy

起動プローブはデフォルトでTCP起動プローブが設定されます。 既存のCloud Runと同様HTTP起動プローブへと変更することも可能なようです。 HTTP起動プローブを構成するには依然として gcloud run services replace FILE によるyamlファイル書き換えが必要なようです。

spec:
  containers:
  - image: proxy
    ports:
      - containerPort: 8080
    startupProbe:
      failureThreshold: 3
      httpGet:
        path: /healthcheck
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 30
      timeoutSeconds: 10
  - image: frontend
    startupProbe:
      failureThreshold: 3
      httpGet:
        path: /healthcheck
        port: 9000 # サイドカーコンテナへの通信ポートが異なる場合に指定必要
      initialDelaySeconds: 10
      periodSeconds: 30
      timeoutSeconds: 10

ここまでCloud Runのマルチコンテナ構成をデプロイする方法、そして起動順序と起動プローブの設定方法について確認できました。次はネットワークについて見ていきましょう。

内向き、外向きのネットワーク

今回は検証時点でプレビューの “Direct VPC egress with a VPC network” という機能を使ってみました。4 これは、VPCアクセスコネクタを使わずにCloud RunからVPCネットワーク内にトラフィックを送信できるようになるようです。 検証ではyamlの直接書き換えで構成変更しましたが、 gcloud beta run deploy でvpc-egressオプションなどネットワーク系のオプションを付けることでデプロイ出来るようです。 構成変更後、Cloud RunからInternalロードバランサにむけてアクセスすることでk8sとの疎通を行うことができました。

外との通信についてはExternalアプリケーション ロードバランサのバックエンドにCloud Runを設定しました。5 Externalアプリケーション ロードバランサはIAPを有効にできるので、社内のユーザーのみにアクセスを閉じることができます。

このあたりはマルチコンテナ構成特有の事項はなさそうです。

マルチコンテナ構成Cloud Runでのネットワーク概念図

まとめ

ネットワークの部分はだいぶ端折ってしまいましたが、ここまでで社内サービスを無事GKEからCloud Runに移設可能だと確認できました。覚えることが少なく、かなり簡単にマルチコンテナ構成に変更できることが分かりましたね。

プレビュー時代と比べて、 gcloud beta run deploy でマルチコンテナ構成をデプロイできるようになったことで使い勝手が向上したところは嬉しいです。 一方で、コンテナ構成によってはデフォルト以外の起動プローブを設定したい場合もありそうです。その場合はこれまでもそうでしたが gcloud beta run deploy 一発という訳でいかないので注意が必要です。


  1. 実際にはGKE上に非同期処理をおこなうPubsubのSubscriberとして振る舞うサービスもデプロイしています。これはCloudRunがGKEよりも後発だったため、移行が間に合っていないということがあります。 [return]
  2. https://cloud.google.com/run/docs/deploying?hl=en#sidecars [return]
  3. https://cloud.google.com/run/docs/configuring/services/containers?hl=en#container-ordering [return]
  4. https://cloud.google.com/run/docs/configuring/vpc-direct-vpc [return]
  5. https://cloud.google.com/load-balancing/docs/https/setting-up-reg-ext-https-serverless [return]