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


本教程介绍了如何使用 Terraform 创建和运行 使用 Cloud Scheduler Cron 作业进行批量作业。

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

虽然 Terraform 没有适用于 Batch 的资源, 教程介绍了如何使用 Terraform 创建 Batch 作业。 具体而言,您可以使用 Terraform 安排和运行以 Batch API 为目标的 Cloud Scheduler cron 作业,以创建和运行批处理作业。Cloud Scheduler 是一项 Google Cloud 服务, 可让您自动安排 Cron 作业,并支持 Terraform。

本教程适用于已经 并且希望将 批量作业进入 Terraform。

目标

  • 创建一个 Terraform 目录和一个定义 Cloud Scheduler Cron 作业,用于创建 批量作业。
  • 部署 Terraform 配置以运行 Cron 作业。
  • 验证 Cron 作业是否会创建批处理作业。
  • 更新 Terraform 配置以暂停 Cron 作业,使其停止创建批处理作业。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 准备开发环境(Cloud Shell 或本地 shell):

    Cloud Shell

    如需使用已设置 gcloud CLI 和 Terraform 的在线终端,请激活 Cloud Shell。

    在此页面的底部,将会启动一个 Cloud Shell 会话 会显示命令行提示符。会话可能需要几秒钟的时间 初始化。

    本地 shell

    如需使用本地开发环境,请按照以下步骤操作:

    1. Install the Google Cloud CLI.
    2. To initialize the gcloud CLI, run the following command:

      gcloud init
    3. 安装 Terraform
  2. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Batch, Compute Engine, Cloud Logging, Cloud Scheduler, and Resource Manager APIs:

    gcloud services enable batch.googleapis.com compute.googleapis.com logging.googleapis.com  cloudscheduler.googleapis.com cloudresourcemanager.googleapis.com
  5. 请确保您的项目至少有一个服务账号,且该账号具有本教程所需的权限。

    具体来说,您可以使用 同一个服务账号或两项不同的服务 账号授予以下权限:

    • 允许该 Cron 作业创建批处理作业并为批处理作业附加服务账号。
    • 允许批处理作业创建和访问运行所需的资源。

    为了确保本教程的服务账号拥有必要的 拥有使用 Terraform 创建批量作业的权限 运行 Cloud Scheduler 请让管理员向本教程的服务账号授予 以下 IAM 角色:

    • Cloud Scheduler Cron 作业的服务账号:
      • 项目的 Batch Job Editor (roles/batch.jobsEditor)
      • Service Account User (roles/iam.serviceAccountUser) 服务账号用户 针对 Batch 作业(即使是批处理作业本身)的服务账号
    • 批量作业的服务账号:

    如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

    您的管理员或许也能为本教程提供服务账号 通过自定义 角色或其他预定义 角色

  6. 确保您拥有本教程所需的权限。

    具体而言,您需要拥有执行以下操作的权限:

    • 创建 Cron 作业,并附加 Cron 作业的服务账号。
    • 查看和删除 Cron 作业和批处理作业。

    获取使用 Terraform 创建批量作业所需的权限 运行 Cloud Scheduler 请让管理员授予您 以下 IAM 角色:

创建 Terraform 目录和配置文件

为 Terraform 创建一个目录,并创建一个配置文件来定义您要使用 Terraform 创建或更新的资源。本教程的示例配置文件定义了 名为“batch-job-invoker”的 Cloud Scheduler Cron 作业。 启用此选项后,batch-job-invoker Cron 作业 每 5 分钟运行一次,以创建一个 批量作业。

  1. 如需在 Terraform 中创建一个目录和一个新的 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_number}/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:电子邮件地址 为批处理作业准备的服务账号指定的身份

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

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      

    此 Terraform 配置定义了一些输入变量和一个 cron 作业,该作业会与用于创建批处理作业的 API 方法联系。

  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_NUMBER/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_NUMBER/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 作业创建的批量作业:

    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
    • --sort-by ~createTime 标志按从新到旧的顺序对列表进行排序。

更新 Terraform 配置以暂停 Cron 作业

达到所需数量的批处理作业后, 更新并部署 Terraform 配置,以暂停 batch-job-invoker Cron 作业。如果您希望更新 Cron 作业或未来的 Batch 作业 相同的流程同样适用

  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_NUMBER/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

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

  1. Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

  2. 转到父级目录,然后删除 Terraform 目录 及其所有文件

    cd .. && rm -r terraform
    

删除各个资源

  1. 删除 batch-job-invoker Cron 作业。

    terraform destroy
    
  2. 如需删除本教程中的所有批处理作业,请执行以下操作: 请按以下步骤操作:

    1. 列出由 Cloud Build 创建的所有 Batch 作业 batch-job-invoker Cron 作业:

      gcloud batch jobs list \
      --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" \
      --sort-by ~createTime
      

      记录您需要删除的每个作业的名称。

    2. 删除本教程中的批处理作业:

      gcloud batch jobs delete JOB_NAME --location us-central1
      

      JOB_NAME 替换为 批量作业。

      对所有 Batch 作业重复此步骤。

  3. 如果您为本教程创建了服务账号,请删除该服务账号:

    gcloud iam service-accounts delete SERVICE_ACCOUNT_EMAIL
    

    SERVICE_ACCOUNT_EMAIL 替换为您为本教程创建的服务账号的电子邮件地址。也就是说,您使用了以下服务账号:

    • CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL: Cloud Scheduler 的服务账号。
    • BATCH_SERVICE_ACCOUNT_EMAIL: Batch 的服务账号。

    如果您创建了两个单独的服务账号,请重复此步骤。

  4. 转到父级目录,然后删除 Terraform 目录 及其所有文件

    cd .. && rm -r terraform
    

后续步骤