Masayan tech blog.

  1. ブログ記事一覧>
  2. Cloud Runを実務でしっかり運用するために押さえておきたい内容を解説

Cloud Runを実務でしっかり運用するために押さえておきたい内容を解説

公開日

Cloud Runの特徴

  • コンテナベースでアプリケーションをデプロイできるGoogle Cloudのフルマネージドのサーバーレスサービス
    • コンテナイメージさえ作成すればいいので、実行環境、使用言語の柔軟性が高い
  • ゾーン障害耐性
    • Cloud Runはリージョンサービスなので、自動的に複数ゾーンにロードバランシングされるようになっている
  • オートスケール
    • 負荷に応じて自動的にスケールアウトし。最大0インスタンスまでスケールイン可能
  • Cloud RunにはCloudRunサービスとCloudRunジョブの2つの利用形態がある
  • リビジョン(バージョン管理)機能
  • Cloud SQL、MemoryStore、シークレットマネージャー等のGCPの別サービスと簡単に連携が可能
  • 秒単位でアプリケーションをデプロイ可能

ユースケース

Cloud Functionsとの違い

項目

Cloud Run

Cloud Functions

デプロイ対象

コンテナイメージを用意する必要があるが、柔軟な実行環境の構築が可能

ソースコードのみなのでサクッとデプロイ可能

開発言語

制限なし

制限あり

最大実行時間

60 分間

HTTP関数で 60 分(第2世代)
イベントドリブン関数で 10 分

インスタンスのライフサイクル

  1. スケーリング
  • 受信リクエストまたはイベントを処理するために必要なインスタンス数に自動的にスケーリング
  1. スタートアップ
  • インスタンスの起動
  • インスタンス起動中に送信されたリクエストはキュー内で保留状態になる
  1. リクエストの処理
  • インスタンス起動後、リクエストが処理される
  1. アイドル状態
  • リクエスト処理後、インスタンスはすぐにシャットダウンされずに連続する次のリクエストに対応するためアイドル状態となる
  1. シャットダウン
  • アイドル状態から15分リクエストがない場合、インスタンスはシャットダウンされる

トリガー

  • HTTPS
  • Pub/Subのpush
  • Eventarc
  • 非同期タスクの実行
    • Cloud Tasksと連携して、タスクをキューに格納した後、Cloud Runによって非同期に処理させることが可能
  • Cloud Schedulerスケジューラーと連携した定期実行

インスタンスへのリクエスト

エンドポイント

  • アプリケーションをデプロイすると、リクエストを受信する HTTPS エンドポイントが払い出される
    • デフォルトでは、Cloud Run サービスには *.run.app ドメインの一意のサブドメイン
    • カスタムドメインの設定も可能

タイムアウト

  • デフォルトで5分(300秒)に設定されているが、最大60分(3600秒)まで延長できる
  • 指定した時間内にレスポンスが返されない場合、リクエストが終了し504エラーが返される

セッションアフィニティ

  • 同じクライアントからの連続したリクエストを同じリビジョンインスタンスに転送する機能のこと
  • スケールインにより削除されたインスタンスに関しては、そもそも接続することができず、別のインスタンスに接続されるので注意
  • 新しいリビジョンの編集とデプロイ→[セッション アフィニティ] テキスト ボックスをクリックすることで有効化できる

https://cloud.google.com/run/docs/configuring/session-affinity?hl=ja

429エラーとなる条件

  • 処理中のリクエストが [最大同時実行数 × 最大インスタンス数] を超過しており、待機キューで10秒待っても振り分けられない場合に発生する
  • 最大同時実行数を超過して、新しいインスタンスの起動を待っている間は待機時間が10秒を超えても429エラーにはならない。ただしユーザーリクエストは起動を待っており、レイテンシに影響はある

オートスケール

概要

  • 負荷に応じて自動的にスケールアウト/インする

スケールアウト

  • 最大インスタンス数はデフォルトが100で、最大1000までスケールアウトできる
    • 割り当ての増加をリクエストすると1000以上スケールアウトすることも可能
    • 一部のケースでは、最大インスタンス数を超えるインスタンスを作成することがある(必ずしも最大インスタンス数を超えないという保証はない)
      • このような特性からサービス要件として、許容できる最大インスタンス数よりも少しバッファを設けた数値を設定することが推奨されている
      • Cloud SQL等のバックキングサービスがある場合、最大インスタンス数が多すぎるとそちらに負荷がかかるため、その辺りの調整も必要
    • インスタンスが立ち上がるまでの時間は10秒程度
      • (参考)App Engine Flexible環境だと、VMベースの実行環境のため負荷の増大を検知してから新しいインスタンスがサービスインするまで数分かかる

スケールイン

  • インスタンス数を0までスケールインさせることが可能(リクエストが全くない時など)

スケール条件

