Cloud Run 上のコンテナのライフサイクル
Google Cloud Japan Team
※この投稿は米国時間 2021 年 1 月 27 日に、Google Cloud blog に投稿されたものの抄訳です。
編集者注: 本日の投稿は、Binx.io のソフトウェア エンジニア兼トレーナーであり、O’Reilly 出版の Google Cloud Run に関する書籍の著者でもある Wietse Venema 氏によるものです。ここでは、ユーザーが Cloud Run を最大限に活用できるように、コンテナのライフサイクル全体と、その中で起こる状態の移り変わりについて同氏にご説明いただきます。
サーバーレス プラットフォームである Cloud Run は、コンテナベースのアプリケーションを実行し、自動的に規模を調整することができます。コンテナのライフサイクル全体とその中で起こる状態の移り変わりを理解すれば、このプラットフォームを最大限に活用することができます。それでは、開始から停止までの状態の流れについて見ていきましょう。
まず、これまで Cloud Run をご存じなかった方のために、いくつかご説明します(ご存じの場合は、「コンテナの開始」まで進んでください)。Cloud Run の開発者ワークフローには、次のシンプルな 3 つのプロセスがあります。
任意のプログラミング言語を使用してアプリケーションを作成し、アプリケーションで HTTP サーバーを起動させる。
アプリケーションをビルドして、コンテナ イメージにパッケージ化する。
作成したコンテナ イメージを Cloud Run にデプロイする。
コンテナ イメージをデプロイすると、一意の HTTPS エンドポイントが得られます。次に、Cloud Run がリクエストを処理するためにオンデマンドでコンテナを起動し、すべての着信リクエストが確実に処理されるよう、コンテナを動的に追加および削除します。ハンズオン クイックスタートを参照して、ご自身で試してみましょう。
コンテナ イメージとコンテナの違いを理解することが重要です。コンテナ イメージは、アプリケーションと、アプリケーションを実行するために必要なあらゆるものを含むパッケージであり、保存と配布を行うアーカイブです。コンテナは、アプリケーションの実行中のプロセスを表します。
アプリケーションをコンテナ イメージにビルドしてパッケージ化する方法は複数存在します。Docker は、下位層のコントロールと柔軟性を提供するものです。Jib と Buildpacks は、より上位層のハンズオフ体験を提供します。Cloud Run を利用して生産性を高めるためにコンテナのエキスパートになる必要はありませんが、エキスパートになれば、Cloud Run が妨げになることはありません。ご自身とプロジェクトにとって最適なコンテナ化手法をご選択ください。
コンテナの開始
コンテナを開始すると、次のことが発生します。
Cloud Run によってコンテナ イメージが実体化され、コンテナのルート ファイルシステムが作成される。
コンテナ ファイルシステムの準備が整った後、Cloud Run によってコンテナ(アプリケーション)のエントリ ポイント プログラムが実行される。
アプリケーションの起動中、Cloud Run によってポート 8080 が継続的にプローブされ、アプリケーションの準備ができているかどうかが確認される(必要に応じて、ポート番号は変更できます)。
アプリケーションが TCP 接続の受け入れを開始すると、Cloud Run によって着信 HTTP リクエストがコンテナに転送される。
Cloud Run は、Artifact Registry の Docker リポジトリに保存されているコンテナ イメージのみをデプロイできます。ただし、新しいコンテナを起動するたびに、そこからイメージ全体が pull されるわけではありません。そうなると不必要な遅延が発生します。
その代わり Cloud Run は、新しいバージョン(Cloud Run のリビジョンと呼ばれる)のデプロイ時に Artifact Registry レジストリからコンテナ イメージを 1 回のみ pull します。次に、コンテナ イメージのコピーを作成し、内部に保存します。
内部ストレージの処理速度は早いため、イメージサイズがコンテナ起動時間のボトルネックに鳴ることはありません。サイズの大きなイメージも小さなイメージと同じくらいのスピードで読み込まれます。コールド スタートのレイテンシの改善を試みている場合、このことを知っておくと便利です。コールド スタートは、リクエストが届いた際、それを処理するために使用できるコンテナがない場合に発生しますが、Cloud Run によって、新しいコンテナが開始するまでリクエストが保持されます。
コンテナが、リクエストを常時処理できるようにしたい場合は、最小インスタンスを構成することで、コールド スタートの数を低減することができます。
Cloud Run はイメージをコピーするため、デプロイされたコンテナ イメージを誤って Artifact Registry から削除しても支障は生じません。Cloud Run サービスはコピーを使用して機能し続けます。
リクエストを処理する
コンテナは、リクエストを処理していないときは、アイドル状態と見なされます。従来のサーバーでは、この点はあまり考慮されなかったかもしれません。しかし Cloud Run では、以下の理由により、この状態は重要となります。
アイドル状態のコンテナには費用が発生しません。費用が発生するのは、コンテナの起動時、リクエストの処理時(100 ミリ秒の粒度)、シャットダウン時に使用するリソースに対してのみです。
アイドル状態のコンテナの CPU はほぼゼロに抑制されます。つまり、アプリケーションが非常に遅いペースで実行されるということです。これは、費用が発生しない CPU 時間であることを考慮すれば理にかなっています。
ただし、コンテナの CPU が抑制されている場合、コンテナでバックグラウンド タスクが実行されることは保証されません。後のタスクが確実に実行されるようスケジュールする場合は、Cloud Tasks をご参照ください。
アイドル状態になった後にコンテナでリクエストが処理されると、Cloud Run によってコンテナの CPU の抑制が直ちに解除されます。お使いのアプリケーション、そしてユーザーは、遅延にまったく気付きません。
また Cloud Run は、トラフィックの急増に対処し、コールド スタートを減らすため、想像以上に長くアイドル状態のコンテナを維持できます。しかし、その機能性に依存しすぎることは禁物です。アイドル状態のコンテナはいつでもシャットダウンされる可能性があるためです。
シャットダウンする
コンテナがアイドル状態の場合、Cloud Run はコンテナの停止を選択することがあります。デフォルトでは、コンテナはシャットダウンされると消滅します。
ただし、SIGTERM シグナル(Linux カーネル機能)を処理するようにアプリケーションをビルドすることは可能です。SIGTERM シグナルは、シャットダウンが迫っていることをアプリケーションに警告するものです。警告を受けたアプリケーションには 10 秒間与えられ、コンテナが削除される前にクリーンアップを行うことができます。たとえばこの間に、データベース接続を閉じたり、別の場所に送信する必要のあるデータがあるバッファをフラッシュしたりすることが可能になります。Cloud Run 上で SIGTERM を処理する方法を学ぶことで、突然ではなく、余裕を持ってシャットダウンが行われるようにすることができます。
ここまで、Cloud Run の状態の移り変わりについて確認してきました。それでは、リクエストの処理中にアプリケーションがクラッシュして停止した場合はどうでしょうか?
異常が発生した場合
通常の状況では、Cloud Run がリクエストを処理中のコンテナを停止することはありません。しかし、アプリケーションが終了した場合(たとえばアプリケーション コードのエラーが原因)や、コンテナがメモリ制限を超えた場合に、コンテナが突然停止する可能性があります。
コンテナがリクエストの処理中に停止すると、その時点で実行中のすべてのリクエストが停止され、そのリクエストはエラーになり失敗します。Cloud Run が代わりのコンテナを開始する間、新しいリクエストは待機が必要になる可能性があり、それは回避したいところです。
メモリ不足を回避するには、メモリ上限の構成を行います。デフォルトでは、コンテナは Cloud Run 上に 256 MB のメモリを取得しますが、この割り振りを 4 GB に増やすことができます。ただし、アプリケーションによってメモリが割り振られすぎると、Cloud Run によって SIGTERM の警告なしにコンテナが停止されることもあるため注意が必要です。
まとめ
ここでは、Cloud Run におけるコンテナのライフサイクル全体について、サービスの開始から提供、シャットダウンまでについて学習しました。要点を以下にまとめます。
Cloud Run は、コンテナ イメージのローカルコピーを保存して、コンテナの起動時に非常に高速に読み込みを行う。
コンテナは、リクエストを処理していないときはアイドル状態と見なされる。アイドル状態のコンテナには料金は発生しないが、CPU はほぼゼロに抑制される。そして、アイドル状態のコンテナはシャットダウンされる可能性がある。
SIGTERM を使用すると、余裕を持ってシャットダウンできるが、確実に実行されるとは限らない。メモリ制限をよく確認し、エラーによってアプリケーションがクラッシュしないようにする必要がある。
私は、Binx.io のエンジニア兼トレーナーであり、O’Reilly 出版の Google Cloud Run に関する書籍(全章の概要を読む)の著者です。Twitter: @wietsevenema(DM を開く)はこちらです。お気軽にフォローしてください。
-Binx.io ソフトウェア エンジニア Wietse Venema