Kustomize で Cloud Run をデプロイする
クラウドエースの北野です。
Cloud Run を GitHub Actions と Kustomize を使って管理する方法を紹介します。
概要
Kustomize を使い Cloud Run の構成情報を定義し、overlays の各環境のディレクトリで以下のコマンドを実行すると、Cloud Run をデプロイできます。
kustomize build . | gcloud run services replace --project <PROJECT ID> -
GitHub Actions で次のようなジョブを定義すると、GitHub Actions から Kustomize を使って Cloud Run をデプロイできます。
name: Deploy Cloud Run
on:
workflow_dispatch:
jobs:
deploy-cloudrun:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
defaults:
run:
working-directory: <DIRECTORY PATH>
steps:
- uses: actions/checkout@v2
- name: Authenticate to Google Cloud
id: authorizaation-googlecloud
uses: google-github-actions/auth@v1
with:
workload_identity_provider: ${{ vars.WORKLOADIDENTITY_PROVIDER_NAME }}
service_account: ${{ vars.WORKLOADIDENTITY_SERVICEACCOUNT_EMAIL }}
- name: cloudrun deploy
id: deploy-cloudrun
run: kustomize build . | gcloud run services replace --project ${{ vars.PROJECT_ID }} -
はじめに
Cloud Run は構成情報を YAML ファイルで定義でき、Cloud Run を構築する環境ごとにファイルを作成するとデプロイを一意に定義できます。
しかし、環境ごとに作成すると、すべてのファイルを管理しなければなりません。もし、Cloud Run の環境変数を追加したり、データベースへの接続方法を変えたりなど構成を大きく変えると、すべての構成ファイルを変更しなければなりません。開発環境のみ構成ファイルを変更し、他の環境の構成ファイルの変更を忘れ、本番環境などで Cloud Run が想定した挙動にならないということを見かけることがあります。
もし、各環境に構築する Cloud Run の構成情報で共通する部分をテンプレートなどで再利用できれば、こうした運用のミスの削減できると考えられます。
この記事では、Kustomize を使い Cloud Run の構成ファイルを管理し、共通部分を再利用する方法を紹介します。また、定義した構成ファイルを GitHub Actions からデプロイする方法も最後に紹介します。
Kustomize とは
Kustomize は Kubernetes マニフェストのカスタマイズをテンプレートやドメイン固有言語を使わずに行うツールです。マニフェストを複数の目的に合わせてカスタマイズできるため、base で共通部分のマニフェストを作り overlays で各環境に合わせてカスタマイズするという使い方が Kubernetes で広くされています。
Cloud Run の構成情報の YAML ファイルは、Kubernetes のマニフェストと同じ構造をしているため、Kustomize を使い定義することができます。
Kustomize から Cloud Run のデプロイ
次のような Cloud Run を Kustomize からデプロイします。
設定項目 | 値 |
---|---|
name | helloworld |
docker image | us-docker.pkg.dev/cloudrun/container/hello:sample-public-image-71cb7d367a8875eef4e0d1599b2046a8edfbb018f20d2e0c40fe0124fd5e3106 |
location | asia-northeast1 |
service account | デフォルトサービスアカウント |
Kustomize の base では、Cloud Run のリージョンを定義し、イメージのバージョンを latest とします。overlays でサービスアカウントとイメージバージョンを指定します。
以下で紹介する Terraform と Kustomize のコードの <>
で囲まれた部分は環境に合わせて読み替えてください。
ローカルからのデプロイ
ローカル環境から Cloud Run をデプロイしてみます。ディレクトリ構造を次のようにします。base の service.yaml に共通部分の構成情報を定義します。
tree
.
├── base
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
└── dev
├── kustomization.yaml
└── service.yaml
共通部分の kustomization.yaml と service.yaml は次の通りです。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
labels:
cloud.googleapis.com/location: asia-northeast1
spec:
template:
spec:
containers:
- name: helloworld
image: us-docker.pkg.dev/cloudrun/container/hello:latest
overlays でカスタマイズする構成ファイルは次の通りです。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- ./service.yaml
patchesJson6902:
- target:
kind: Service
name: helloworld
patch: |-
- op: replace
path: /spec/template/spec/containers/0/image
value: us-docker.pkg.dev/cloudrun/container/hello:sample-public-image-71cb7d367a8875eef4e0d1599b2046a8edfbb018f20d2e0c40fe0124fd5e3106
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
spec:
template:
spec:
serviceAccountName: <PROJECT NUMBER>-compute@developer.gserviceaccount.com
ビルドをしてデプロイされる構成定義を確認すると、base の定義からプロジェクトのデフォルトサービスアカウントが追加されているのと、sample-public-image-71cb7d367a8875eef4e0d1599b2046a8edfbb018f20d2e0c40fe0124fd5e3106 バージョンのイメージを使うようにカスタマイズされているのが分かるかと思います。
kustomize build .
# Warning: 'patchesJson6902' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
labels:
cloud.googleapis.com/location: asia-northeast1
name: helloworld
spec:
template:
spec:
containers:
- image: us-docker.pkg.dev/cloudrun/container/hello:sample-public-image-71cb7d367a8875eef4e0d1599b2046a8edfbb018f20d2e0c40fe0124fd5e3106
name: helloworld
serviceAccountName: <PROJECT NUMBER>-compute@developer.gserviceaccount.com
ここから実際に Kustomize を使って Cloud Run をデプロイします。デプロイの前に作成する helloworld の Cloud Run が存在しないことを確認します。
gcloud run services describe helloworld --region asia-northeast1 --project <PROJECT ID>
ERROR: (gcloud.run.services.describe) Cannot find service [helloworld]
Cloud Run がないことが確認できたので、以下のコマンドでデプロイして、Cloud Run が作成されることを確認します。
kustomize build . | gcloud run services replace --project <PROJECT ID> -
# Warning: 'patchesJson6902' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
Applying new configuration to Cloud Run service [helloworld] in project [<PROJECT ID>] region [asia-northeast1]
Deploying new service...
Creating Revision..............................................................................................................done
Routing traffic.....done
Done.
New configuration has been applied to service [helloworld].
URL: https://helloworld-<PROJECT NUMBER>.asia-northeast1.run.app
gcloud run services describe helloworld --region asia-northeast1 --project <PROJECT ID>
✔ Service helloworld in region asia-northeast1
URL: https://helloworld-<PROJECT NUMBER>.asia-northeast1.run.app
Ingress: all
Traffic:
100% LATEST (currently helloworld-00001-htt)
Scaling: Auto (Min: 0)
Last updated on 2025-03-27T07:22:33.269068Z by <GOOGLE ACCOUNT>:
Revision helloworld-00001-htt
Container helloworld
Image: us-docker.pkg.dev/cloudrun/container/hello:sample-public-image-71cb7d367a8875eef4e0d1599b2046a8edfbb018f20d2e0c40fe0124fd5e3106
Port: 8080
Memory: 512Mi
CPU: 1000m
Startup Probe:
TCP every 240s
Port: 8080
Initial delay: 0s
Timeout: 240s
Failure threshold: 1
Type: Default
Service account: <PROJECT NUMBER>-compute@developer.gserviceaccount.com
Concurrency: 80
Max instances: 100
Timeout: 300s
GitHub Actions からのデプロイ
最後に GitHub Actions からデプロイする CD パイプラインを紹介します。
Google Cloud の認証に Workload Identity を使います。Workload Identity を使い GitHub Actions を Google Cloud に認証させる詳細については、こちらの記事を確認ください。
Google Cloud の設定
Workload Identity を設定するため、Workload Identity Pool および、サービスアカウントを次のコードで作成します。
resource "google_iam_workload_identity_pool" "main" {
workload_identity_pool_id = <WORKLOAD IDENTITY POOL ID>
project = var.project
}
resource "google_iam_workload_identity_pool_provider" "main" {
workload_identity_pool_provider_id = <WORKLOAD IDENTITY PROVIDER ID>
workload_identity_pool_id = google_iam_workload_identity_pool.main.workload_identity_pool_id
project = var.project
attribute_condition = "assertion.repository == \"<GITHUB ORGANIZATION>/<GITHUB REPOSITORY NAME>\""
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.actor" = "assertion.actor"
"attribute.repository" = "assertion.repository"
}
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
}
resource "google_service_account" "main" {
account_id = <SERVICE ACCOUNT ID>
project = var.project
}
resource "google_service_account_iam_member" "main" {
service_account_id = google_service_account.main.name
role = "roles/iam.workloadIdentityUser"
member = format("principalSet://iam.googleapis.com/%s/%s", google_iam_workload_identity_pool.main.name, local.filter)
}
resource "google_project_iam_member" "main" {
project = var.project
role = "roles/editor"
member = google_service_account.main.member
}
GitHub 変数の設定
GitHub Actions で使う以下の変数を Terraform で定義します。
変数名 | 変数の内容 |
---|---|
PROJECT_ID | Cloud Run をデプロイする Google Cloud のプロジェクト ID |
WORKLOADIDENTITY_PROVIDER_NAME | Workload Identity のプロバイダ名 |
WORKLOADIDENTITY_SERVICEACCOUNT_EMAIL | サービスアカウントの email |
locals {
envs = [
{
name = "PROJECT_ID"
value = var.project
},
{
name = "WORKLOADIDENTITY_PROVIDER_NAME"
value = google_iam_workload_identity_pool_provider.main.name
},
{
name = "WORKLOADIDENTITY_SERVICEACCOUNT_EMAIL"
value = google_service_account.main.email
}
]
}
resource "github_actions_variable" "main" {
provider = github.aquamarinearia
for_each = { for v in local.envs : v.name => v }
variable_name = each.value.name
value = each.value.value
repository = data.github_repository.main.name
}
実行
次のワークフローを定義し GitHub Actions を実行させます。
name: Deploy Cloud Run
on:
workflow_dispatch:
jobs:
deploy-cloudrun:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
defaults:
run:
working-directory: <DIRECTORY PATH>
steps:
- uses: actions/checkout@v2
- name: Authenticate to Google Cloud
id: authorizaation-googlecloud
uses: google-github-actions/auth@v1
with:
workload_identity_provider: ${{ vars.WORKLOADIDENTITY_PROVIDER_NAME }}
service_account: ${{ vars.WORKLOADIDENTITY_SERVICEACCOUNT_EMAIL }}
- name: Deploy Cloud Run
id: deploy-cloudrun
run: kustomize build . | gcloud run services replace --project ${{ vars.PROJECT_ID }} -
<DIRECTORY PATH>
は overlays のパスを指定してください。実行すると次のように成功します。
さいごに
Cloud Run のデプロイに Kustomize を使う方法を紹介しました。環境変数が多い Cloud Run を運用している場合、この方法を適用すると運用ミスが減る可能性があるので、活用を検討してみてください。
Discussion