Cloud Deploy を使って Cloud Run サービスを dev → stg → prod の順にプロモートしてみた

Cloud Deploy を使って Cloud Run サービスを dev → stg → prod の順にプロモートしてみた

2026.06.25

はじめに

こんにちは。
クラウド事業本部コンサルティング部の渡邉です。

アプリケーションを複数環境(開発・ステージング・本番)へ段階的にリリースする際、デプロイ手順を標準化しつつ安全に進めることが重要です。Google Cloud Deploy は、Cloud Run をはじめとするランタイムへの継続的デリバリーをフルマネージドで提供するサービスです。

本記事では、Cloud Deploy を使って Cloud Run サービスを dev → stg → prod の順にプロモート(昇格)する手順を検証します。実際のユースケースに即して、環境ごとに独立した Google Cloud プロジェクトを使う構成を採用し、prod 環境へのプロモートには 手動承認 を設けることで、意図しない本番デプロイを防ぐ構成も合わせてご紹介します。

Cloud Deploy とは

Cloud Deploy は、GKE・Cloud Run などへのデプロイを一元管理するフルマネージドの継続的デリバリー(CD)サービスです。CI ツール(Cloud Build・GitHub Actions など)がコンテナイメージをビルドした後、そのイメージを複数環境へ段階的にデプロイする CD の部分を担当 します。

主な機能

機能 概要
デリバリーパイプライン デプロイ先ターゲットを順序付きで定義し、リリースを段階的にプロモート
承認フロー 特定のターゲットへのプロモート前に手動承認を要求できる
ロールバック 前のリリースへワンステップで戻せる
カナリアデプロイ 新バージョンへのトラフィックを段階的に移行できる
監査ログ Cloud Audit Logs と連携し、誰がいつ何をデプロイしたかを追跡可能
パイプライン可視化 コンソール上でリリースの進捗をグラフィカルに確認できる

主要コンセプト

Cloud Deploy を理解するうえで重要な用語を整理します。

用語 説明
Delivery Pipeline(デリバリーパイプライン) デプロイ先ターゲットの昇格順序(Progression)を定義するリソース。clouddeploy.yaml に記述する
Target(ターゲット) デプロイ先のランタイム環境(Cloud Run サービスや GKE クラスタなど)の定義。同一プロジェクト内に置くが、デプロイ先は別プロジェクト・別リージョンも可能
Release(リリース) デプロイするコンテナイメージと設定を表す Cloud Deploy リソース。CI 完了後に gcloud deploy releases create で作成し、最初のターゲットへの自動デプロイが始まる
Rollout(ロールアウト) リリースと特定ターゲットを紐づけるリソース。プロモートのたびに1つ作成される。3ターゲット構成では1リリースにつき3つのロールアウトが生成される
Progression(プログレッション) パイプライン内のターゲット昇格順序の定義。例: dev → stg → prod
Promotion(プロモート) リリースを次のターゲットへ昇格させる操作。gcloud deploy releases promote で実行する

CI/CD パイプラインにおける Cloud Deploy の位置づけ

[CI フェーズ]                   [CD フェーズ: Cloud Deploy]
┌─────────────────┐            ┌────────────────────────────────────┐
│ コード変更       │            │                                    │
│ ↓               │            │  Release 作成                      │
│ テスト実行       │            │  └→ dev へ自動デプロイ(Rollout①) │
│ ↓               │            │       ↓ promote                    │
│ コンテナイメージ  │ ──────→   │      stg へデプロイ(Rollout②)    │
│ のビルド & Push  │            │       ↓ promote + 承認             │
│                 │            │      prod へデプロイ(Rollout③)   │
└─────────────────┘            └────────────────────────────────────┘

Cloud Deploy では、同一のコンテナイメージが dev から prod まで昇格します。環境ごとにビルドを行わないため、dev で動作確認したイメージがそのまま prod に届くことが保証されます。

Cloud Deploy は内部で Skaffold を使用し、Cloud Run サービス定義 YAML のレンダリングとデプロイを行います。

検証シナリオ

本記事では、以下の4プロジェクト構成で検証します。

プロジェクト 役割
DEPLOY_PROJECT Cloud Deploy のパイプライン・ターゲット・リリースを管理する
DEV_PROJECT dev 環境の Cloud Run サービスをホストする
STG_PROJECT stg 環境の Cloud Run サービスをホストする
PROD_PROJECT prod 環境の Cloud Run サービスをホストする

