BazelでGoogle Cloud Storageをremote cacheとして設定する

投稿日:

このサイトの開発レポジトリではBazelでビルドを管理しています。

ビルド最適化の一環としてBazelのremote cacheを設定したので、ログを残しておきます。

キャッシュサーバの選択

https://docs.bazel.build/versions/master/remote-caching.html によれば、自前でキャッシュサーバを用意する方法と、GCPなどのマネージドサービスを利用する方法があるようです。

BazelはGoogleのプロジェクトだけに、デフォルトでGCPのcredentialsを用いて認証するオプションが付いていますので、これを用いるのが一番手っ取り早そうです。 (月数百円程度のコストは掛かってしまいますが)

自宅サーバが遊んでいればそっちを流用してみても良かったかも。

GCPの設定

キャッシュ用のストレージへのアクセス権限と鍵発行を担うアカウントを作成して、ストレージへ紐付けます。

Projectを作成

既存の関連Projectがなければ作成します。

Roleを作ってService Accountに紐付け

Remote cacheにはCloud Storageを使います。

その前にCloud StorageにアクセスするためのService Accountと、Accountに紐付けるRoleを用意します。

Remote cacheのためには、以下の3つの権限が付いていれば良いようです。

  • storage.objects.get
  • storage.objects.create
  • storage.objects.update

次にService Accountを作成して、先程作成したRoleを紐付けます。

Keyを作成

Service AccountからKeyを発行します。

Cloud StorageにBucketを作成

Bucketを作成します。objecgtにはBazelからしかアクセスしないので、Access ControlにはUniformedを設定します。

PERMISSIONSを追加

先程作成したService Accountを追加します。

LifyCycleを設定

キャッシュなのでいつまでも残しておく必要はありません。

Actionに Delete Object を選択して、conditionsの Age に適当な期間を入力します。 (私は30日で設定しています)

ローカルに設定

.bazelrcを設定

.bazelrc に、設定したBucketをremote cacheとして紐付けます。

run --remote_cache=https://storage.googleapis.com/your-bucket-name
run --google_default_credentials
build --remote_cache=https://storage.googleapis.com/your-bucket-name
build --google_default_credentials
test --verbose_failures --remote_cache=https://storage.googleapis.com/your-bucket-name
test --google_default_credentials

これでremote cacheの設定は完了です。

google_default_credentials はGoogle Cloudへアクセスする際の、 実行環境のデフォルトのService Accountをクレデンシャルとして用いる オプションです。 先程発行したKeyでgcloudコマンドから認証しておくことで、BazelがBucketへアクセス出来るようになります。

ただしこのためだけにgcloudコマンドをインストールするのも手間なので、以下のようにKeyを直接クレデンシャルとして設定することも可能です。

--- .bazelrc
+++ .bazelrc
@@ -1,5 +1,3 @@
+try-import %workspace%/dev.bazelrc

# user.bazelrc
run --nogoogle_default_credentials
build --nogoogle_default_credentials
test --nogoogle_default_credentials

run --google_credentials=secrets.json
build --google_credentials=secrets.json
test --google_credentials=secrets.json

ビルドしてみる

設定が正しいか確認してみましょう。

$ npx bazelisk build //...

設定に問題があれば、404系のエラーがログに表示されるはずです。 ビルドが完了したら、Bucketにobjectが出来ているかも確認できます。

GitHub Actionsに設定

最後にCI環境でremote cacheを設定します。 このサイトの 開発レポジトリではGitHub Actionsを使って いますのでそれに応じた作業ログになります。

Secretsに設定

gcloudの設定用actions が提供されているので、こちらを用います。

先程発行したKeyを適当なsecretsに設定して、actionからgcloudが認証出来るようにします。

# GitHub Actionsの設定
  - name: Set up Cloud SDK
    uses: google-github-actions/setup-gcloud@master
    with:
      project_id: "your-project-id"
      service_account_key: ${{ secrets.GCP_BAZEL_CACHE_KEY }}
      export_default_credentials: true

まとめ

以上で設定はすべて完了です。

月ごとの費用感 は数ドル~くらいのようです。

実はこのサイトの開発レポジトリくらいの規模感だと費用対効果はいまいちなのですが、別のレポジトリで各7~8分くらいのaction(がcommit毎に複数)が2~3分くらいにまで短縮されました。