Google Cloud Build の高速化 tips
Google Cloud Platform (以下「 GCP 」)の Cloud Build の処理を高速化するための tips をかんたんにまとめました。
情報はいずれも記事執筆時点のものです。 時間が経つとあてはまらなくなる部分も出てくるので、参考にされる際は注意してください。
Cloud Build でできることは Docker イメージのビルドだけではありませんが、今回は前提として Docker イメージのビルドを含む処理を行うことを想定しています。
背景
まずかんたんに Cloud Build を利用する上で前提となるポイントです。
- Cloud Build の実行時間は上限はデフォルトでは 10 分
- ちょっと時間がかかる処理を連ねると 10 分はわりとすぐに越える
Cloud Build 高速化 tips
- ボトルネックを特定する
Dockerfile
を見直す- Docker の代わりに Kaniko を使う
- Cloud Storage にキャッシュを置く
- マシンのスペックを上げる
- ステップの順序を
waitFor
で調整する - Docker イメージのダウンロード処理を並列化する
1. ボトルネックを特定する
Cloud Build にかぎりませんが、高速化を図る上でもっとも重要なことは戦略的にボトルネックを特定することです。 パレートの法則( 80:20 )を意識して「どこを改善すると最もインパクトが大きいか」をまず見極めます。
「 Docker イメージのビルド」に時間がかかっているのかそれとも「ダウンロード・アップロード」が遅いのか、ここを特定するだけでも大きな効果があります。
2. Dockerfile
を見直す
これは「 Docker イメージのビルド処理」に時間がかかっているときに有効な打ち手です。
Dockerfile
の中身を見直します。
主に「ベースイメージは適切か」「余計なステップが入っていないか」といったポイントをチェックします。
公式ドキュメントではこの打ち手は「よりスリムなコンテナのビルド」として紹介されています:
3. Docker の代わりに Kaniko を使う
こちらも「 Docker イメージのビルド処理」に時間がかかっているときに有効な打ち手です。 Google Cloud が公式の Kaniko を Docker イメージのビルドに使用します。
Kaniko というのは Docker イメージのビルドの中間成果物を Container Registry を保存・キャッシュしてくれるイメージビルダーです。 公式ということもあり細かな設定をしなくてもかんたんに導入できるのが特徴です。
具体的には、 Docker イメージのビルド処理を gcr.io/cloud-builders/docker
の代わりに gcr.io/kaniko-project/executor
ワーカーを使って実行します。
cloudbuild.yaml
:
steps:
# Kaniko ワーカーを使って Docker イメージをビルドする
- name: 'gcr.io/kaniko-project/executor:latest'
args:
- --destination=${_IMAGE_APP}
- --cache=true
substitutions:
_IMAGE_APP: 'asia.gcr.io/MY_PROJECT/app:latest'
公式ドキュメントではこの打ち手は「ビルドでの Kaniko キャッシュの有効化」として紹介されています:
ただし、 Kaniko キャッシュを使うと Container Registry のスペースを余計に消費します。 ビジネスユースではほとんどの場合気にならないレベルのコストだと思いますが、プライベートで使用する場合は気になる方もいるかもしれません。 プライベートで使う方は Kaniko を数日試して増加分のコストが許容可能な範囲に収まるかどうか確認しておくとよいと思います。
4. Cloud Storage にキャッシュを置く
こちらは Docker イメージ以外の処理に時間がかかっているときに有効な打ち手です。 ビルドで生成した成果物の一部を Cloud Storage に保存して次回のビルドで再利用します。
公式ドキュメントではこの打ち手は「 Google Cloud Storage でのディレクトリのキャッシュ」として紹介されています:
細かな方法についてはここでは紹介しないので公式ドキュメントや他の記事をご覧ください。
こちらも Cloud Storage の容量を消費するためコストが余計にかかります。 予算制限が厳しい場合はコストの増加分に注意が必要です。
5. マシンのスペックを上げる
こちらはボトルネックが CPU にありビルド処理が全体的に遅くなっている場合に有効な打ち手です。 ビルド処理に使用するマシンのスペックを上げます。
具体的には、 Cloud Build ではデフォルトでは安価な 1 CPU のマシンが使用されますが、 machineType
オプションでこれをスペックの高いマシンに変更します:
cloudbuild.yaml
:
# デフォルトのマシンは遅いのでひとつ上のものを使う
options:
machineType: 'E2_HIGHCPU_8'
記事執筆時点では以下の 4 つのマシンタイプが選択可能です。
N1_HIGHCPU_8
N1_HIGHCPU_32
E2_HIGHCPU_8
E2_HIGHCPU_32
公式ドキュメントではこの打ち手は「カスタム仮想マシンサイズを使用する」として紹介されています:
その他参考:
options
| ビルド構成ファイルのスキーマ | Cloud Build のドキュメント | Google CloudMachineType
| REST Resource: projects.builds | Cloud Build のドキュメント | Google Cloud
こちらもマシンスペックを上げるとコストが上がるので、コスト増加分に注意が必要です。
6. ステップの順序を waitFor
で調整する
こちらは一連のステップの中に互いに独立で並列に進められるものがある場合に有効な打ち手です。
各ステップで waitFor
を使って、各ステップの順序・先行ステップを設定します。
たとえば、「 Firebase Hosting にあげる静的サイトのビルド」と「 Cloud Run で動かす Docker イメージのビルドとデプロイ」という 2 つの独立した処理を行う場合、これらは直列に実行しなくても OK です。 たとえば次のようにすれば並行で処理を進められます。
cloudbuild.yaml
:
steps:
# Cloud Run にあげる Docker イメージをビルドする
- name: '${_WORKER_DOCKER}'
args:
- 'build'
- '-t'
- '${_ARTIFACT_CLOUDRUN}'
- '{_CLOUD_RUN_DIR}'
# Firebase Hosting にあげる静的サイトをビルドする
- name: '${_WORKER_NODE}'
entrypoint: 'npm'
args:
- 'install'
id: 'npm install'
# Cloud Run にあげるイメージのビルドを待たなくてもよいので先に進める
waitFor:
- '-'
substitutions:
_WORKER_DOCKER: 'gcr.io/cloud-builders/docker'
_WORKER_NODE: 'node:16-slim'
_ARTIFACT_CLOUDRUN: '...'
_CLOUD_RUN_DIR: '...'
なおこの打ち手は、ネットワークなどがボトルネックとなっている場合には有効ですが、 CPU がボトルネックとなっている場合にはあまり効果はありません。
公式ドキュメントではこの打ち手は「ビルドステップの順序の構成」というところで紹介されています:
7. Docker イメージのダウンロード処理を並列化する
こちらは、使用する Docker イメージのサイズが大きくダウンロードに時間がかかる場合に有効な打ち手です。 Docker イメージのダウンロードを並列化します。
ただし、(記事執筆時点で最新の 20.10.6
の) docker pull
は複数のイメージをまとめてダウンロードする機能が無いため、これをやるには Bash で for ループを回して wait
で待機するなどの工夫が必要です。
cloudbuild.yaml
:
steps:
# 利用するワーカーの Docker イメージをあらかじめまとめて pull する
- name: '${_WORKER_DOCKER}'
entrypoint: 'bash'
args:
- '-c'
- |
images=('${_WORKER_NODE}' '${_WORKER_GCLOUD}' '${_WORKER_FIREBASE}')
for image in $${images[@]}
do
docker pull $${image} &
done
wait
substitutions:
_WORKER_DOCKER: 'gcr.io/cloud-builders/docker'
_WORKER_NODE: 'node:16-slim'
_WORKER_GCLOUD: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
_WORKER_FIREBASE: 'asia.gcr.io/MY_PROJECT/firebase'
ということで、 Cloud Build の処理を高速化するための tips でした。
また他にもよいものが見つかれば追加していきます。