Cloud Runのオートスケーラーは5秒ごとに以下を評価して、スケールアウト/インするかどうかを決定している

  • CPU使用率
  • 最大同時実行数
  • インスタンスの最小数の設定
  • インスタンスの最大数の設定

CPU使用率

  • リクエストまたはイベントを1分以上処理中の既存インスタンスのCPU使用率が、60%を超えるとスケールアウト

最大同時実行数

  • 1分間でのリクエストの最大同時実行数と比較した現在の同時実行数(インスタンスあたりの最大同時リクエスト数)を超過した場合、CPU利用率にかかわらずただちに新しいインスタンスが起動され、そちらにトラフィックが振り分けられる
  • デフォルトは80で、1~1000の範囲で設定することができる

インスタンスの最小数の設定

最小数を下回る場合はスケールインしない

インスタンスの最大数の設定

最大数を超える場合はスケールアウトしない(※前述の通り、例外あり)

コールドスタート

概要

インスタンスを起動する時間分、処理の遅延が発生することをコールドスタートといい、具体的には以下のようなケースで生じる可能性がある

  • インスタンス数が0の状態でCloud Runサービスに対するリクエストがあった場合
  • リクエスト数が急激に増加し、コンテナインスタンスのスケールアウトがリクエスト数の増加に間に合わない場合

対処法

  • 最小インスタンス数を1以上にすることにより、コンテナインスタンスのウォームアップリクエストを維持し、リクエストをすぐに処理する
    • 指定した数のコンテナインスタンスがアイドル状態で常に起動しており、リクエストを処理していないときでも、アイドル状態のインスタンスの料金が発生するので注意
    • アイドル状態のインスタンスの料金は、実際にリクエスト処理をしているときの料金よりも安く設定されている ( 料金表 )

Startup CPU boost

概要

  • 最小インスタンス数を1以上にすると、0→1の場合コールドスタート対策にはなる
  • しかし、サーバーレスの強みが損なわれてしまうし、リクエスト数が急増した場合、コンテナインスタンスのスケールアウトがリクエスト数の増加に間に合わないと、新しく起動されるコンテナインスタンスでは同様にコールドスタートが発生するので、根本的な解決策にならない
  • また、最小インスタンス数に該当するインスタンスは、アクティブ状態でもアイドル状態でも課金対象なので、それなりに費用が発生する
  • サーバーレスの強みを活かしつつ、コールドスタート対策できる機能として、Startup CPU boostというものがある
  • コンテナインスタンスの起動中に追加のCPUを割り当てることで、インスタンス数が0のときにリクエストがあった場合や、インスタンスがスケールアウトする場合に、コールドスタートによるレイテンシを軽減することができる機能(インスタンスの起動時に一時的にCPU割り当てを増やして起動レイテンシを短縮できる)

追加料金

  • 割り当てられたブーストCPUはコンテナの起動中に課金される
  • たとえば、ブーストを有効にしたCPU数2のコンテナインスタンスの起動時間が10秒の場合、起動中の10秒間だけCPU数4の料金が発生する

設定手順

  • サービス作成時、更新時に「起動時のCPUブースト」にチェックをつける

注意点

起動時に追加で割り当てることができるCPU数は、コンテナインスタンスに設定したCPU数の上限値によって変わる

設定した CPU 上限

ブースト時の CPU 数

0-1

2

2

4

4

8

6

8

8

8(ブーストされない)

アイドル状態のインスタンス

概要

  • すべてのリクエストを処理した後、インスタンスはすぐにシャットダウンされず、コールドスタートの影響を最小限に抑えるために、最大で15分間アイドル状態で待機する

インスタンスの最小数が設定されている場合

  • インスタンスの最小数の構成で、常に指定数のインスタンスをアイドル状態にする必要がある場合は、最小のインスタンス数を維持しようとするため、15分以上アイドル状態のインスタンスが残ることがある
  • たとえば、最小インスタンス数が10で、アクティブなインスタンスの数が0の場合、アイドル状態のインスタンスの数は10になり、アクティブなインスタンスの数が5まで増えると、アイドル状態のインスタンスの数は5に減る
  • 最小数を保持するために起動されているアイドル状態のインスタンスには、全くリクエストを処理していない場合でもコストが発生することに注意が必要
  • 余談だが、最小インスタンスが0でも、GoやPythonのような軽量言語で実装されていればそもそもコンテナはある程度高速で起動する

リビジョン管理

概要

サービスをデプロイもしくは構成を変更すると、新しいリビジョンが作成され流ようになっており、以下のような機能を実現できる

  • リビジョンが受信するトラフィックの割合を指定して、複数のリビジョンでトラフィックを分割
  • 以前のリビジョンへのロールバック
  • リビジョンの段階的なロールアウト

