使用 Terraform 和 Cloud Scheduler 创建和运行批处理作业

本教程介绍了如何使用 Terraform 通过 Cloud Scheduler Cron 作业创建和运行 Batch 作业。

Terraform 是一种开源工具,可让您通过在配置文件中指定所需状态来预配和管理基础架构。这些文件可以视为代码,并存储在 GitHub 等版本控制系统中。

虽然 Terraform 没有 Batch 的资源,但本教程展示了如何使用 Terraform 创建 Batch 作业。具体来说,您可以使用 Terraform 安排和运行 Cloud Scheduler cron 作业,该作业以 Batch API 为目标来创建和运行 Batch 作业。Cloud Scheduler 是一项 Google Cloud 服务,可让您自动安排 cron 作业,并支持 Terraform。

本教程面向已使用 Terraform 管理基础架构并希望将 Batch 作业纳入 Terraform 的 Batch 用户。

创建 Terraform 目录和配置文件

为 Terraform 创建一个目录和一个配置文件,用于定义您要使用 Terraform 创建或更新的资源。本教程的示例配置文件定义了一个名为 batch-job-invoker 的 Cloud Scheduler cron 作业。启用后,batch-job-invoker cron 作业每 5 分钟运行一次,以创建定义的 Batch 作业的新实例。

  1. 如需创建目录并在该目录中创建新的 Terraform 配置 (.tf) 文件,请输入以下命令,然后按 Enter

    mkdir terraform && cd terraform && cat > main.tf
    

    此命令会创建 terraform 目录,将您导航到该目录,并在下一行开始定义新的 main.tf 配置文件。

  2. 复制并粘贴以下 Terraform 配置:

    # define variables
    variable "project_id" {
      type        = string
      description = "The project name to use."
      default = "PROJECT_ID"
    }
    
    variable "project_number" {
      type        = string
      description = "The project number to use."
      default = "PROJECT_NUMBER"
    }
    
    variable "region" {
      type        = string
      description = "The region where resources are created."
      default = "us-central1"
    }
    
    variable "cloud_scheduler_service_account_email" {
      type        = string
      description = "The service account email."
      default = "CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL"
    }
    
    variable "batch_service_account_email" {
      type        = string
      description = "The service account email."
      default = "BATCH_SERVICE_ACCOUNT_EMAIL"
    }
    
    # define a Cloud Scheduler cron job which triggers Batch jobs
    resource "google_cloud_scheduler_job" "batch-job-invoker" {
      paused           = false # this cron job is enabled
      name             = "batch-job-invoker"
      project          = var.project_id
      region           = var.region
      schedule         = "*/5 * * * *" # when enabled, run every 5 minutes
      time_zone        = "America/Los_Angeles"
      attempt_deadline = "180s"
    
      retry_config {
        max_doublings        = 5
        max_retry_duration   = "0s"
        max_backoff_duration = "3600s"
        min_backoff_duration = "5s"
      }
    
      # when this cron job runs, create and run a Batch job
      http_target {
        http_method = "POST"
        uri = "https://batch.googleapis.com/v1/projects/${var.project_id}/locations/${var.region}/jobs"
        headers = {
          "Content-Type" = "application/json"
          "User-Agent"   = "Google-Cloud-Scheduler"
        }
        # Batch job definition
        body = base64encode(<<EOT
        {
          "taskGroups":[
            {
              "taskSpec": {
                "runnables":{
                  "script": {
                    "text": "echo Hello world! This job was created using Terraform and Cloud Scheduler."
                  }
                }
              }
            }
          ],
          "allocationPolicy": {
            "serviceAccount": {
              "email": "${var.batch_service_account_email}"
            }
          },
          "labels": {
            "source": "terraform_and_cloud_scheduler_tutorial"
          },
          "logsPolicy": {
            "destination": "CLOUD_LOGGING"
          }
        }
        EOT
        )
        oauth_token {
          scope                 = "https://www.googleapis.com/auth/cloud-platform"
          service_account_email = var.cloud_scheduler_service_account_email
        }
      }
    }
    
    

    替换以下内容:

    • PROJECT_ID:您的项目的项目 ID
    • PROJECT_NUMBER:您的项目的项目编号
    • CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL:您为 Cloud Scheduler cron 作业准备的服务账号的电子邮件地址。

      例如,如需使用 Compute Engine 默认服务账号,请指定以下内容:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      
    • BATCH_SERVICE_ACCOUNT_EMAIL:您为 Batch 作业准备的服务账号的电子邮件地址。

      例如,如需使用 Compute Engine 默认服务账号,请指定以下内容:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      

    此 Terraform 配置定义了一些输入变量和一个用于调用 API 方法来创建 Batch 作业的 cron 作业。

  3. 如需保存并关闭文件,请按 Ctrl+D(在 macOS 上,按 Command+D)。

