Crie e execute trabalhos em lote com o Terraform e o Cloud Scheduler

Este tutorial explica como pode usar o Terraform para criar e executar tarefas do Batch através de uma tarefa cron do Cloud Scheduler.

O Terraform é uma ferramenta de código aberto que lhe permite aprovisionar e gerir a infraestrutura especificando o estado pretendido nos ficheiros de configuração. Estes ficheiros podem ser tratados como código e armazenados em sistemas de controlo de versões, como o GitHub.

Embora o Terraform não tenha recursos para o Batch, este tutorial mostra como pode usar o Terraform para criar tarefas do Batch. Em concreto, pode usar o Terraform para agendar e executar uma tarefa cron do Cloud Scheduler que tem como destino a API Batch para criar e executar tarefas do Batch. O Cloud Scheduler é um Google Cloud serviço que lhe permite agendar automaticamente tarefas cron e suporta o Terraform.

Este tutorial destina-se a utilizadores do Batch que já gerem infraestrutura com o Terraform e querem incorporar tarefas do Batch no Terraform.

Crie o diretório do Terraform e o ficheiro de configuração

Crie um diretório para o Terraform e um ficheiro de configuração que defina os recursos que quer criar ou atualizar com o Terraform. O ficheiro de configuração de exemplo para este tutorial define uma tarefa cron do Cloud Scheduler denominada batch-job-invoker. Quando está ativada, a tarefa cron batch-job-invokeré executada a cada 5 minutos para criar uma nova instância da tarefa em lote definida.

  1. Para criar um diretório e um novo ficheiro de configuração do Terraform (.tf) nesse diretório, escreva o seguinte comando e, em seguida, prima Enter:

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

    Este comando cria o diretório terraform, navega até ele e começa a definir um novo ficheiro de configuração main.tf na linha seguinte.

  2. Copie e cole a seguinte configuração do 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
        }
      }
    }
    
    

    Substitua o seguinte:

    • PROJECT_ID: o ID do projeto do seu projeto.
    • PROJECT_NUMBER: o número do projeto do seu projeto.
    • CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL: o endereço de email da conta de serviço que preparou para a tarefa cron do Cloud Scheduler.

      Por exemplo, para usar a conta de serviço predefinida do Compute Engine, especifique o seguinte:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      
    • BATCH_SERVICE_ACCOUNT_EMAIL: o endereço de email da conta de serviço que preparou para tarefas em lote.

      Por exemplo, para usar a conta de serviço predefinida do Compute Engine, especifique o seguinte:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      

    Esta configuração do Terraform define algumas variáveis de entrada e uma tarefa cron que contacta o método da API para criar uma tarefa em lote.

  3. Para guardar e fechar o ficheiro, prima Ctrl+D (ou Command+D no macOS).

Implemente a configuração do Terraform para criar a tarefa cron

Implemente a configuração do Terraform inicializando o Terraform, gerando as alterações planeadas e aplicando-as. Depois de implementar a configuração do Terraform, pode descrever os recursos no seu projeto para verificar se o Terraform criou com êxito a tarefa cron batch-job-invoker.

  1. Inicialize o Terraform no diretório:

    terraform init
    

    O resultado é semelhante ao seguinte:

    ...
    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. Gere o plano de execução do Terraform com base no estado atual do seu projeto e no ficheiro de configuração:

    terraform plan
    

    O resultado é semelhante ao seguinte, que mostra que o plano é criar a tarefa cron:batch-job-invoker

    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. Para aplicar o plano de modo a criar a tarefa cron batch-job-invoker, siga estes passos:

    1. Introduza o seguinte comando:

      terraform apply
      

      O resultado é semelhante ao comando terraform plan anterior, exceto que termina com um pedido de confirmação.

    2. Para confirmar e aplicar o plano, introduza yes.

      O resultado é semelhante ao seguinte:

      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. Para verificar se a tarefa cron batch-job-invoker existe e está ativada, descreva-a:

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

    O resultado é semelhante ao seguinte:

    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: '...'
    

    Na saída, verifique se o campo state está definido como ENABLED.

Verifique se a tarefa cron cria uma tarefa em lote

Verifique se a tarefa cron batch-job-invoker está a criar corretamente tarefas em lote.

  1. Aguarde 5 minutos para que a tarefa cronológica seja executada automaticamente ou acione a tarefa cronológica para execução imediata:

    gcloud scheduler jobs run batch-job-invoker --location us-central1
    
  2. Indique as tarefas em lote que foram criadas pela tarefa cron: batch-job-invoker

    gcloud batch jobs list \
    --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" \
    --sort-by ~createTime
    
    • A flag --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" filtra a lista para incluir apenas tarefas em lote que tenham uma etiqueta com a chave source e o valor terraform_and_cloud_scheduler_tutorial.
    • A opção --sort-by ~createTime ordena a lista do mais recente para o mais antigo.

Atualize a configuração do Terraform para pausar a tarefa cron

Depois de ter o número desejado de tarefas em lote, atualize e implemente a configuração do Terraform para pausar a tarefa cron batch-job-invoker. Se quiser atualizar outras propriedades da tarefa cron ou de tarefas em lote futuras, aplica-se o mesmo processo.

  1. Atualize o ficheiro de configuração do Terraform para pausar a tarefa cron definindo o campo paused como true:

    sed -i 's/paused           = false # this cron job is enabled/paused           = true # this cron job is paused/g' main.tf
    
  2. Gere o plano de execução do Terraform com base no estado atual do seu projeto e no ficheiro de configuração:

    terraform plan
    

    A saída é semelhante à seguinte, que mostra que o plano é atualizar o valor do campo paused de false para 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. Para aplicar o plano para atualizar a tarefa cron batch-job-invoker, siga estes passos:

    1. Introduza o seguinte comando:

      terraform apply
      

      O resultado é semelhante ao comando terraform plan anterior, exceto que termina com um pedido de confirmação.

    2. Para confirmar e aplicar o plano, introduza yes.

      O resultado é semelhante ao seguinte:

      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. Para verificar se a tarefa cron batch-job-invoker está pausada, descreva-a:

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

    O resultado é semelhante ao seguinte:

    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: '...'
    

    Na saída, verifique se o campo state está definido como PAUSED.