また、新しいリビジョンが作成されたタイミングで、Artifact RegistryレジストリからコンテナイメージをPullしてコンテナイメージのコピーを作成し、内部に保存してコンテナ起動時に使用する

トラフィック切り替えの即時性

リビジョンのトラフィックを変更しても、現在処理中のリクエストは続行され、処理中のリクエストは破棄されないため、リビジョンのトラフィック移行期間中に以前のリビジョンにリクエストが送信される可能性がある

タグ

  • リビジョンにタグをつけるとリビジョン名---がhttps://の直後に付与されたurlにアクセスできるようになるので、新しいバージョンへのトラフィック切り替え前にテストすることが可能
https://リビジョン名---**-an.a.run.app
  • タグは管理画面からもデプロイ時に指定することも可能
# デプロイ時にタグをつけることも可能
gcloud run deploy sample_service --image IMAGE_URL  --no-traffic --tag TAG_NAME

CPU

概要

  • 使用するCPUを1未満にする場合は、0.08から1までの範囲の値を0.01単位で選択する必要がある
  • 1より大きい値は整数値にする必要がある
  • CPUを1未満の値で指定すると、いくつかの制限が適用される

CPUの割り当て方

リクエストの処理中のみCPUを割り当てる

  • デフォルトの挙動
  • リクエストを処理している間に割り当てられたCPUとメモリの利用時間について100ミリ秒の粒度で課金される
  • アイドル状態のインスタンスには課金されない(※最小インスタンス数を1以上にしている場合のみ、アイドル状態のインスタンスに対しても料金が発生する)
  • デプロイしたCloudRunサービスに対するリクエスト数について100万リクエスト単位で課金される
  • ユースケース
    • 特定の時間帯(深夜など)にトラフィックがほとんど来ない
    • 管理画面など内部的に使用するサービス
    • 受信トラフィックが散発的かバーストまたは急増する場合

CPUを常に割り当てる

  • リクエストがない場合でもコンテナインスタンスにCPUを割り当てることが可能になり、短期のバックグラウンドタスクや非同期処理タスクを実行することができる
  • 512MiB以上のメモリを用意する必要がある
  • オートスケールについて
    • CPUが常に割り当てられている場合でも、オートスケーリングは有効であり、受信トラフィックの処理に必要ないインスタンスは停止できる。リクエスト処理後15分を過ぎるとインスタンスのアイドル状態は解除される
    • リクエスト処理中のCPU使用率が60%を超過した場合にのみスケールアウトする
    • リクエストのないバックグラウンドアクティビティを実行する場合、CPU使用率が60%のしきい値を超えてもスケールアウトされないことがある。(リクエストを処理していないインスタンスのCPU使用率は、CloudRunによって実質的に無視されるため)
  • 常にリクエストを一定数受信する、受信トラフィックが安定して緩やかなサービスの場合に向いている

料金

概要

  • インスタンスに割り当てられたCPUとメモリは100ミリ秒の粒度で課金される
  • 最小インスタンス数を構成しておらず、かつサービスが全く使用されていなければ料金は発生しない
    • 最小インスタンスに該当するインスタンスはアクティブでもアイドル状態でも課金対象
    • 最小インスタンスではないアイドル状態のインスタンスは課金されない
  • 最小インスタンスの設定が1以上になっているリビジョンがいくつかある場合、使っていないリビジョンも課金対象に含まれるため注意
  • 毎月適用される無料枠あり
  • CPUをどのように割り当てるか(リクエストの処理中のみCPUを割り当てる場合と、CPUを常に割り当てる場合)で、別々の料金体系が適用される(料金表)

リクエストの処理中のみCPUを割り当てる

  • リクエストを処理しているとき(リクエストを受け付けてからレスポンスを返すまでの間)のみCPUが割り当てられ、割り当て時間(秒単位)に応じて料金が発生
  • インスタンスを起動してからリクエストを受け付けるまでの間は課金されない

CPUを常に割り当てる

  • CPUを常に割り当てる場合はコンテナインスタンスの起動から終了までCPUが割り当てられ、そのライフサイクル全体に課金される
  • リクエスト単位の課金はなく、CPUとメモリの利用時間についての課金のみとなる
  • 料金単価は「リクエストの処理中のみCPUを割り当てる」場合よりも安価なものが適用される (料金表)

コンテナ要件

コンテナイメージ内の実行可能ファイルは、Linux64ビット用にコンパイルする必要がある

アプリケーション要件

  • リクエストの送信先ポート(デフォルトのポートは8080)で0.0.0.0のリクエストをリッスンするHTTPサーバーを起動する必要がある
  • リクエストを受信してからリクエストのタイムアウト設定で指定された時間内に、レスポンスを返す必要がある
  • サービスがネットワーク ファイル システムを使用する場合は、第 2 世代の実行環境を使用する必要がある

