TerraformでGCPのCloud Run Jobsを構築する

みなさん、Cloud Run Jobs 使っていますか?

Cloud Run Jobsが2023年4月26日に一般提供が開始されました。

あらゆるニーズに応えるサーバーレス: Cloud Run ジョブと第 2 世代の実行環境が一般提供に

試しに構築していたときに注意点もあったため、その点も踏まえて、Terraformを使ってCloud Run Jobsのジョブとトリガーを構築しようと思います。

環境

$ terraform -v
Terraform v1.5.0
on linux_amd64
+ provider registry.terraform.io/hashicorp/google v4.69.1

準備

作業用のディレクトリを作成・移動します。

$ mkdir terraform-job
$ cd terraform-job

ジョブを作成、更新、削除、実行するための完全な権限がある Cloud Run 管理者 のロールが必要なため付与しておきます。

また、「IAM と管理」 > 「サービス アカウント」 > 「キー」から新しい鍵をJSONで作成して、キーファイルを保存しておきます。

Artifact Registry に何らかのDockerイメージをビルドして登録しておきます。

操作

main.tfを作成、編集します。

main.tf

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.69.1"
    }
  }
}

provider "google" {
  credentials = file("サービス アカウント キーのjsonファイル")

  project = "プロジェクトID"
  region  = "asia-northeast1"
  zone    = "asia-northeast1-a"
}

# Cloud Run Jobs
resource "google_cloud_run_v2_job" "run_job" {
  name     = "job"

  template {
    template {
      containers {
        image   = "Artifact Registry に登録したイメージ"
      }
    }
  }
}

resourceの定義にはcloud_run_v2_jobを利用します。

初期化します。

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/google versions matching "4.69.1"...
- Installing hashicorp/google v4.69.1...
- Installed hashicorp/google v4.69.1 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

(以下省略)

つぎにapplyコマンドで構築します。
実行の確認をしてくるので「yes」と入力します。

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_cloud_run_v2_job.run_job will be created

  (中略)

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

google_cloud_run_v2_job.run_job: Creating...

途中で501エラーになってしまいました……。

│ Error: Error creating Job: googleapi: Error 501: Operation is not implemented, or supported, or enabled.
│
│   with google_cloud_run_v2_job.run_job,
│   on main.tf line 17, in resource "google_cloud_run_v2_job" "run_job":
│   17: resource "google_cloud_run_v2_job" "run_job" {

リクエストに対してAPI側がサポートしてないようです。
しばらく原因を探っていると、
ドキュメントで旧バージョンの google_cloud_run_servicelocationが Required になっているのに対して、v2のAPIである google_cloud_run_v2_servicelocationが Optional となっているのを見つけました。

cloud_run_service#location

location - (Required) The location of the cloud run instance. eg us-central1

cloud_run_v2_service#location

 location - (Optional) The location of the cloud run service

この変更のことから、Jobsのほうのlocationも何かありそうです。

main.tfを修正してlocationを追加します。

(省略)

resource "google_cloud_run_v2_job" "run_job" {
  name     = "job"
  location = "asia-northeast1"

  template {
    template {
      containers {
        image   = "Artifact Registry に登録したイメージ"
      }
    }
  }
}

再度、applyコマンドで構築します。

$ terraform apply

(中略)

google_cloud_run_v2_job.run_job: Creating...
google_cloud_run_v2_job.run_job: Still creating... [10s elapsed]
google_cloud_run_v2_job.run_job: Creation complete after 10s [id=projects/example/locations/asia-northeast1/jobs/job]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

今度は、構築が正常に完了しました。

どうやらgoogle_cloud_run_v2_joblocationはRequiredのはずがドキュメント上ではOptionalになってしまっているようです……。

最後にスケジュール実行のトリガーを設定してみます。
main.tfに追加します。

(省略)

data "google_compute_default_service_account" "default" {
}

# Scheduler Jobs
resource "google_cloud_scheduler_job" "scheduler_job" {
  name      = "job-scheduler-trigger"
  schedule  = "*/8 * * * *"
  time_zone = "Asia/Tokyo"

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

    oauth_token {
      service_account_email = data.google_compute_default_service_account.default.email
    }
  }

  depends_on = [resource.google_cloud_run_v2_job.run_job]
}

applyコマンドで構築。

これでようやくコンソールからもジョブとトリガーが確認できるようになりました!

参考