アーキテクチャ全体像は以下のとおりです。

Cloud Deploy の主なメリットは、同一のコンテナイメージをビルドなしで各環境へプロモートする点です。dev で動作確認したイメージがそのまま prod へ昇格するため、環境間での差異を排除できます。

実際に試してみる

前提条件

  • 4つの Google Cloud プロジェクト(DEPLOY / DEV / STG / PROD)が作成済みであること
  • gcloud CLI がインストール・認証済みであること
  • 各プロジェクトに対して請求が有効になっていること

0. 環境変数の設定

export DEPLOY_PROJECT_ID="your-deploy-project-id"
export DEV_PROJECT_ID="your-dev-project-id"
export STG_PROJECT_ID="your-stg-project-id"
export PROD_PROJECT_ID="your-prod-project-id"
export REGION="asia-northeast1"
export ARTIFACT_REPO="cloud-run-demo"
export SA_NAME="cloud-deploy-runner"

1. API の有効化

DEPLOY_PROJECT で Cloud Deploy と関連 API を有効化します。

gcloud services enable clouddeploy.googleapis.com run.googleapis.com \
  artifactregistry.googleapis.com cloudbuild.googleapis.com \
  --project=${DEPLOY_PROJECT_ID}

Operation "operations/acf.p2-xxxxxxxxxxxx-d05efe55-7875-402e-aca8-f1d8744ef194" finished successfully.

各ターゲットプロジェクトで Cloud Run API を有効化します。

for PROJECT in ${DEV_PROJECT_ID} ${STG_PROJECT_ID} ${PROD_PROJECT_ID}; do
  gcloud services enable run.googleapis.com --project=$PROJECT
done

Operation "operations/acf.p2-xxxxxxxxxxxx-4bba08d0-fa41-4201-b5b3-c9ee9227506c" finished successfully.
Operation "operations/acf.p2-xxxxxxxxxxxx-b68bba8d-5a26-4840-9265-d7c8604cc271" finished successfully.
Operation "operations/acf.p2-xxxxxxxxxxxx-3dd5efc6-6dab-492d-b875-68a3e6b98ddd" finished successfully.

2. 専用サービスアカウントの作成と IAM ロールの付与

Cloud Deploy の実行にはデフォルトで Compute Engine デフォルト サービスアカウントが使われますが、専用の実行サービスアカウントを作成することがベストプラクティスです。最小権限の原則に従い、このパイプライン専用の サービスアカウント を DEPLOY_PROJECT に作成します。

gcloud iam service-accounts create cloud-deploy-runner \
  --display-name="Cloud Deploy Runner for cloud-run-demo-pipeline" \
  --project=${DEPLOY_PROJECT_ID}

Created service account [cloud-deploy-runner].

cloud-deploy-runner SA 作成確認
cloud-deploy-runner サービスアカウントが DEPLOY_PROJECT に作成された

作成した SA(cloud-deploy-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com)に対して、必要な IAM ロールを付与します。

IAM ロールを付与する前に、コンテナイメージを格納する Artifact Registry リポジトリを作成します。

gcloud artifacts repositories create ${ARTIFACT_REPO} \
  --repository-format=docker \
  --location=${REGION} \
  --project=${DEPLOY_PROJECT_ID}

Create request issued for: [cloud-run-demo]
Waiting for operation [projects/your-deploy-project-id/locations/asia-northeast1/operations/a130205f-dc99-44ce-a4b8-03c20bfc23fc] to complete...done.
Created repository [cloud-run-demo].

Artifact Registry リポジトリ作成確認
Artifact Registry リポジトリ cloud-run-demo が Docker 形式で作成された(asia-northeast1)

DEPLOY_PROJECT への付与(レンダリング・デプロイ実行権限)

# Cloud Deploy 実行権限
gcloud projects add-iam-policy-binding ${DEPLOY_PROJECT_ID} \
  --member="serviceAccount:cloud-deploy-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/clouddeploy.jobRunner"

# Artifact Registry 読み取り権限(Cloud Run へのデプロイ時にイメージの存在確認に必要)
gcloud artifacts repositories add-iam-policy-binding ${ARTIFACT_REPO} \
  --location=${REGION} \
  --project=${DEPLOY_PROJECT_ID} \
  --member="serviceAccount:cloud-deploy-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/artifactregistry.reader"