部署 Terraform 配置以创建 cron 作业

通过初始化 Terraform、生成计划更改并应用这些更改来部署 Terraform 配置。部署 Terraform 配置后,您可以描述项目中的资源,以验证 Terraform 是否已成功创建 batch-job-invoker cron 作业。

  1. 在目录中初始化 Terraform:

    terraform init
    

    输出类似于以下内容:

    ...
    Terraform has been successfully initialized!
    
    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.
    
    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
    
  2. 根据项目的当前状态和配置文件生成 Terraform 执行计划:

    terraform plan
    

    输出类似于以下内容,其中显示了计划创建 batch-job-invoker cron 作业:

    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_scheduler_job.batch-job-invoker will be created
      + resource "google_cloud_scheduler_job" "batch-job-invoker" {
          + id        = (known after apply)
          + name      = "batch-job-invoker"
          + paused    = false
          + project   = "PROJECT_ID"
          + region    = "us-central1"
          + schedule  = "*/5 * * * *"
          + state     = (known after apply)
          + time_zone = "America/Los_Angeles"
    
          + http_target {
              + body        = "..."
              + headers     = {
                  + "Content-Type" = "application/json"
                  + "User-Agent"   = "Google-Cloud-Scheduler"
                }
              + http_method = "POST"
              + uri         = "https://batch.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/jobs"
    
              + oauth_token {
                  + scope                 = "https://www.googleapis.com/auth/cloud-platform"
                  + service_account_email = "CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL"
                }
            }
    
          + retry_config {
              + max_backoff_duration = "3600s"
              + max_doublings        = 5
              + max_retry_duration   = "0s"
              + min_backoff_duration = "5s"
              + retry_count          = (known after apply)
            }
        }
    
    Plan: 1 to add, 0 to change, 0 to destroy.
    
    ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    
    Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
    
  3. 如需应用该方案来创建 batch-job-invoker cron 作业,请按以下步骤操作:

    1. 输入以下命令:

      terraform apply
      

      输出与之前的 terraform plan 命令类似,只是结尾会显示确认提示。

    2. 如需确认并应用方案,请输入 yes

      输出类似于以下内容:

      google_cloud_scheduler_job.batch-job-invoker: Creating...
      google_cloud_scheduler_job.batch-job-invoker: Creation complete after 0s [id=projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker]
      
      Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
      
  4. 如需验证 batch-job-invoker cron 作业是否存在并已启用,请对其进行描述:

    gcloud scheduler jobs describe batch-job-invoker --location us-central1
    

    输出类似于以下内容:

    attemptDeadline: 180s
    httpTarget:
      body: ...
      headers:
        Content-Type: application/json
        User-Agent: Google-Cloud-Scheduler
      httpMethod: POST
      oauthToken:
        scope: https://www.googleapis.com/auth/cloud-platform
        serviceAccountEmail: CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL
      uri: https://batch.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/jobs
    lastAttemptTime: '...'
    name: projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker
    retryConfig:
      maxBackoffDuration: 3600s
      maxDoublings: 5
      maxRetryDuration: 0s
      minBackoffDuration: 5s
    schedule: '*/5 * * * *'
    scheduleTime: '...'
    state: ENABLED
    status: {}
    timeZone: America/Los_Angeles
    userUpdateTime: '...'
    

    在输出中,验证 state 字段是否已设置为 ENABLED

