🎉

Cloud Run Jobs がリリースされたので、何ができるか試してみた!

2022/05/13に公開

2022/05/11にCloud Run Jobsがプレビューでリリースされました!
https://cloud.google.com/run/docs/release-notes#May_11_2022
https://cloud.google.com/run/docs/create-jobs

Unlike services, which listen for requests, a job does not serve requests but only runs its tasks and exits when finished.

従来のCloud Runのserviceでジョブ的なことを実装する場合、ポートをリッスンしてリクエストを受け取り、ジョブを実行して、成功/失敗のレスポンスを返すという流れでした。
今回リリースされたCloud Run Jobsでは、ポートをリッスンする必要がなくなったということで、ついに待ち望んでいた機能がきたのか!?とさっそく動作確認し、僕が期待してたことは全部できそうでした🎉

これまでCloudBuildでワークフロー組んでたんですが、対応リージョン増えてCloudWorkflowで動かせることがCloudRunJobsに移行するぞ〜

まとめ

  • jobs createしてから、jobs executeすると単発でジョブを実行できる
  • jobs createする時に、実行時のコマンドと引数を--commandフラグと--argsフラグで設定できる
  • jobs createする時に、環境変数を--set-env-varsフラグで設定できる
  • jobs createする時に、--tasksフラグで実行時の並列数を指定できる
    • 実行されるジョブはCLOUD_RUN_TASK_INDEXCLOUD_RUN_TASK_COUNTという環境変数を利用できる
  • jobs createする時に、--parallelismフラグで実行時の最大並列数を指定できる
  • ジョブの最大実行時間は1h
  • まだGCPコンソールではjobsは表示できないっぽい

期待してたことと結果

  • ①普段バッチ処理はspf13/cobraとかを利用してCLIアプリケーションとして作るので、それをCloud Runで実行したい
    • できる!
    • コマンドと引数は渡せるが、まだ--userみたいな引数を渡せないっぽい
    • 環境変数は渡せる
    • なので、環境変数で渡せるように実装すればOK(僕はそうしてたので問題なし!)
  • ②時間のかかる処理を分割して実行したい
    • できる!
    • --tasks使って、CLOUD_RUN_TASK_INDEXCLOUD_RUN_TASK_COUNTを利用すれば、たとえば処理対象が10万個あった時に1万個ずつ処理みたいなことができる
  • ③Cloud Workflowは並列な処理を書けないので、Cloud WorflowとCloud Run Jobsでギリ並列処理を実現できると嬉しい(処理Aと処理Bを同時に実行して、両方が終わったら処理Cみたいなのはできない)(もしかしたらCloud Workflowってもう並列な処理をかけるようになってるかも?!)
    • 動作確認はできなった
    • が、公式ドキュメントでは「できる」と記載はある
    • 具体的なやり方のドキュメントはまだないっぽい

Cloud Run Jobsだけを試してみた

利用したドキュメント

環境変数を用意

export GOOGLE_PROJECT=xxxxx
export REGION=europe-west9
export IMAGE_URL=asia.gcr.io/$GOOGLE_PROJECT/xxxxxxx:latest
export JOB_NAME=sample-job

実行ファイルを用意

package main

import (
	"log"
	"os"
	"time"
)

func main() {
	log.Print("hello cloud run job!")
	log.Print(os.Args)
	log.Printf("CLOUD_RUN_TASK_INDEX = %s", os.Getenv("CLOUD_RUN_TASK_INDEX"))
	log.Printf("CLOUD_RUN_TASK_COUNT = %s", os.Getenv("CLOUD_RUN_TASK_COUNT"))
	log.Printf("FOO = %s", os.Getenv("FOO"))
	log.Printf("BAR = %s", os.Getenv("BAR"))

	for i := 0; i < 10; i++ {
		time.Sleep(1 * time.Second)
		log.Printf("[%d] I'm doing something!", i)
	}
	log.Print("Your task has been successfully completed!!!")
}

FROM golang:1.18.1-alpine AS builder
WORKDIR /usr/local/src/
ADD go.mod ./
RUN go mod download
ADD . .
RUN go build -o /go/bin/app ./main.go

FROM alpine:latest
COPY --from=builder /go/bin/app /
CMD ["/app"]

イメージをプッシュ

docker image build .  --platform amd64 -t $IMAGE_URL
docker image push $IMAGE_URL

コマンドフラグなし -> 動作する

gcloud beta run jobs create $JOB_NAME \
    --image $IMAGE_URL \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs execute $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs delete $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

コマンドと引数は指定できる

gcloud beta run jobs create $JOB_NAME \
    --image $IMAGE_URL \
    --command "/app" \
    --args a,b,c,100 \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs execute $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs delete $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

フラグっぽい引数は指定する -> エラー

gcloud beta run jobs create $JOB_NAME \
    --image $IMAGE_URL \
    --command "/app" \
    --args --user,hoge \
    --project $GOOGLE_PROJECT \
    --region $REGION

これできなかったの個人的には非常に残念。。。

yamlで無理やり更新を試みる -> servicesと違ってjobsはreplaceコマンド使えない

gcloud beta run jobs describe $JOB_NAME --format export \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs replace sample_job.yaml \
    --project $GOOGLE_PROJECT \
    --region $REGION

なので、今のところフラグっぽい引数を指定することは不可能っぽい
これできなかったの個人的には非常に残念。。。

tasksを指定する -> 並列に実行される

gcloud beta run jobs create $JOB_NAME \
    --tasks 3 \
    --image $IMAGE_URL \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs execute $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs delete $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

tasksとparallelismを指定する -> 並列数を制御できる

gcloud beta run jobs create $JOB_NAME \
    --tasks 3 \
    --parallelism 1 \
    --image $IMAGE_URL \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs execute $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION
gcloud beta run jobs delete $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

その他使ったコマンド

gcloud beta run jobs execute $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

gcloud beta run jobs list \
    --project $GOOGLE_PROJECT \
    --region $REGION

gcloud beta run jobs executions list\
    --project $GOOGLE_PROJECT \
    --region $REGION

gcloud beta run jobs executions describe sample-job-m9xkv \
    --project $GOOGLE_PROJECT \
    --region $REGION

gcloud beta run jobs delete $JOB_NAME \
    --project $GOOGLE_PROJECT \
    --region $REGION

他のサービスと組み合わせで何ができるの?

Cloud Scheduler

Cloud Schedulerとの組み合わせで定期実行ができるらしい
https://cloud.google.com/run/docs/execute/jobs-on-schedule#console

Cloud Workflow

https://cloud.google.com/run/docs/create-jobs

After you create or update a job, you can execute the job as a one-off, on a schedule or as part of a workflow. You can manage individual job executions and view the execution logs.

Cloud Workflowで実行できるとの記載があるが、ドキュメントはまだないようで、yamlの書き方が不明だったので試せなかった

使ったコード

https://github.com/nekoshita/cloud-run-job-example

Discussion