Crea y ejecuta trabajos por lotes con Terraform y Cloud Scheduler


En este instructivo, se explica cómo puedes usar Terraform para crear y ejecutar trabajos por lotes mediante un trabajo cron de Cloud Scheduler.

Terraform es una herramienta de código abierto que te permite aprovisionar y administrar la infraestructura mediante la especificación del estado deseado en los archivos de configuración. Estos archivos se pueden tratar como código y almacenarse en sistemas de control de versión, como GitHub.

Aunque Terraform no tiene recursos para Batch, en este instructivo se muestra cómo puedes usar Terraform y crear trabajos por lotes. En particular, puedes usar Terraform para programar y ejecutar un trabajo cron de Cloud Scheduler que se oriente a la API de Batch para crear y ejecutar trabajos de Batch. Cloud Scheduler es un servicio de Google Cloud que te permite programar de forma automática los trabajos cron y es compatible con Terraform.

Este instructivo está dirigido a los usuarios de Batch que ya administran la infraestructura con Terraform y desean incorporar trabajos por lotes en Terraform.

Objetivos

  • Crea un directorio de Terraform y un archivo de configuración que defina un trabajo cron de Cloud Scheduler que cree trabajos por lotes.
  • Implementa la configuración de Terraform para ejecutar el trabajo cron.
  • Verifica que el trabajo cron cree trabajos por lotes.
  • Actualiza la configuración de Terraform para pausar el trabajo cron a fin de que deje de crear trabajos por lotes.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. Prepara tu entorno de desarrollo, ya sea Cloud Shell o una shell local:

    Cloud Shell

    Para usar una terminal en línea con gcloud CLI y Terraform ya configurados, activa Cloud Shell.

    En la parte inferior de esta página, se inicia una sesión de Cloud Shell que muestra una ventana de línea de comandos. La sesión puede tardar unos segundos en inicializarse.

    Shell local

    Para usar un entorno de desarrollo local, sigue estos pasos:

    1. Instala Google Cloud CLI.
    2. Para inicializar la CLI de gcloud, ejecuta el siguiente comando:

      gcloud init
    3. Instala Terraform.
  2. Crea o selecciona un proyecto de Google Cloud.

    • Crea un proyecto de Google Cloud:

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto de Google Cloud que estás creando.

    • Selecciona el proyecto de Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre del proyecto de Google Cloud.

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Habilita las APIs de Batch, Compute Engine, Cloud Logging, Cloud Scheduler, and Resource Manager:

    gcloud services enable batch.googleapis.com compute.googleapis.com logging.googleapis.com  cloudscheduler.googleapis.com cloudresourcemanager.googleapis.com
  5. Asegúrate de que tu proyecto tenga al menos una cuenta de servicio con los permisos necesarios para este instructivo.

    En particular, puedes usar la misma cuenta de servicio o dos cuentas de servicio separadas para otorgar los siguientes permisos:

    • Permite que el trabajo cron cree trabajos por lotes y adjunte la cuenta de servicio a los trabajos por lotes.
    • Permite que los trabajos por lotes creen los recursos necesarios para ejecutarse y accedan a ellos.

    Si quieres asegurarte de que las cuentas de servicio de este instructivo tengan los permisos necesarios para usar Terraform y crear trabajos por lotes a través de un trabajo cron de Cloud Scheduler, pídele a tu administrador que otorgue a las cuentas de servicio los siguientes roles de IAM para este instructivo:

    Si quieres obtener más información para otorgar funciones, consulta Administra el acceso.

    Es posible que el administrador también pueda otorgar a las cuentas de servicio de este instructivo los permisos necesarios a través de roles personalizados o de otras funciones predefinidas.

  6. Asegúrate de tener los permisos necesarios para este instructivo.

    En particular, necesitas permisos para hacer lo siguiente:

    • Crea un trabajo cron y adjunta la cuenta de servicio para el trabajo cron.
    • Visualiza y borra el trabajo cron y los trabajos por lotes.

    Si quieres obtener los permisos que necesitas para usar Terraform a fin de crear trabajos por lotes a través de un trabajo cron de Cloud Scheduler, pídele a tu administrador que te otorgue los siguientes roles de IAM:

Crea el directorio y el archivo de configuración de Terraform

Crea un directorio para Terraform y un archivo de configuración que defina los recursos que deseas crear o actualizar con Terraform. En el archivo de configuración de ejemplo para este instructivo, se define un trabajo cron de Cloud Scheduler llamado batch-job-invoker. Cuando está habilitado, el trabajo cron batch-job-invoker se ejecuta cada 5 minutos para crear una instancia nueva del trabajo por lotes definido.

  1. Para crear un directorio y un archivo de configuración de Terraform nuevo (.tf) dentro de ese directorio, escribe el siguiente comando y, luego, presiona Enter:

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

    Con este comando, se crea el directorio terraform, se navega hacia él y se comienza a definir un nuevo archivo de configuración main.tf en la línea siguiente.

  2. Copia y pega la siguiente configuración de 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
        }
      }
    }
    
    

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el ID del proyecto.
    • PROJECT_NUMBER: Es el número del proyecto.
    • CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL: Es la dirección de correo electrónico de la cuenta de servicio que preparaste para el trabajo cron de Cloud Scheduler.

      Por ejemplo, para usar la cuenta de servicio predeterminada de Compute Engine, especifica lo siguiente:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      
    • BATCH_SERVICE_ACCOUNT_EMAIL: La dirección de correo electrónico de la cuenta de servicio que preparaste para los trabajos por lotes.

      Por ejemplo, para usar la cuenta de servicio predeterminada de Compute Engine, especifica lo siguiente:

      PROJECT_NUMBER-compute@developer.gserviceaccount.com
      

    Esta configuración de Terraform define algunas variables de entrada y un trabajo cron que contacta al método de la API para crear un trabajo por lotes.

  3. Para guardar y cerrar el archivo, presiona Ctrl+D (o Command+D en macOS).