验证 cron 作业是否创建了批处理作业

验证 batch-job-invoker cron 作业是否正确创建了批处理作业。

  1. 您可以等待 5 分钟,让 cron 作业自动运行,也可以触发 cron 作业立即运行:

    gcloud scheduler jobs run batch-job-invoker --location us-central1
    
  2. 列出由 batch-job-invoker cron 作业创建的 Batch 作业:

    gcloud batch jobs list \
    --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" \
    --sort-by ~createTime
    
    • --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" 标志会过滤列表,使其仅包含具有键为 source 且值为 terraform_and_cloud_scheduler_tutorial 的标签的 Batch 作业。
    • --sort-by ~createTime 标志可按从新到旧的顺序对列表进行排序。

更新 Terraform 配置以暂停 Cron 作业

在获得所需数量的 Batch 作业后,更新并部署 Terraform 配置以暂停 batch-job-invoker cron 作业。如果您想更新 cron 作业或未来批处理作业的其他属性,也可以使用此流程。

  1. 更新 Terraform 配置文件,将 paused 字段设置为 true,以暂停 cron 作业:

    sed -i 's/paused           = false # this cron job is enabled/paused           = true # this cron job is paused/g' main.tf
    
  2. 根据项目的当前状态和配置文件生成 Terraform 执行计划:

    terraform plan
    

    输出类似于以下内容,其中显示了将 paused 字段的值从 false 更新为 true 的计划:

    google_cloud_scheduler_job.batch-job-invoker: Refreshing state... [id=projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      ~ update in-place
    
    Terraform will perform the following actions:
    
      # google_cloud_scheduler_job.batch-job-invoker will be updated in-place
      ~ resource "google_cloud_scheduler_job" "batch-job-invoker" {
            id               = "projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker"
            name             = "batch-job-invoker"
          ~ paused           = false -> true
            # (6 unchanged attributes hidden)
    
          ~ http_target {
              ~ headers     = {
                  + "User-Agent"   = "Google-Cloud-Scheduler"
                    # (1 unchanged element hidden)
                }
                # (3 unchanged attributes hidden)
    
                # (1 unchanged block hidden)
            }
    
            # (1 unchanged block hidden)
        }
    
    Plan: 0 to add, 1 to change, 0 to destroy.
    
    ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    
    Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
    
  3. 如需应用该方案来更新 batch-job-invoker cron 作业,请按以下步骤操作:

    1. 输入以下命令:

      terraform apply
      

      输出与之前的 terraform plan 命令类似,只是结尾会显示确认提示。

    2. 如需确认并应用方案,请输入 yes

      输出类似于以下内容:

      google_cloud_scheduler_job.batch-job-invoker: Modifying... [id=projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker]
      google_cloud_scheduler_job.batch-job-invoker: Modifications complete after 1s [id=projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker]
      
      Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
      
  4. 如需验证 batch-job-invoker cron 作业是否已暂停,请描述该作业:

    gcloud scheduler jobs describe batch-job-invoker --location us-central1
    

    输出类似于以下内容:

    attemptDeadline: 180s
    httpTarget:
      body: ...
      headers:
        Content-Type: application/json
        User-Agent: Google-Cloud-Scheduler
      httpMethod: POST
      oauthToken:
        scope: https://www.googleapis.com/auth/cloud-platform
        serviceAccountEmail: CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL
      uri: https://batch.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/jobs
    lastAttemptTime: '...'
    name: projects/PROJECT_ID/locations/us-central1/jobs/batch-job-invoker
    retryConfig:
      maxBackoffDuration: 3600s
      maxDoublings: 5
      maxRetryDuration: 0s
      minBackoffDuration: 5s
    schedule: '*/5 * * * *'
    scheduleTime: '...'
    state: PAUSED
    status: {}
    timeZone: America/Los_Angeles
    userUpdateTime: '...'
    

    在输出中,验证 state 字段是否已设置为 PAUSED