DEPLOY_PROJECT IAM 権限確認
DEPLOY_PROJECT の IAM 権限。cloud-deploy-runnerroles/clouddeploy.jobRunner(Cloud Deploy ランナー)が付与されている

次に、コンテナイメージのビルド専用サービスアカウント cloud-build-runner を作成します。Cloud Build(CI)と Cloud Deploy(CD)の権限を分離することで、最小権限の原則をより厳密に実現できます。

gcloud iam service-accounts create cloud-build-runner \
  --display-name="Cloud Build Runner for cloud-run-demo" \
  --project=${DEPLOY_PROJECT_ID}

Created service account [cloud-build-runner].

cloud-build-runner SA 作成確認
cloud-build-runner サービスアカウントが DEPLOY_PROJECT に作成された

cloud-build-runner SA に必要なロールを付与します。

# Cloud Build 実行権限
gcloud projects add-iam-policy-binding ${DEPLOY_PROJECT_ID} \
  --member="serviceAccount:cloud-build-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/cloudbuild.builds.builder"

# Artifact Registry への書き込み権限
gcloud projects add-iam-policy-binding ${DEPLOY_PROJECT_ID} \
  --member="serviceAccount:cloud-build-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/artifactregistry.writer"

cloud-build-runner IAM 権限確認
DEPLOY_PROJECT の IAM 権限。cloud-build-runnerroles/cloudbuild.builds.builder(Cloud Build サービス アカウント)と roles/artifactregistry.writer(Artifact Registry 書き込み)が付与されている

各ターゲットプロジェクトへの付与

専用 SA が各ターゲットプロジェクトの Cloud Run へデプロイできるように、3プロジェクトそれぞれにロールを付与します。

for PROJECT in ${DEV_PROJECT_ID} ${STG_PROJECT_ID} ${PROD_PROJECT_ID}; do
  # Cloud Run Developer ロール
  gcloud projects add-iam-policy-binding $PROJECT \
    --member="serviceAccount:cloud-deploy-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/run.developer"

  # IAM Service Account User ロール
  gcloud projects add-iam-policy-binding $PROJECT \
    --member="serviceAccount:cloud-deploy-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"
done

ターゲットプロジェクト IAM 権限確認
ターゲットプロジェクト(DEV/STG/PROD)の IAM 権限。cloud-deploy-runnerroles/run.developer(Cloud Run デベロッパー)と roles/iam.serviceAccountUser(サービス アカウント ユーザー)が付与されている

Artifact Registry へのクロスプロジェクトアクセス権の付与

Cloud Run サービスが起動する際、コンテナイメージを pull するのは Cloud Run Service Agentservice-PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com)です。イメージは DEPLOY_PROJECT の Artifact Registry にあるため、各ターゲットプロジェクトの Cloud Run Service Agent に対してクロスプロジェクトの読み取り権限を付与します。

for PROJECT in ${DEV_PROJECT_ID} ${STG_PROJECT_ID} ${PROD_PROJECT_ID}; do
  PROJECT_NUMBER=$(gcloud projects describe ${PROJECT} --format='value(projectNumber)')
  gcloud artifacts repositories add-iam-policy-binding ${ARTIFACT_REPO} \
    --location=${REGION} \
    --project=${DEPLOY_PROJECT_ID} \
    --member="serviceAccount:service-${PROJECT_NUMBER}@serverless-robot-prod.iam.gserviceaccount.com" \
    --role="roles/artifactregistry.reader"
done

付与した権限を整理すると以下のとおりです。

SA ロール付与先 ロール 目的
cloud-build-runner DEPLOY_PROJECT roles/cloudbuild.builds.builder Cloud Build 実行
cloud-build-runner DEPLOY_PROJECT roles/artifactregistry.writer イメージのプッシュ
cloud-deploy-runner DEPLOY_PROJECT roles/clouddeploy.jobRunner Cloud Deploy 実行
cloud-deploy-runner DEPLOY_PROJECT(Artifact Registry) roles/artifactregistry.reader デプロイ時のイメージ存在確認
cloud-deploy-runner DEV/STG/PROD_PROJECT roles/run.developer Cloud Run へのデプロイ
cloud-deploy-runner DEV/STG/PROD_PROJECT roles/iam.serviceAccountUser Cloud Run 実行 SA の借用
Cloud Run Service Agent(各ターゲット) DEPLOY_PROJECT(Artifact Registry) roles/artifactregistry.reader Cloud Run 起動時のイメージ pull

