👟

定期実行ジョブを Cloud Scheduler + Cloud Run Jobs で作る

に公開

概要

定期実行ジョブを実現する際には、タイトルとは別の選択肢として Cloud Run Function を利用する方法があります。しかし、Cloud Run Functions では、Cloud Scheduler と Cloud Run Functions の間に Cloud PubSub を挟まなければなりません。
Cloud Run Jobs を利用すればシンプルな構成で定期実行ジョブを実現できます。ただし、完全な上位互換ではないことに注意です。

terraformで構築する

variable "region" {
  type = string
}
variable "project_id" {
  type = string
}

Cloud Run Jobs

  • 今回は us-docker.pkg.dev/cloudrun/container/job:latest を実行するだけのジョブです。
    • Cloud Scheduler でコマンド引数を上書きしていますが、このイメージでは書き換えたところで出力結果は変わりません。
  • ジョブの制限に cpu = "1000m", memory = "512Mi" を指定していますが、現在はこれが最小値となります。[1]
    • Cloud Run Functions で設定できる最小値は cpu = "83m", memory = "128Mi"[2]
resource "google_service_account" "example_job" {
  account_id   = "example-job"
  display_name = "example-job"
  description  = "Service Account for Cloud Run Jobs"
}

# ジョブを実行するにあたって必要な権限を付与する
#resource "google_project_iam_member" "cloudsql_admin" {
#  project = var.project_id
#  role    = "roles/cloudsql.admin"
#  member  = google_service_account.example_job.member
#}

resource "google_cloud_run_v2_job" "example_job" {
  name     = "example-job"
  location = var.region
  template {
    parallelism = 1
    task_count  = 1
    template {
      max_retries     = 1
      timeout         = "60s"
      service_account = google_service_account.example_job.email
      containers {
        image = "us-docker.pkg.dev/cloudrun/container/job:latest"
        env {
          name  = "GOOGLE_CLOUD_PROJECT"
          value = var.project_id
        }
        resources {
          limits = {
            cpu    = "1000m"
            memory = "512Mi"
          }
        }
      }
    }
  }
  lifecycle {
    ignore_changes = [
      client,
      template[0].template[0].containers[0].name,
      template[0].template[0].containers[0].image,
    ]
  }
}

Cloud Scheduler

  • 単にジョブを実行するだけでなく、いろいろオーバライドしてジョブを実行することができます。
resource "google_service_account" "example_scheduler" {
  account_id   = "example-scheduler"
  display_name = "example-scheduler"
  description  = "Service Account for Cloud Scheduler"
}

resource "google_project_iam_member" "run_jobs_executor_with_overrides" {
  project = var.project_id
  role    = "roles/run.jobsExecutorWithOverrides"
  member  = google_service_account.example_scheduler.member
}

resource "google_cloud_scheduler_job" "scheduler_1" {
  name             = "scheduler-1"
  description      = "Scheduler 1"
  schedule         = "0 8 * * 1-5"
  time_zone        = "Asia/Tokyo"
  attempt_deadline = "60s"
  retry_config {
    retry_count = 1
  }
  http_target {
    uri         = "https://${google_cloud_run_v2_job.example_job.location}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${var.project_id}/jobs/${google_cloud_run_v2_job.example_job.name}:run"
    http_method = "POST"
    headers = {
      "Content-Type" = "application/json"
    }
    body = base64encode(jsonencode(
      {
        "overrides" : {
          "containerOverrides" : [
            {
              "args" : ["scheduler_1"]
            }
          ]
        }
      }
    ))
    oauth_token {
      service_account_email = google_service_account.example_scheduler.email
    }
  }
}

resource "google_cloud_scheduler_job" "scheduler_2" {
  name             = "scheduler-2"
  description      = "Scheduler 2"
  schedule         = "0 20 * * 1-5"
  time_zone        = "Asia/Tokyo"
  attempt_deadline = "60s"
  retry_config {
    retry_count = 1
  }
  http_target {
    uri         = "https://${google_cloud_run_v2_job.example_job.location}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${var.project_id}/jobs/${google_cloud_run_v2_job.example_job.name}:run"
    http_method = "POST"
    headers = {
      "Content-Type" = "application/json"
    }
    body = base64encode(jsonencode(
      {
        "overrides" : {
          "containerOverrides" : [
            {
              "args" : ["scheduler_2"]
            }
          ]
        }
      }
    ))
    oauth_token {
      service_account_email = google_service_account.example_scheduler.email
    }
  }
}
脚注
  1. Configure CPU limits for jobs - CPU and memory table ↩︎

  2. Configure memory limits for services - Required minimum CPUs ↩︎

Discussion