Cloud Runへのデプロイ時間短縮方法の模索
はじめに
こんにちは!今年社会人2年目を迎える山﨑です。
近年、クラウドの普及によって、インフラ管理や運用でサーバーレスなサービスを利用している人も多いのではないでしょうか。
私自身も業務でCloud Runを使っています。
その中で、Cloud Runへのデプロイ手法にはどのようなものがあるのか、手法によるデプロイ時間に差異はあるのか、という疑問を持っていました。
この記事では、自分の備忘録もかねて、デプロイ手法とデプロイ時間の差異についてまとめています。
背景
- これまで
gcloud run deploy
コマンドでソースからデプロイしていましたが、ソースコードの軽微な修正にもかかわらず、再デプロイ完了までに初回デプロイと同程度の時間を要することが気になっていました。 -
gcluod run deploy
コマンドを実行すると、裏ではCloud Buildによるビルドプロセスが実行されることは知っていたため、Cloud Buildを明示的に使用するとデプロイ時間に変化があるのか気になりました。 - また、(多分)Google Cloud Professional Cloud Developer Certificationの学習をしている際、
cache-from
引数を使用するとビルド時間を短縮できるということを知りました。 - 以上を踏まえ、複数のデプロイ手法を実施・比較し、デプロイ時間を短縮するという目標を達成するためにどの手法が良いか模索します。
デプロイ手法
以下の手法でデプロイし、時間を計測します。操作はすべてCloud Shellから行います。
なお、cache-from
引数ありの手法の時間については、2回目以降のビルド・デプロイ時間です。
1. gcloud run deploy
でソースからデプロイする
2. Dockerfileからgcloud builds submit
でビルドし、gcloud run deploy
でイメージからデプロイする
3. cloudbuild.yamlでビルド〜デプロイまで行う
3-1. cache-from
引数なし
3-2. cache-from
引数あり
4. cloudbuild.yamlでビルド~プッシュまでを行い、gcloud run deploy
でデプロイする
4-1. cache-from
引数なし
4-2. cache-from
引数あり
cache-from
引数に関する補足(参考)
Docker イメージビルドの速度を上げる最も簡単な方法は、後続のビルドに使用できるようにキャッシュ イメージを指定することです。ビルド構成ファイルに
--cache-from
引数を追加すると、キャッシュされたイメージを指定できます。これにより、Docker はこのイメージをキャッシュ ソースとしてビルドします。
Docker イメージは、スタックレイヤから構成されています。--cache-from
を使用すると、変更されたレイヤからビルドの最後までのすべてのレイヤが再構築されます。したがって、Docker ビルドの初期段階でレイヤを変更する場合には、--cache-from
の使用は得策ではありません。ビルドに
--cache-from
を常に使用することをおすすめしますが、次の点に注意してください。
- キャッシュから取得するには、以前にビルドした Docker イメージが必要です。
--cache-from
は Docker ビルドにのみ使用できます。他の種類のアーティファクトを作成するビルダーには使用できません。- キャッシュされたイメージはレジストリから取得する必要があります。このため、ビルドにかかる時間が長くなることがあります。
補足:今回の検証でデプロイするアプリの概要
- 言語:Python
- フレームワーク:streamlit
- 依存ライブラリ数:少ない
test_app/
├app.py
├cloudbuild.yaml
├Dockerfile
├.gcloudignore
├requirements.txt
└run.sh #下記の時間計測コマンド実行用スクリプト
時間計測方法
以下を使うことで時間を計測します。
実行後に表示されるreal
の時間をかかった時間とします。
手法2と4は、2つのgcloudコマンドを実行し、それらを合算します。
#手法1
time gcloud run deploy --source=. --project=<PROJECT_ID>
#手法2
time gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME
time gcloud run deploy --image=<IMAGE>
#手法3
time gcloud builds submit --config cloudbuild.yaml .
#手法4
time gcloud builds submit --config cloudbuild.yaml .
time gcloud run deploy --image=<IMAGE>
結果
それぞれの手法における時間は以下の表のようになりました。
結果から以下の2点が分かりました。
1. ビルドとデプロイは分離した方が早い
2. cache-from
引数を使用した方が早い
# | 手法 | 時間 | 順位 |
---|---|---|---|
1 |
gcloud run deploy でソースからデプロイ |
2m19s | 4 |
2 | Dockerfileからgcloud builds submit でビルドし、gcloud run deploy でイメージからデプロイ |
1m38s+18s=1m56s | 2 |
3-1 | cloudbuild.yamlでビルドからデプロイまで行う(cache-from 引数なし) |
3m8s | 6 |
3-2 | cloudbuild.yamlでビルドからデプロイまで行う(cache-from 引数あり) |
2m33s | 5 |
4-1 | cloudbuild.yamlでビルド~プッシュまでを行い、gcloud run deploy でデプロイする(cache-from 引数なし) |
1m52s+20s=2m12s | 3 |
4-2 | cloudbuild.yamlでビルド~プッシュまでを行い、gcloud run deploy でデプロイする(cache-from 引数あり) |
1m1s+19s=1m20s | 1 |
気になった点
- cloudbuild.yamlでビルドからデプロイまで行ったときに最も時間がかかったこと
- 実質的に同じ処理を行っていそうな#1と#3-1で50秒程度、#2と#4-1で20秒弱の差があること
考察
- Cloud Buildは一連のビルドステップを分離したコンテナ環境で実施され、各ステップの実行後にそのコンテナが破棄されます(参考)。そのため、各ステップにおけるコンテナ起動時間などの小さなオーバーヘッドの積み重ねによりデプロイ時間が最も遅くなったと考えます。
-
gcloud run deploy
コマンドでイメージからデプロイした場合のデプロイ単体に要した時間はいずれも20秒程度であり(結果の表#2, #4-1, #4-2)、ビルドプロセスに大半の時間を要していることがわかります。gcloud run deploy
コマンドではビルドプロセスを柔軟に設定することができず、キャッシュを利用するといった設定もできません。したがって、デプロイまでの時間を短縮するという私の目標を達成するためには、ビルドとデプロイを分離し、キャッシュを利用できるようにすることが求められます。
おわりに
今回6つの手法を実施して、ビルドとデプロイの分離、cache-from
引数によりデプロイ時間を短縮できるという結果が得られました。
今回検証した以外の手法や、より効率的なファイルの書き方を調べつつ、適したデプロイ方法を見つけたいです。
おすすめの方法があればぜひご教示お願いします。
参考
- Dockerfileを使用したビルド:コンテナ イメージのビルド
- cloudbuild.yamlの書き方:Cloud Build を使用した Cloud Run へのデプロイ
-
cache-from
引数を使用したビルド:ビルドを高速化する際のベスト プラクティス
Discussion