STERFIELD

Cloud Run jobs を利用したバッチ処理

Cloud Run jobs を利用したバッチ処理

はじめに

Google Cloud 上でバッチ処理を行う際に、Cloud Run jobsを使用したので紹介します。 本記事では、他サービスとの比較とCloud Run jobsの使い方について説明します。

Google Cloud でバッチ処理できるサービス

Cloud Run jobs を使用するにあたって、他のサービスについても調べたのでそれぞれの特徴をまとめました。

Cloud Functions

様々なイベントをトリガーにできるので、特定のイベントが発生したときに動かしたいバッチ処理の場合は Cloud Functions を使うと良さそうです。 例えば Cloud Storage に画像がアップロードされた際に、自動的にサムネイルを作成したり、画像にフィルターをかけたりする処理が簡単に作れます。 しかし、最大実行時間に制限(60 分)があるため長時間の処理には適さない場合があります。

Batch

大規模なバッチ処理ワークロードを効率的に実行するためのフルマネージドなサービスです。 高性能コンピューティング(HPC)、機械学習、データ処理など、さまざまな種類のバッチジョブをスケーラブルかつ柔軟に実行できます。 また、最大実行時間に制限が無いので長時間の処理に適しています。 しかし、Cloud Functions や Cloud Run jobs よりも設定が複雑になってしまうので採用しませんでした。

Cloud Run jobs

Cloud Run の一機能で、バッチ処理や非同期タスクの実行に特化したサービスです。 最大実行時間に制限がありますが、24 時間実行できるのでほとんどのバッチ処理は問題ないでしょう。

Cloud Run jobs の基本要素

Cloud Run jobs のリソース構造

Cloud Run jobs は以下のようなリソースで構成されています。
リソース構造

ジョブ (Job)

実行したいタスクの全体像を定義するルートリソースです。

ジョブでは以下の項目を設定できます。

  • コンテナイメージ
  • タスク数
  • 並列実行数
  • リソース(各タスクに割り当てる CPU やメモリなどのリソース量)
  • 環境変数
  • サービスアカウント

タスク (Task)

ジョブによって定義されたタスクのインスタンスです。 タスクはジョブに設定された数だけ実行されます。コンテナインスタンスを 1:1 で用意し、コンテナインスタンスごとの進捗を管理します。タスクがエラーで終了した場合は、タスク単位で再実行もできます。

実行 (Execution)

タスクの実行履歴です。 ジョブの設定に応じてタスクを実行し、全てのタスクが完了するまでの状態を管理します。1 度作成した実行は、何度でも再実行が可能です。

Cloud Run jobs の作成・実行方法

サンプルアプリケーションの用意

以下のコードを適当なフォルダに作成します

環境変数にSLEEP_MSを設定すると、設定した時間だけスリープするようになり、時間のかかる処理を再現できます。 FAIL_RATEを設定すると、指定した確率でジョブがエラーになり、エラー時の挙動を確認できます。

main.js

1// Retrieve Job-defined env vars 2const { CLOUD_RUN_TASK_INDEX = 0, CLOUD_RUN_TASK_ATTEMPT = 0 } = process.env; 3// Retrieve User-defined env vars 4const { SLEEP_MS, FAIL_RATE } = process.env; 5 6// Define main script 7const main = async () => { 8 console.log( 9 `Starting Task #${CLOUD_RUN_TASK_INDEX}, Attempt #${CLOUD_RUN_TASK_ATTEMPT}...` 10 ); 11 // Simulate work 12 if (SLEEP_MS) { 13 await sleep(SLEEP_MS); 14 } 15 // Simulate errors 16 if (FAIL_RATE) { 17 try { 18 randomFailure(FAIL_RATE); 19 } catch (err) { 20 err.message = `Task #${CLOUD_RUN_TASK_INDEX}, Attempt #${CLOUD_RUN_TASK_ATTEMPT} failed.\n\n${err.message}`; 21 throw err; 22 } 23 } 24 console.log(`Completed Task #${CLOUD_RUN_TASK_INDEX}.`); 25}; 26 27// Wait for a specific amount of time 28const sleep = (ms) => { 29 return new Promise((resolve) => setTimeout(resolve, ms)); 30}; 31 32// Throw an error based on fail rate 33const randomFailure = (rate) => { 34 rate = parseFloat(rate); 35 if (!rate || rate < 0 || rate > 1) { 36 console.warn( 37 `Invalid FAIL_RATE env var value: ${rate}. Must be a float between 0 and 1 inclusive.` 38 ); 39 return; 40 } 41 42 const randomFailure = Math.random(); 43 if (randomFailure < rate) { 44 throw new Error("Task failed."); 45 } 46}; 47 48// Start script 49main().catch((err) => { 50 console.error(err); 51 process.exit(1); // Retry Job Task by exiting the process 52});

package.json

1{ 2 "main": "main.js", 3 "scripts": { 4 "start": "node main.js" 5 }, 6 "engines": { 7 "node": ">=20.0.0" 8 } 9}

Dockerfile

1FROM node:20 2WORKDIR /app 3COPY . . 4RUN npm install 5CMD [ "npm", "start" ]

コンテナをプッシュ

次のコマンドで Artifact Registry にコンテナをプッシュします。${REGION}${PROJECT_ID}は各自で置き換えてください。

1gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/gcr.io/job-sample

ジョブを作成

今回は、以下の Cloud Run のコンソールから作成します。
https://console.cloud.google.com/run/jobs

「ジョブの作成」をクリックします。
ジョブの作成ボタン

「コンテナ イメージの URL」に先ほど作成したコンテナを選択します。 イメージ名が自動的に設定されます。 リージョンやタスク数はお好みで設定して下さい。
ジョブの詳細

ジョブの実行

「実行」をクリックし、ジョブを開始します。
実行ボタン

しばらく経つと、全てのタスクが完了し、実行が完了します。実行の詳細を開くとタスクが完了していることが確認でき、各タスクのログ等が確認できます。
タスク

作成した Job を定期実行する方法

「トリガー」タブを選択し、「スケジューラ トリガーを追加」をクリックします。
トリガー追加ボタン

頻度を unix-cron 形式で選択します。 今回は 5 分ごと(*/5****)に実行してみます。
トリガー詳細

指定した通り、5 分ごとにジョブが実行されました。
ジョブ一覧

まとめ

今回は Cloud Run jobs について説明しましたが、各サービスのメリット・デメリットを比較し、要件に合った最適なサービスを選択することが重要です。 今後、他サービスにも触れる機会がありましたら紹介したいです。

参考

Author Profile

著者近影

AIROU

プログラマーです 猫とラーメンが好きです

SHARE

合わせて読みたい