Implementa la configuración de Terraform para crear el trabajo cron

Implementa la configuración de Terraform mediante la inicialización, la generación de los cambios planificados y la aplicación de estos cambios. Después de implementar la configuración de Terraform, puedes describir los recursos de tu proyecto para verificar que Terraform creó correctamente el trabajo cron batch-job-invoker.

  1. Inicializa Terraform en el directorio:

    terraform init
    

    El resultado es similar al siguiente:

    ...
    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. Genera el plan de ejecución de Terraform según el estado actual de tu proyecto y el archivo de configuración:

    terraform plan
    

    El resultado es similar al siguiente, que muestra que el plan es crear el trabajo 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_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. Si deseas aplicar el plan para crear el trabajo cron batch-job-invoker, sigue estos pasos:

    1. Ingresa el siguiente comando:

      terraform apply
      

      El resultado es similar al comando terraform plan anterior, excepto que termina con una solicitud de confirmación.

    2. Para confirmar y aplicar el plan, ingresa yes.

      El resultado es similar al siguiente:

      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 que el trabajo cron batch-job-invoker exista y esté habilitado, descríbelo:

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

    El resultado es similar al siguiente:

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

    En el resultado, verifica que el campo state esté configurado como ENABLED.

Verifica que el trabajo cron cree un trabajo por lotes

Verifica que el trabajo cron batch-job-invoker cree trabajos por lotes de forma correcta.

  1. Espera 5 minutos a que se ejecute automáticamente el trabajo cron o actívalo de inmediato:

    gcloud scheduler jobs run batch-job-invoker --location us-central1
    
  2. Enumera los trabajos por lotes que creó el trabajo cron batch-job-invoker:

    gcloud batch jobs list \
    --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" \
    --sort-by ~createTime
    
    • La marca --filter labels.source=\"terraform_and_cloud_scheduler_tutorial\" filtra la lista para incluir solo los trabajos por lotes que tienen una etiqueta con la clave source y el valor terraform_and_cloud_scheduler_tutorial.
    • La marca --sort-by ~createTime ordena la lista de la más reciente a la más antigua.

Actualiza la configuración de Terraform para pausar el trabajo cron

Una vez que tengas la cantidad deseada de trabajos por lotes, actualiza y, luego, implementa la configuración de Terraform para pausar el trabajo cron batch-job-invoker. Si deseas actualizar otras propiedades del trabajo cron o trabajos por lotes futuros, se aplica este mismo proceso.

  1. Actualiza el archivo de configuración de Terraform para pausar el trabajo cron mediante la configuración del campo paused en true:

    sed -i 's/paused           = false # this cron job is enabled/paused           = true # this cron job is paused/g' main.tf
    
  2. Genera el plan de ejecución de Terraform según el estado actual de tu proyecto y el archivo de configuración:

    terraform plan
    

    El resultado es similar al siguiente, que muestra que el plan es actualizar el valor del campo paused de false a 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. Si deseas aplicar el plan para actualizar el trabajo cron batch-job-invoker, sigue estos pasos:

    1. Ingresa el siguiente comando:

      terraform apply
      

      El resultado es similar al comando terraform plan anterior, excepto que termina con una solicitud de confirmación.

    2. Para confirmar y aplicar el plan, ingresa yes.

      El resultado es similar al siguiente:

      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 que el trabajo cron batch-job-invoker esté pausado, descríbelo:

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

    El resultado es similar al siguiente:

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

    En el resultado, verifica que el campo state esté configurado como PAUSED.

Limpia

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Borra el proyecto

  1. Borra un proyecto de Google Cloud:

    gcloud projects delete PROJECT_ID

  2. Ve al directorio superior y, luego, borra el directorio de Terraform y todos sus archivos.

    cd .. && rm -r terraform
    

Borra los recursos individuales

  1. Borra el trabajo cron batch-job-invoker.

    terraform destroy
    
  2. Para borrar todos los trabajos por lotes de este instructivo, sigue estos pasos:

    1. Enumera todos los trabajos por lotes que creó el trabajo cron batch-job-invoker:

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

      Registra el nombre de cada trabajo que necesites borrar.

    2. Borra un trabajo por lotes de este instructivo:

      gcloud batch jobs delete JOB_NAME --location us-central1
      

      Reemplaza JOB_NAME por el nombre de un trabajo por lotes.

      Repite este paso para todos los trabajos por lotes.

  3. Si creaste una cuenta de servicio para este instructivo, bórrala:

    gcloud iam service-accounts delete SERVICE_ACCOUNT_EMAIL
    

    Reemplaza SERVICE_ACCOUNT_EMAIL por la dirección de correo electrónico de la cuenta de servicio que creaste para este instructivo. En particular, usaste las siguientes cuentas de servicio:

    • CLOUD_SCHEDULER_SERVICE_ACCOUNT_EMAIL: Es la cuenta de servicio de Cloud Scheduler.
    • BATCH_SERVICE_ACCOUNT_EMAIL: Es la cuenta de servicio para Batch.

    Si creaste dos cuentas de servicio separadas, repite este paso.

  4. Ve al directorio superior y, luego, borra el directorio de Terraform y todos sus archivos.

    cd .. && rm -r terraform
    

¿Qué sigue?