見出し画像

Cloud Run jobs を使ってみる

こんにちは、自分の勉強したことをまとめて、発信を行なっていこうと思います。
今回は備忘録的な内容になります。

この記事では、Cloud Run の 1 機能であるCloud Run jobs を terraformで構築して、pythonジョブを定期実行するまでをまとめています。

Cloud Run jobs とは

Cloud Run には Cloud Run services と Cloud Run jobs があります。
Cloud Run services はHTTPリクエストを受け付けることのできるので、Webサーバーなどによく使われます。
一方、Cloud Run jobs はある一回の実行で終了する作業(ジョブ)の動作環境に使用できます。

Cloud Run jobsの特徴

Cloud Run servicesに比べると Cloud Run jobs の特徴は以下のようなものだと思います。個人的には最大24時間までタイムアウトが延べせるのが使い所によっては使いやすいなと思っています。

  • 1回限りの実行が可能

  • HTTPSで実行開始することはできるが、パラメータを渡すことはできない

  • ジョブの実行時に、環境変数をオーバーライドできる

  • ジョブのタイムアウトは最長24時間まで長くすることができる

    • Cloud Run services は最長60分まで

実際に使ってみる

コードはここに全てアップしています
https://github.com/M0T0-2020/GCP-memorandum/tree/master/cr-jobs-0714

コンテナイメージの用意

今回はダミージョブとして、このpythonスクリプトを実行していきます。

`MESSAGE` と `NUMBER` という環境変数を読み込んで、それらをパラメータとして処理を実行します。

# main.py

import os
import time

from joblib import Parallel, delayed


def process_something(id: int, message: str):
    n = min(id, 10)
    for k in range(n):
        print(f"id{n}: {message} {k}th")
        time.sleep(1)
    return message


def do_job(message: str, number: int):
    results = Parallel(n_jobs=-1)(
        delayed(process_something)(id, message) for id in range(number)
    )
    return list(results)


if __name__ == "__main__":
    message = os.getenv("MESSAGE")
    number = int(os.getenv("NUMBER"))
    messages = do_job(message, number)

Dockerfileを用意してArtifact Registry にpushしておきます。
タスクはインスタンス上で1度だけ実行されるので、Dockerfileもpython環境を構築して、.pyを実行するだけの構成になっています。

# Dockerfile

# Use Python 3.11 slim as the base image
FROM python:3.11-slim

# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV JOBS_HOME=/jobs
# Set the working directory
WORKDIR $JOBS_HOME

# Copy requirements file and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the remaining application files
COPY . .

# Run the main Python script
CMD ["python", "main.py"]
# Artifact Registry にpushしておきます。 

gcloud builds submit . -t us-central1-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE_NAME

terraformで環境構築

ジョブのスクリプトの用意ができたので、次はCloud Run jobsの環境をterraformで構築したいと思います。
今回は、スケジュラーで毎日19時にジョブを定期実行するような構成で書いていきます。
ジョブのタイムアウトは3時間に設定してみました。

terraformコードの作成には、この辺の情報を参考にしています。

provider "google" {
  project = var.project_id
  region  = var.region
}

data "google_project" "project" {
    project_id = var.project_id
}

resource "google_service_account" "default" {
  account_id   = "cloud-run-jobs-test-sa"
  display_name = "service account for cr-jobs-0714"
}

resource "google_project_service" "cloudscheduler_api" {
  service = "cloudscheduler.googleapis.com"
}


resource "google_cloud_run_v2_job" "default" {
  name         = "cloud-run-job"
  location     = var.region
  launch_stage = "BETA"

  template {
    template {
      containers {
        image = var.container_path
        env {
          name  = "MESSAGE"
          value = var.message
        }
        env {
          name  = "NUMBER"
          value = var.number
        }
      }
      # 3 hours
      timeout      = "10800s"
      service_account = google_service_account.default.email
    }
  }
}

resource "google_cloud_run_v2_job_iam_binding" "binding" {
  project  = google_cloud_run_v2_job.default.project
  name     = google_cloud_run_v2_job.default.name
  location = google_cloud_run_v2_job.default.location
  role     = "roles/run.invoker"

  members = [
    "serviceAccount:${google_service_account.default.email}"
  ]
}

resource "google_cloud_scheduler_job" "job" {
  name             = "schedule-job"
  description      = "test http job"
  schedule         = "0 10 * * *" # execute every day at 7pm(jst)
  attempt_deadline = "320s"
  region           = var.region
  project          = var.project_id

  retry_config {
    retry_count = 3
  }

  http_target {
    http_method = "POST"
    uri         = "https://${google_cloud_run_v2_job.default.location}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${data.google_project.project.number}/jobs/${google_cloud_run_v2_job.default.name}:run"

    oauth_token {
      service_account_email = google_service_account.default.email
    }
  }

  depends_on = [
    resource.google_project_service.cloudscheduler_api,
    resource.google_cloud_run_v2_job.default,
    resource.google_cloud_run_v2_job_iam_binding.binding
  ]
}

確認

コンソールを確認すると、スケジューラによって19時にジョブが実行されているのが確認できました。

赤枠がスケジューラの実行 (他は手動のテスト実行)

詳細を見ると意図通りのログも見ることができました。

詳細ログ

他には、コンソール環境変数の値を上書きして実行することもできます。

「実行」のボタンの少し右にある下矢印のボタンを押すと環境変数を変えて実行可能

環境変数の上書き設定をして、httpリクエストによる実行も可能です。

まとめ

  • 簡単にCloud Run Jobsを構築することができました。

  • Cloud FunctionsやCloudRunServiceは最大タイムアウト時間が1時間ですが、Cloud Run Jobsは24時間まで許容範囲なので、時間がかかるようなタスクを実行させるときに使えるかなと思いました。

最後まで読んでくれてありがとうございます。 🙏

この記事が気に入ったらサポートをしてみませんか?