Google Cloud Build の高速化 tips

Google Cloud Platform

Google Cloud Platform (以下「 GCP 」)の Cloud Build の処理を高速化するための tips をかんたんにまとめました。

情報はいずれも記事執筆時点のものです。 時間が経つとあてはまらなくなる部分も出てくるので、参考にされる際は注意してください。

Cloud Build でできることは Docker イメージのビルドだけではありませんが、今回は前提として Docker イメージのビルドを含む処理を行うことを想定しています。

背景

まずかんたんに Cloud Build を利用する上で前提となるポイントです。

  • Cloud Build の実行時間は上限はデフォルトでは 10 分
  • ちょっと時間がかかる処理を連ねると 10 分はわりとすぐに越える

Cloud Build 高速化 tips

  1. ボトルネックを特定する
  2. Dockerfile を見直す
  3. Docker の代わりに Kaniko を使う
  4. Cloud Storage にキャッシュを置く
  5. マシンのスペックを上げる
  6. ステップの順序を waitFor で調整する
  7. 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

公式ドキュメントではこの打ち手は「カスタム仮想マシンサイズを使用する」として紹介されています:

その他参考:

こちらもマシンスペックを上げるとコストが上がるので、コスト増加分に注意が必要です。

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 でした。

また他にもよいものが見つかれば追加していきます。

参考


アバター
後藤隼人 ( ごとうはやと )

Python や PHP を使ってソフトウェア開発やウェブ制作をしています。詳しくはこちら