コンテナ実行環境 (世代)

  • コンテナ実行環境として、第1世代と第2世代が選択可能
  • デフォルトは第1世代
  • 実行環境の選択基準(公式ドキュメント)
  • 第2世代は持続的な負荷の下では迅速に動作するが、ほとんどのサービスでは、第1世代よりもコールド スタート時間が長くなる

世代

特徴

ユースケース

第 1 世代

・高速なコールドスタート
・ネットワークファイルシステムは使用できない

・バーストトラフィックが予測される場合
・スケール時のコンテナインスタンスの起動速度をとにかく優先したい
・Cloud Run サービスに対する定常的なトラフィックがなく、コンテナインスタンスの数が頻繁にゼロまでスケールインする場合
・512 MiB 未満のメモリを使用したい場合(第 2 世代は最低 512 MiB)

第 2 世代

・ネットワークファイルシステムのサポート、Linux との完全な互換性
・CPU とネットワークパフォーマンスの高速化

・アプリケーションからネットワークファイルシステムを使用する場合
・Cloud Run サービスに対する定常的なトラフィックがあり、コールドスタートが多少遅くても許容できる場合
・CPU やネットワークに高いパフォーマンスが求められるワークロードの場合

VPCネットワークとの接続

  • Cloud RunはプロジェクトのVPC内に存在しないため、VPC内のリソースにPrivateIP(内部IP)でアクセスすることはデフォルトでは不可
  • Cloud SQLやMemorystoreといったVPCに紐づくリソースに対してプライベートIPで接続したい場合、サーバーレス VPC アクセス を設定する必要がある

障害耐性

  • Cloud Run サービスは特定のリージョンに作成され、冗長性とフェイルオーバーのため、リージョン内の複数のゾーンに自動的に複製される
  • 適切に負荷分散されるので、利用者はゾーン障害を意識する必要がない

ローカルでの動作検証

Recommenderによる最適化

Google Cloud上でのリソースの使用に関する推奨事項とインサイトを提供してくれるサービス

費用

  • CPU割り当てを最適化できる
  • 過去1か月間にCloudRunサービスが受信したトラフィックをもとに、より適切なCPUの割り当て方を提案してくれる

セキュリティ

過剰なサービスアカウントへの権限付与がある場合や環境変数にパスワード等のシークレット値が含まれる場合、適切な構成/設定を提案してくれる

必要な権限

GoogleCloudサービスからCloudRunサービスを呼び出す場合は、CloudRun起動元(roles/run.invoker)ロール、もしくは同等の権限をもつカスタムロールが付与されたサービスアカウントによる認証が必要

継続的デプロイ

Cloud Buildを使用して、Dockerイメージのビルド、レジストリへのpush、デプロイが可能

デプロイ時のオプション

https://cloud.google.com/sdk/gcloud/reference/run/deploy

使用するコンテナイメージの指定

gcloud run deploy sample --image=asia-northeast1-docker.pkg.dev/path/to/image

quiet

デプロイプロセス中に通常表示されるプロンプトや確認メッセージが表示されなる。有効にすると、デプロイプロセスがユーザーの介入なしにスムーズに進行する

gcloud run deploy \
  sample \
  --quiet \
  ・・・

concurrency

デプロイ時に最大同時リクエスト数を指定できる

gcloud run deploy \
  sample \
  --concurrency=1000 \
  ・・・

image

Artifact Registry上のDockerイメージを指定する

gcloud run deploy ${{ env.SERVICE_NAME }} \
    --image asia.gcr.io/${{ env.GCP_PROJECT_ID }}/${{ env.SERVICE_NAME }}:${{ github.sha }} \

platform

  • デフォルトはmanaged(Cloud Runの完全管理版)
  • platform=gkeを指定すると、Cloud Run for Anthos(GKEクラスタ上で動作)が使用され、より詳細な設定と制御が可能になる

allow-unauthenticated

サービスへの認証されていないアクセスを許可する。許可する場合は--allow-unauthenticatedを、許可しない場合には--no-allow-unauthenticatedを使用する

gcloud run deploy sample \
    ・・・
    --allow-unauthenticated \

--no-traffic

デプロイ後に新しいリビジョンにトラフィックを自動的に切り替えない

gcloud beta run deploy sample \
    --no-traffic
    ・・・

--tag

新しく作成されるリビジョンに割り当てるトラフィックタグを指定

gcloud run deploy sample \
    ・・・
    --tag v1

ベストプラクティス

https://cloud.google.com/run/docs/tips/general?hl=ja#write_effective_services

まとめ

いかがでしたでしょうか。本記事では、Cloud Runを実務でしっかり運用するために押さえておきたい内容を解説しました。具体的にはCloud Runの特徴、ユースケース、Cloud Functionsとの違い、料金体系、CI/CDとの連携方法など実務で利用する上で必須の内容を中心に説明していますので、ぜひ参考にしてみてください