🐶
Cloud Run Jobs を使うときの覚書
はじめに
Cloud Run Jobs(以下、Cloud Run ジョブ)を使ってバッチ処理や一回限りの処理を実行する際の個人的な覚書です。忘れやすいポイントをまとめます。
これは何?
HTTP サーバー不要。一度(またはスケジュール)で実行して終了するバッチ向けコンテナ。 FaaS とは違い、Web サーバを意識しないため、シンプルな実装が可能です。
想定ユースケース
- ETL/データ集計、レポート生成
- API バックフィル、バッチ送信(Slack/メール等)
- 定期メンテナンス(不要データ削除、サマリー作成など)
前提・準備
- イメージは Artifact Registry に集約します。
-
job.yaml
を単一の真実源(SSOT)として宣言的に管理します。 - CI/CD は Cloud Build で、ビルド・プッシュ後に
gcloud run jobs replace
を実行します。 - 定期実行は Cloud Scheduler、イベント駆動は Pub/Sub、手動実行はオペレーションから行います。
ビルドとデプロイ(概要)
- アプリのビルド→イメージを Artifact Registry へプッシュ。
-
job.yaml
のイメージタグを更新し、gcloud run jobs replace
で適用。 - 実行はトリガー(スケジューラ/イベント/手動)で行い、CD では自動実行しない運用を推奨。
設計の要点(ジョブ)
- 並列実行:
taskCount
とparallelism
を設計に合わせて設定。 - 再試行:
maxRetries
はタスク単位。冪等性で重複実行に耐える。 - タイムアウト:
timeoutSeconds
を処理時間に見合う値へ。
実行と観測(概要)
- 実行トリガー: Cloud Scheduler、Pub/Sub、手動。
- 観測: Cloud Logging に標準出力/標準エラー。Error Reporting と Alerting を連携。
運用・ライフサイクル
- 更新は
job.yaml
を更新してjobs replace
を実施(宣言的)。 - 削除は
jobs delete
。ラベル・アノテーションは管理タグを活用。
スケジューリング・イベント連携(概要)
- Cloud Scheduler: CRON で
jobs.run
を呼ぶ。最小権限でサービスアカウントを付与。 - Pub/Sub: メッセージ受信をトリガーに実行(ワーク分割・冪等性設計)。
- 手動実行: オペレーション手順として実行・監視を行う。
並列実行と再試行の設計メモ
-
並列実行:
--tasks=N
で N 個のタスクを並列に起動。タスク間でワークを分割する設計にする(例: シャーディングやページング)。 -
再試行:
--max-retries
はタスク単位。冪等設計にして重複実行に耐える。 -
タイムアウト: 長時間ジョブは
--task-timeout
を十分大きく。中断されるときは SIGTERM を受ける想定で安全に終了させる。 - データ授受: ステップごとのデータの授受は、Cloud Storage 利用が推奨。
YAMLでのリソース定義
CLI オプションでも管理できますが、再現性・コードレビュー性の観点から YAML で定義して replace
する運用をおすすめします。以下は VPC 設定を含む最小例です。
job.yaml
apiVersion: run.googleapis.com/v1
kind: Job
metadata:
name: job-sample
labels:
cloud.googleapis.com/location: asia-northeast1
spec:
template:
template:
metadata:
annotations:
# 直結 VPC(Direct VPC egress)。JSON 文字列で指定
run.googleapis.com/network-interfaces: '[{"network":"projects/PROJECT_ID/global/networks/NETWORK","subnetwork":"projects/PROJECT_ID/regions/asia-northeast1/subnetworks/SUBNET"}]'
# すべてのアウトバウンドを VPC 経由にする場合
run.googleapis.com/vpc-access-egress: all-traffic
spec:
serviceAccountName: job-sa@PROJECT_ID.iam.gserviceaccount.com
containers:
- image: asia-northeast1-docker.pkg.dev/PROJECT_ID/app-repo/job-sample:latest
env:
- name: NODE_ENV
value: production
timeoutSeconds: 600
maxRetries: 1
taskCount: 1
parallelism: 1
適用は gcloud run jobs replace job.yaml
を用います(CIとRelease参照)。
補足:
-
VPC:
run.googleapis.com/network-interfaces
はネットワーク/サブネットを JSON 文字列で指定します。run.googleapis.com/vpc-access-egress
はall-traffic
(全量)/private-ranges-only
(プライベート範囲のみ)を選択。 - 帯域制限: Cloud Run の各インスタンス(ジョブの各タスク相当)のアウトバウンド帯域は 1 Gbps が上限です。大量転送がある処理は並列数・分割・再試行を設計してください。
アーキテクチャ
構成の考え方:
-
CI/CD: Cloud Build がイメージをビルド/プッシュし、
gcloud run jobs replace
でjob.yaml
を宣言的に適用。 - イベント: Cloud Scheduler/ Pub/Sub/手動実行で Cloud Run ジョブを起動。
- 観測: Cloud Loggingを連携し、失敗検知と通知を自動化。
- ネットワーク: VPC egress を要件に合わせて選択。大容量転送は 1 Gbps/インスタンスの上限を考慮し並列度設計。
Cloud Run サービスとの違い
- HTTP サーバー不要(プロセスが終われば終了)。
- 課金単位は実行中の vCPU/メモリ時間。アイドル課金はなし。
- スケールはタスク数ベース。リクエスト駆動ではない。
- ヘルスチェックは不要。終了コードで成否を判定。
トラブルシュートのメモ
- コンテナが即終了する: エントリポイント(CMD/ENTRYPOINT)が正しいか確認。
- 失敗が続く: 退出コードの確認、
--max-retries
と冪等性、外部依存のタイムアウト設定を見直す。 - ログが出ない: 標準出力/標準エラーに出力しているか、Cloud Logging のフィルタで
resource.type=cloud_run_job
を確認。
おわりに
Cloud Run ジョブは「HTTP がいらない一回きりの処理」を手早く安全に動かすのに便利です。ここにある雛形とコマンドを土台に、プロジェクトのガードレール(IAM/ネットワーク/監視)を整えて使っていきます。
付録: Cloud Build サンプル(CI と Release)
宣言的デプロイ(gcloud run jobs replace
)を前提に、CI 用と Release 用の YAML 例を示します。テンプレート置換は簡易に sed
を利用しています。
CI: プルリク/ブランチ向け(ビルドと一時タグ)
cloudbuild.ci.yaml
substitutions:
_REGION: asia-northeast1
_REPO: app-repo
_JOB_NAME: job-sample
steps:
- name: gcr.io/cloud-builders/docker
args: ['build', '-t', '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:${SHORT_SHA}', '.']
- name: gcr.io/cloud-builders/docker
args: ['push', '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:${SHORT_SHA}']
# 任意: SBOM生成/脆弱性スキャン等
images:
- '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:${SHORT_SHA}'
Release
cloudbuild.release.yaml
substitutions:
_REGION: asia-northeast1
_REPO: app-repo
_JOB_NAME: job-sample
steps:
# CI で作ったイメージを release タグへ付け替え
- name: gcr.io/cloud-builders/docker
entrypoint: bash
args:
- -c
- |
SRC=${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:${SHORT_SHA}
DST=${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:release
docker pull ${SRC}
docker tag ${SRC} ${DST}
docker push ${DST}
# job.yaml をテンプレートからレンダリングし、宣言的に置換
- name: gcr.io/cloud-builders/gcloud
entrypoint: bash
args:
- -c
- |
IMAGE=${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_JOB_NAME}:release
sed "s#IMAGE_PLACEHOLDER#${IMAGE}#g; s#PROJECT_ID#${PROJECT_ID}#g; s#REGION#${_REGION}#g; s#JOB_NAME#${_JOB_NAME}#g" job.tmpl.yaml > job.yaml
gcloud run jobs replace job.yaml --region=${_REGION}
artifacts:
objects:
location: gs://$PROJECT_ID-build-artifacts/jobs/
paths: ['job.yaml']
job.tmpl.yaml(例)
job.tmpl.yaml
apiVersion: run.googleapis.com/v1
kind: Job
metadata:
name: JOB_NAME
labels:
cloud.googleapis.com/location: REGION
spec:
template:
template:
metadata:
annotations:
# 例: すべてのアウトバウンドをVPC経由
run.googleapis.com/vpc-access-egress: all-traffic
spec:
serviceAccountName: job-sa@PROJECT_ID.iam.gserviceaccount.com
containers:
- image: IMAGE_PLACEHOLDER
env:
- name: NODE_ENV
value: production
timeoutSeconds: 600
maxRetries: 1
taskCount: 1
parallelism: 1
運用メモ:
- CI はビルドと検証用タグの発行まで。Release で安定タグ付与と
jobs replace
を実施。 - 実行は Scheduler/手動/イベントに分離。CD 直後の自動実行は避けると安全。
- 大容量転送は 1 Gbps/インスタンスの上限を考慮し、並列度・分割を調整。
Discussion