3. 作業ディレクトリと各種ファイルの準備

mkdir cloud-deploy-cloud-run-promotion && cd cloud-deploy-cloud-run-promotion

tree
.
├── app
   ├── Dockerfile
   ├── main.py
   └── requirements.txt
├── deploy
    ├── clouddeploy.yaml
    ├── run-service.yaml
    └── skaffold.yaml

4. Cloud Run サービス定義ファイルの作成

プロジェクトを環境ごとに分けているため、各プロジェクト内のサービス名は統一できます。ファイルは1つで構いません。

run-service.yaml

run-service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: demo-app
spec:
  template:
    spec:
      containers:
      - image: demo-app-image

demo-app-image はプレースホルダーで、リリース作成時に --images フラグで実際のイメージに置き換えられます。

5. Skaffold 設定ファイルの作成

プロファイル不要のシンプルな構成です。

skaffold.yaml

skaffold.yaml
apiVersion: skaffold/v4beta7
kind: Config
metadata:
  name: cloud-run-demo
manifests:
  rawYaml:
  - run-service.yaml
deploy:
  cloudrun: {}

6. Cloud Deploy パイプラインとターゲットの定義

各ターゲットの run.location に異なるプロジェクト ID を指定します。また executionConfigs で専用 SA を指定します。

clouddeploy.yaml

clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: cloud-run-demo-pipeline
description: Cloud Run demo delivery pipeline (dev -> stg -> prod)
serialPipeline:
  stages:
  - targetId: dev
  - targetId: stg
  - targetId: prod
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: dev
description: Development environment
executionConfigs:
- defaultPool:
    serviceAccount: cloud-deploy-runner@DEPLOY_PROJECT_ID.iam.gserviceaccount.com
  usages:
  - RENDER
  - DEPLOY
run:
  location: projects/DEV_PROJECT_ID/locations/REGION
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: stg
description: Staging environment
executionConfigs:
- defaultPool:
    serviceAccount: cloud-deploy-runner@DEPLOY_PROJECT_ID.iam.gserviceaccount.com
  usages:
  - RENDER
  - DEPLOY
run:
  location: projects/STG_PROJECT_ID/locations/REGION
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: prod
description: Production environment
requireApproval: true
executionConfigs:
- defaultPool:
    serviceAccount: cloud-deploy-runner@DEPLOY_PROJECT_ID.iam.gserviceaccount.com
  usages:
  - RENDER
  - DEPLOY
run:
  location: projects/PROD_PROJECT_ID/locations/REGION

executionConfigs.defaultPool.serviceAccount で専用 SA を指定しています。requireApproval: true を設定した prod ターゲットへのプロモートは、承認が行われるまで保留状態になります。

7. パイプラインとターゲットの登録

パイプラインとターゲットの定義を DEPLOY_PROJECT に登録します。

gcloud deploy apply --file=clouddeploy.yaml \
  --region=${REGION} \
  --project=${DEPLOY_PROJECT_ID}

Waiting for the operation on resource projects/your-deploy-project-id/locations/asia-northeast1/deliveryPipelines/cloud-run-demo-pipeline...done.                                                         
Created Cloud Deploy resource: projects/your-deploy-project-id/locations/asia-northeast1/deliveryPipelines/cloud-run-demo-pipeline.
Waiting for the operation on resource projects/your-deploy-project-id/locations/asia-northeast1/targets/dev...done.                                                                                       
Created Cloud Deploy resource: projects/your-deploy-project-id/locations/asia-northeast1/targets/dev.
Waiting for the operation on resource projects/your-deploy-project-id/locations/asia-northeast1/targets/stg...done.                                                                                       
Created Cloud Deploy resource: projects/your-deploy-project-id/locations/asia-northeast1/targets/stg.
Waiting for the operation on resource projects/your-deploy-project-id/locations/asia-northeast1/targets/prod...done.                                                                                      
Created Cloud Deploy resource: projects/your-deploy-project-id/locations/asia-northeast1/targets/prod.

コンソールの「Delivery pipelines」ページでパイプラインが作成されたことを確認します。

デリバリーパイプライン一覧
Cloud Deploy コンソールのデリバリーパイプライン一覧。cloud-run-demo-pipeline が登録され、dev・stg・prod の 3 ターゲットが確認できる

