🐕

Cloud Build で Firebase のリソースをデプロイする

に公開

やりたいこと

Firebaseのプロダクトを管理する上で、1つ考慮しなければならないのが、rulesやindexといったインフラリソースの管理です。

リリース前は本番環境のrule更新もCLIで手動実行してもそれほど問題はありませんが、サービスインした後だと本番環境におかしな設定をデプロイしてしまったときの損害が大きくなるため、CI/CDで安全にデプロイするようにしたいです。

今回はCloud Buildを使って、GitHub上のmainブランチにpushがあったら、自動でそれらのインフラリソースがデプロイされるようにします。

Cloud Build Triggerの作成

開発・本番の2環境あるため、環境差異が出ないようにTerraformでCloud Build Triggerを作成します。今回は以下のドキュメントを参考にさせていただきました。

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloudbuild_trigger

https://zenn.dev/wataru777/articles/c9aa1c09bf51b4

なお、Cloud Buildのアップデートに伴い、プロジェクトの作成時期によって挙動が異なるため、サービスアカウントも別途新規に作成しています。

今回はFirebaseのリソースを操作するため、roles/firebase.adminの権限をtriggerで使用するアカウントに付与しています。

resource "google_project_iam_member" "firebase_admin" {
  project = var.project_id
  role    = "roles/firebase.admin"
  member  = "serviceAccount:${google_service_account.cloudbuild_service_account.email}"
}

Firebase CLIをCloud Buildで実行する準備

Cloud BuildでFirebase CLIツールの操作を行うためには、Firebase CLIをDockerイメージとしてArtifact Registryにpushする必要があります。

https://cloud.google.com/build/docs/deploying-builds/deploy-firebase

基本的にはこのドキュメントの流れに沿う形ですが、いくつか落とし穴がありました。

まず、Windowsでgit cloneを実行すると、改行コードがLFからCRLFに変わってしまうため、shファイルが実行できなくなる可能性があります。

Windowsユーザーは改行コードを書き換えないようにautocrlfを無効化してください。この挙動については公式ドキュメントには記載はありませんが、GitHub側には注意書きがあります。

git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git --config core.autocrlf=false

次はcloud buildを実行してArtifact Registryにpushするプロセスですが、実行されるコマンドを見ると最終的にUSリージョンにpushされるようになっています。

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/firebase', '.']
images:
- 'gcr.io/$PROJECT_ID/firebase'
tags: ['cloud-builders-community']

普段からUSリージョンを使っているという場合は問題ありませんが、アジアやヨーロッパのリージョンをcloud buildなど他のリソースで使っている場合は、リージョン間通信で追加コストが発生する可能性があります。

このプロジェクトでもGDPR対応のためにUS以外のリージョンに各種リソースを置いているので、今回はcloudbuild.yamlを使わずに手動でArtifact Registryにpushすることにしました。

まず、Artifact RegistryにRepositoryを作成します。

gcloud artifacts repositories create firebase \
  --repository-format=docker \
  --location=asia-northeast1 \
  --description="Firebase CLI Docker image"

次に、firebaseのDockerイメージをローカルでビルドします。

cloneしたcloud buildのリポジトリに移動してから、

cd cloud-builders-community/firebase

docker buildコマンドを実行します。

docker build -t asia-northeast1-docker.pkg.dev/{you_project_id}/firebase/firebase .

ローカルにイメージは作成されましたが、手動でArtifact Registryにpushする場合は、Dockerレジストリに対するDockerの認証情報を設定するために以下のコマンドを実行する必要があります。

https://stackoverflow.com/questions/72251787/permission-artifactregistry-repositories-downloadartifacts-denied-on-resource

gcloud auth configure-docker asia-northeast1-docker.pkg.dev

このコマンドを実行すると、~/.docker/config.jsonに以下のような設定が追加されます。

{
  "credHelpers": {
    "asia-northeast1-docker.pkg.dev": "gcloud"
  }
}

これで認証は通ったので、Artifact registryにpushします。

docker push asia-northeast1-docker.pkg.dev/{your_project_id}/firebase/firebase:latest

問題なくpushすれば準備は完了です。最後に、cloud buildで使用するyamlもnameの部分をドキュメントのサンプルコードから修正します。


steps:
  - name: asia-northeast1-docker.pkg.dev/$PROJECT_ID/firebase/firebase
    args: 
      - 'deploy'
      - '--project=$PROJECT_ID'
      - '--only=firestore:rules'

timeout: 540s
options:
  logging: CLOUD_LOGGING_ONLY

あとは、前述のCloud build triggerと組み合わせることで、mainブランチにマージすると自動でデプロイされるようになります。

もちろん、デプロイ前にローカルでcloud buildの動作確認を行うこともできます。トリガーと同じサービスアカウントで実行するための指定オプションがやや特殊な書き方になっている点に注意してください。


gcloud builds submit \
  --region=asia-northeast1 \
  --service-account projects/{your_project_id}/serviceAccounts/cloud-build-common-sa@{your_project_id}.iam.gserviceaccount.com \
  --config cloudbuild__firebase.yaml \
  .

GitHub Actionsでももちろん同じことは実現可能ですが、認証キーの払い出しなどを行わなくて済むので、Cloud Buildを使う方が管理がシンプルになりました。

Discussion