CircleCIを使っていてCloud Runが必要になったので設定したけど、いくつかハマったのでメモ
前提
この公式Orbsを使用する。
CircleCI Developer Hub - circleci/gcp-cloud-run
.circleci/config.ymlはこんな感じ。本番でなくステージング環境を作ってるので環境変数は変えてある。
version: 2.1
orbs:
gcp-cloud-run: circleci/gcp-cloud-run@1.0.2
jobs:
// 省略
deploy-cloud-run-staging:
docker:
- image: 'cimg/base:stable'
steps:
- checkout
- gcp-cloud-run/init:
gcloud-service-key: GCLOUD_SERVICE_KEY_STAGING
google-project-id: GOOGLE_PROJECT_ID_STAGING
- gcp-cloud-run/build:
config: ./cloudbuild.yml
GCPのプロジェクトでサービスアカウントを作り、キーやプロジェクトIDなどはCircleCIの環境変数に設定済み。
今回モノレポなプロジェクトでDockerfileの場所とコンテキストの場所が異なるけど、Orbの設定ではできなさそうだったので、cloudbuild.ymlが必要になった。
シンプルにビルド、プッシュ、デプロイの3アクション。
cloudbuild.yml
steps:
- id: "build the container image"
name: "gcr.io/cloud-builders/docker"
args: ["build", "-t", "gcr.io/${PROJECT_ID}/api-staging:${BUILD_ID}", "-f", "./Dockerfiles/api/Dockerfile", "."]
- id: "push container image"
name: "gcr.io/cloud-builders/docker"
args: ["push", "gcr.io/${PROJECT_ID}/api-staging:${BUILD_ID}"]
- id: "deploy to Cloud Run"
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args: ['run', 'deploy', 'api-staging', '--image', 'gcr.io/${PROJECT_ID}/api-staging:${BUILD_ID}', '--region', 'asia-northeast1']
Cloud Buildは成功しているのにCircleCIでエラー
ログを表示しようとしてるのにサービスアカウントに権限がなくてエラーになってる模様。
Uploading tarball of [.] to [gs://********************_cloudbuild/source/*****************.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/********************/locations/global/builds/*****************.].
Logs are available at [https://console.cloud.google.com/cloud-build/builds/*****************?project=************].
ERROR: (gcloud.builds.submit)
The build is running, and logs are being written to the default logs bucket.
This tool can only stream logs if you are Viewer/Owner of the project and, if applicable, allowed by your VPC-SC security policy.
The default logs bucket is always outside any VPC-SC security perimeter.
If you want your logs saved inside your VPC-SC perimeter, use your own bucket.
See https://cloud.google.com/build/docs/securing-builds/store-manage-build-logs.
Exited with code exit status 1
CircleCI received exit code 1
よく読むと答えが書いてあり
This tool can only stream logs if you are Viewer/Owner of the project
プロジェクトのオーナーか参照の権限をサービスアカウントに追加が必要。もちろん参照でいいので追加して解決。
Cloud Buildのログを出すだけなのに、プロジェクト全体が必要とはちょっと大げさな権限だなぁ。
Cloud Runにデプロイ時に権限かサービスがなくてエラー1
Step #2 - "deploy to Cloud Run": gcr.io/google.com/cloudsdktool/cloud-sdk:latest
Step #2 - "deploy to Cloud Run": ERROR: (gcloud.run.deploy) PERMISSION_DENIED: Permission 'run.services.get' denied on resource 'namespaces/********************/services/api-staging' (or resource may not exist).
Finished Step #2 - "deploy to Cloud Run"
ERROR
ERROR: build step 2 "gcr.io/google.com/cloudsdktool/cloud-sdk" failed: step exited with non-zero status: 1
BUILD FAILURE: Build step failure: build step 2 "gcr.io/google.com/cloudsdktool/cloud-sdk" failed: step exited with non-zero status: 1
ERROR: (gcloud.builds.submit) build bc02f3af-d341-4af1-98cb-0e2d396078a4 completed with status "FAILURE"
単純に最初なのでCloud Runのサービスが存在しない。
最初は手作業でサービス作って解決、と思ったらだめだった。
こちらを参考にCloud BuildのサービスアカウントにCloud RunのAdminをつけて解決するはず、と思ったらだめだった。
stackoverflow.com
Cloud Runにデプロイ時に権限かサービスがなくてエラー2
1をやったらエラーが変わった。
Step #2 - "deploy to Cloud Run": ERROR: (gcloud.run.deploy) PERMISSION_DENIED: Permission 'iam.serviceaccounts.actAs' denied on service account *****-compute@developer.gserviceaccount.com (or it may not exist).
ググると解決策が出てくるけどiam.serviceaccounts.actAs
が見つからない。
stackoverflow.com
ロール作成画面でフィルタするも出てこないのでiamだけでフィルタし、ページ送りしまくったらやっとみつかったので、カスタムロールを作成。
Cloud Buildでイメージのタグにコミットハッシュが使えなくてエラー
昔作った設定を参考に、イメージのバージョンに$COMMIT_SHAなどを使っていたけど、今回はGitレポジトリのフックではなくコマンド経由なせいか存在せず、空白になってしまいエラー。
Already have image (with digest): gcr.io/cloud-builders/docker
invalid argument "gcr.io/*****api-staging:" for "-t, --tag" flag: invalid reference format
See 'docker build --help'.
Substituting variable values | Cloud Build Documentation | Google Cloud
にある通り、絶対に使えるのは下記3つだけで、ビルドごとに異なるのはBuild IDだけなので必然的にそれを使うことにして解決。
$PROJECT_ID: Cloud プロジェクトの ID
$BUILD_ID: ビルドの ID
$PROJECT_NUMBER: プロジェクトの番号