パイプライン詳細画面
パイプライン詳細画面。dev → stg → prod の Progression が視覚的に表示される

8. コンテナイメージのビルドとプッシュ

リリース作成前に、デプロイするコンテナイメージをビルドして Artifact Registry へプッシュします。

# Cloud Build でビルド & プッシュ
IMAGE_TAG="${REGION}-docker.pkg.dev/${DEPLOY_PROJECT_ID}/cloud-run-demo/demo-app:release-001"
gcloud builds submit ./app \
  --tag="${IMAGE_TAG}" \
  --project=${DEPLOY_PROJECT_ID} \
  --region=${REGION} \
  --service-account="projects/${DEPLOY_PROJECT_ID}/serviceAccounts/cloud-build-runner@${DEPLOY_PROJECT_ID}.iam.gserviceaccount.com" \
  --default-buckets-behavior=regional-user-owned-bucket

Artifact Registry イメージ確認
Artifact Registry に demo-app:release-001(46.9 MB)が push されたことを確認

9. リリースの作成(dev へのデプロイ)

リリースを作成すると、Cloud Deploy は自動的にパイプラインの 最初のターゲット(dev) へデプロイします。

gcloud deploy releases create release-001 \
  --project=${DEPLOY_PROJECT_ID} \
  --region=${REGION} \
  --delivery-pipeline=cloud-run-demo-pipeline \
  --images=demo-app-image=${REGION}-docker.pkg.dev/${DEPLOY_PROJECT_ID}/cloud-run-demo/demo-app:release-001

Creating temporary archive of %s file(s) totalling %s before compression. 3 1.5 KiB
Uploading tarball of [/home/xxxxxxxxx/repo/google-cloud-lab/cloud-deploy-cloud-run-promotion/deploy] to [gs://566f48777ff34d9c9c33e0fa56844107_clouddeploy/source/1782336858.686549-5534ae8c45564767bc8e4044cd199cce.tgz]
Waiting for operation [operation-1782336861837-65506a3851a26-5247859e-9abfeba8]...done.                                                                                                             
Created Cloud Deploy release release-001.
Creating rollout projects/your-deploy-project-id/locations/asia-northeast1/deliveryPipelines/cloud-run-demo-pipeline/releases/release-001/rollouts/release-001-to-dev-0001 in target dev
Waiting for rollout creation operation to complete...done.

dev デプロイ開始
リリース作成直後の状態。dev ターゲットへのロールアウト(release-001-to-dev-0001)が自動的に開始されている

dev デプロイ成功
dev へのデプロイが成功。「正しくデプロイされました」と表示され、「プロモート」ボタンから stg への昇格が可能になった

DEV_PROJECT の Cloud Run サービス一覧に demo-app が表示されていれば成功です。

gcloud run services list --region=${REGION} --project=${DEV_PROJECT_ID}

   SERVICE   REGION           URL                                                    LAST DEPLOYED BY                                              LAST DEPLOYED AT
  demo-app  asia-northeast1  https://demo-app-xxxxxxxxxxxx.asia-northeast1.run.app  cloud-deploy-runner@your-deploy-project-id.iam.gserviceaccount.com  2026-06-24T21:35:12.797401Z

DEV Cloud Run サービス確認
DEV_PROJECT の Cloud Run サービス一覧。demo-app が正常にデプロイされていることを確認

10. stg へのプロモート

dev へのデプロイが完了したら、stg へプロモートします。

gcloud deploy releases promote \
  --release=release-001 \
  --delivery-pipeline=cloud-run-demo-pipeline \
  --region=${REGION} \
  --project=${DEPLOY_PROJECT_ID}

Promoting release release-001 to target stg.

Do you want to continue (Y/n)?  y

Creating rollout projects/your-deploy-project-id/locations/asia-northeast1/deliveryPipelines/cloud-run-demo-pipeline/releases/release-001/rollouts/release-001-to-stg-0001 in target stg
Waiting for rollout creation operation to complete...done.

--to-target を省略すると、プロモーションシーケンスの次のターゲット(stg)へ自動的にプロモートされます。

stg デプロイ開始
stg へのプロモート後。stg ターゲットでロールアウトが進行中の状態

stg デプロイ成功
stg へのデプロイが成功。「正しくデプロイされました」と表示された

STG_PROJECT に demo-app が作成されていることを確認します。

gcloud run services list --region=${REGION} --project=${STG_PROJECT_ID}

   SERVICE   REGION           URL                                                    LAST DEPLOYED BY                                              LAST DEPLOYED AT
  demo-app  asia-northeast1  https://demo-app-xxxxxxxxxxxx.asia-northeast1.run.app  cloud-deploy-runner@your-deploy-project-id.iam.gserviceaccount.com  2026-06-24T21:39:23.119074Z

STG Cloud Run サービス確認
STG_PROJECT の Cloud Run サービス一覧。demo-app が正常にデプロイされていることを確認

11. prod へのプロモートと承認

stg へのデプロイが完了したら、prod へプロモートします。

gcloud deploy releases promote \
  --release=release-001 \
  --delivery-pipeline=cloud-run-demo-pipeline \
  --region=${REGION} \
  --project=${DEPLOY_PROJECT_ID} \
  --rollout-id=rollout-to-prod-001

Promoting release release-001 to target prod.

Do you want to continue (Y/n)?  y

Creating rollout projects/your-deploy-project-id/locations/asia-northeast1/deliveryPipelines/cloud-run-demo-pipeline/releases/release-001/rollouts/rollout-to-prod-001 in target prod
Waiting for rollout creation operation to complete...done.                                                                                                                                          
The rollout is pending approval.

prod 承認待ち状態
prod ターゲットへのプロモートが保留中。stg → prod 間に「確認」ボタンが表示され、承認待ち状態を視覚的に確認できる

prod ターゲットには requireApproval: true が設定されているため、ロールアウトは 承認待ち(Pending Approval) 状態になります。

承認はコンソールまたは gcloud CLI で行えます。

コンソールでの承認

  1. コンソールの「Delivery pipelines」ページを開き、パイプラインをクリック
  2. prod ターゲットに「確認」リンクが表示されるのでクリック
  3. マニフェストの差分を確認し「Approve」をクリック

prod ロールアウト承認画面(概要)
prod ロールアウトの承認画面(概要タブ)。リリース名・タイミング・デプロイアーティファクトなどの情報を確認したうえで承認できる

prod ロールアウト承認画面(マニフェスト差分)
承認画面の「マニフェストの差分」タブ。デプロイされる Cloud Run サービス定義 YAML を事前に確認できる

gcloud CLI での承認

gcloud deploy rollouts approve rollout-to-prod-001 \
  --delivery-pipeline=cloud-run-demo-pipeline \
  --release=release-001 \
  --region=${REGION} \
  --project=${DEPLOY_PROJECT_ID}

承認後、PROD_PROJECT の Cloud Run に demo-app サービスがデプロイされます。

prod デプロイ開始
承認後、prod ターゲットへのデプロイが開始。prod のステータスが「stable」に移行した

パイプライン全体完了
dev・stg・prod すべてのターゲットに release-001 がデプロイされ、パイプライン全体が完了した状態

gcloud run services list --region=${REGION} --project=${PROD_PROJECT_ID}

   SERVICE   REGION           URL                                                    LAST DEPLOYED BY                                              LAST DEPLOYED AT
  demo-app  asia-northeast1  https://demo-app-309275480917.asia-northeast1.run.app  cloud-deploy-runner@your-deploy-project-id.iam.gserviceaccount.com  2026-06-24T21:45:31.558859Z

PROD Cloud Run サービス確認
PROD_PROJECT の Cloud Run サービス一覧。demo-app が正常にデプロイされていることを確認

デプロイの自動化

ここまで gcloud deploy releases promote を手動実行しましたが、Cloud Deploy のネイティブ機能や CI ツールと組み合わせることで、リリース作成からプロモートまでを自動化できます。

Cloud Deploy Automation 機能

Cloud Deploy には、プロモートや失敗時のリトライを自動化する Automation リソースが組み込まれています。別のツールなしに clouddeploy.yaml に定義を追記するだけで有効になります。

ルール 動作
promoteReleaseRule 特定ターゲットへのデプロイ成功後、自動的に次のターゲットへプロモート
timedPromoteReleaseRule cron スケジュールに基づいてプロモート(例: 毎週月曜 9:00)
repairRolloutRule デプロイ失敗時に自動リトライ、リトライ上限到達後は自動ロールバック

以下は dev → stg を成功後に自動プロモートする Automation の設定例です。prodrequireApproval: true のままにしておくことで、dev→stg は自動、stg→prod は手動承認という構成を Cloud Deploy だけで実現できます。

# clouddeploy.yaml に追記する
apiVersion: deploy.cloud.google.com/v1
kind: Automation
metadata:
  name: cloud-run-demo-pipeline/promote-dev-to-stg
description: dev へのデプロイ成功後、stg へ自動プロモート
serviceAccount: cloud-deploy-runner@DEPLOY_PROJECT_ID.iam.gserviceaccount.com
selector:
  targets:
  - id: dev
rules:
- promoteReleaseRule:
    id: promote-release
    wait: 1m          # デプロイ成功後 1 分待機してからプロモート
    destinationTargetId: "@next"

スケジュール実行が必要なケース(例: 毎週木曜深夜に stg → prod を自動プロモート)では timedPromoteReleaseRule を使います。

apiVersion: deploy.cloud.google.com/v1
kind: Automation
metadata:
  name: cloud-run-demo-pipeline/timed-promote-stg-to-prod
description: 毎週木曜 23:00 JST に stg → prod へ自動プロモート
serviceAccount: cloud-deploy-runner@DEPLOY_PROJECT_ID.iam.gserviceaccount.com
selector:
  targets:
  - id: stg
rules:
- timedPromoteReleaseRule:
    id: timed-promote-release
    schedule: "0 14 * * 4"   # UTC 14:00 = JST 23:00 の木曜
    timeZone: "UTC"
    destinationTargetId: "@next"

Cloud Build との連携

リリース作成(gcloud deploy releases create)は CI の最終ステップとして呼び出すのが一般的です。以下は Cloud Build でコンテナイメージをビルドし、Cloud Deploy のリリースを作成する cloudbuild.yaml の例です。

# cloudbuild.yaml
steps:
  # コンテナイメージのビルド
  - name: gcr.io/cloud-builders/docker
    args:
      - build
      - -t
      - REGION-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/demo-app:$COMMIT_SHA
      - ./app

  # Artifact Registry へプッシュ
  - name: gcr.io/cloud-builders/docker
    args:
      - push
      - REGION-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/demo-app:$COMMIT_SHA

  # Cloud Deploy リリースの作成(CI の最終ステップ)
  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    entrypoint: gcloud
    args:
      - deploy
      - releases
      - create
      - rel-$SHORT_SHA
      - --delivery-pipeline=cloud-run-demo-pipeline
      - --region=REGION
      - --project=DEPLOY_PROJECT_ID
      - --annotations=commitId=$REVISION_ID
      - --images=demo-app-image=REGION-docker.pkg.dev/$PROJECT_ID/cloud-run-demo/demo-app:$COMMIT_SHA

Cloud Build トリガーを main ブランチへの push に設定することで、コードをマージするだけで dev へのデプロイが始まるフローが完成します。

まとめ

Cloud Deploy を使って、プロジェクトを分けた Cloud Run 環境(dev / stg / prod)への段階的なプロモートを検証しました。

環境ごとにプロジェクトを分けることで、Skaffold プロファイルが不要になり設定がシンプルになるうえ、IAM・課金・リソースの隔離も自然に実現できます。executionConfigs に専用の実行サービスアカウントを指定することで、CI(Cloud Build)と CD(Cloud Deploy)の権限を分離し、最小権限の原則に従ったセキュアな構成を実現できます。また、prod ターゲットに requireApproval: true を設定するだけで承認フローを組み込めるため、意図しない本番デプロイを防ぐ仕組みを手軽に導入できます。

なお、利用にあたっていくつかの制限事項も把握しておく必要があります。同一パイプライン内のターゲットはすべて同じランタイムタイプ(GKE か Cloud Run か)に統一する必要があり、混在はできません。requireApproval: true のターゲットで承認を拒否した場合、そのロールアウトは APPROVAL_REJECTED 状態になり再承認はできないため、改めてプロモートを実行して新しいロールアウトを作成する必要があります。また、今回のようにプロジェクトをまたいだ構成では実行サービスアカウントの権限をターゲットプロジェクトごとに漏れなく付与する必要があり、1つでも不足するとデプロイが失敗します。

CI ツール(Cloud Build・GitHub Actions など)と組み合わせることで、より本格的な CI/CD パイプラインを構築できます。Cloud Deploy の活用を検討してみてはいかがでしょうか。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部コンサルティング部の渡邉でした!

この記事をシェアする

関連記事