Ejecuta un trabajo de Cloud Run con Workflows

Workflows te permite ejecutar trabajos de Cloud Run como parte de un flujo de trabajo para realizar procesamientos de datos más complejos o bien organizar un sistema de trabajos existentes.

En este instructivo, se muestra cómo usar Workflows para ejecutar un trabajo de Cloud Run que procesa datos que se pasan como variables de entorno al trabajo, en respuesta a un evento de Cloud Storage.

Ten en cuenta que también puedes almacenar los datos del evento en un bucket de Cloud Storage, lo que te permite encriptar los datos con claves de encriptación administradas por el cliente. Para obtener más información, consulta Ejecuta un trabajo de Cloud Run que procese los datos de eventos guardados en Cloud Storage.

Crear un trabajo de Cloud Run

En este instructivo, se usa un trabajo de muestra de Cloud Run de GitHub. El trabajo lee datos de un archivo de entrada en Cloud Storage y realiza algún procesamiento arbitrario para cada línea del archivo.

  1. Clona el repositorio de la app de ejemplo en tu máquina local para obtener el código de muestra:

    git clone https://github.com/GoogleCloudPlatform/jobs-demos.git

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

  2. Dirígete al directorio que contiene el código de muestra:

    cd jobs-demos/parallel-processing
  3. Crea un bucket de Cloud Storage para almacenar un archivo de entrada en el que se pueda escribir y que active un evento:

    Console

    1. En la consola de Google Cloud , ve a la página Buckets de Cloud Storage.

      Ir a Buckets

    2. Haz clic en add Crear.
    3. En la página Crear un bucket, ingresa un nombre para tu bucket:
      input-PROJECT_ID
      Reemplaza PROJECT_ID por el ID de tu proyecto de Google Cloud .
    4. Conserva los demás valores predeterminados.
    5. Haz clic en Crear.

    gcloud

    Ejecuta el comando gcloud storage buckets create:

    gcloud storage buckets create gs://input-PROJECT_ID

    Si la solicitud se realiza correctamente, el comando mostrará el siguiente mensaje:

    Creating gs://input-PROJECT_ID/...

    Terraform

    Para crear un bucket de Cloud Storage, usa el recurso google_storage_bucket y modifica tu archivo main.tf como se muestra en el siguiente ejemplo.

    Si deseas obtener más información para aplicar o quitar una configuración de Terraform, consulta los comandos básicos de Terraform.

    Ten en cuenta que, en un flujo de trabajo típico de Terraform, aplicas todo el plan de una vez. Sin embargo, para los fines de este instructivo, puedes segmentar un recurso específico. Por ejemplo:

    terraform apply -target="random_id.bucket_name_suffix"
    y
    terraform apply -target="google_storage_bucket.default"

    # Cloud Storage bucket names must be globally unique
    resource "random_id" "bucket_name_suffix" {
      byte_length = 4
    }
    
    # Create a Cloud Storage bucket
    resource "google_storage_bucket" "default" {
      name                        = "input-${data.google_project.project.name}-${random_id.bucket_name_suffix.hex}"
      location                    = "us-central1"
      storage_class               = "STANDARD"
      force_destroy               = false
      uniform_bucket_level_access = true
    }
  4. Crea un repositorio estándar de Artifact Registry en el que puedas almacenar tu imagen de contenedor:

    Console

    1. En la consola de Google Cloud , ve a la página Repositorios de Artifact Registry:

      Ir a Repositorios

    2. Haz clic en Crear repositorio.

    3. Ingresa un nombre para el repositorio, por ejemplo, my-repo. Para la ubicación de cada repositorio en un proyecto, los nombres de los repositorios deben ser únicos.

    4. Conserva el formato predeterminado, que debe ser Docker.

    5. Conserva el modo predeterminado, que debe ser Estándar.

    6. En la región, selecciona us-central1 (Iowa).

    7. Conserva todos los demás valores predeterminados.

    8. Haz clic en Crear.

    gcloud

    Ejecuta el siguiente comando:

    gcloud artifacts repositories create REPOSITORY \
        --repository-format=docker \
        --location=us-central1

    Reemplaza REPOSITORY por un nombre único para el repositorio, por ejemplo, my-repo. Para la ubicación de cada repositorio en un proyecto, los nombres de los repositorios deben ser únicos.

    Terraform

    Para crear un repositorio de Artifact Registry, usa el recurso google_artifact_registry_repository y modifica tu archivo main.tf como se muestra en el siguiente ejemplo.

    Ten en cuenta que, en un flujo de trabajo típico de Terraform, aplicas todo el plan de una vez. Sin embargo, para los fines de este instructivo, puedes segmentar un recurso específico. Por ejemplo:

    terraform apply -target="google_artifact_registry_repository.default"

    # Create an Artifact Registry repository
    resource "google_artifact_registry_repository" "default" {
      location      = "us-central1"
      repository_id = "my-repo"
      format        = "docker"
    }
  5. Compila la imagen de contenedor con un paquete de compilación Google Cloud predeterminado:

    export SERVICE_NAME=parallel-job
    gcloud builds submit \
        --pack image=us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}

    Reemplaza REPOSITORY por el nombre de tu repositorio de Artifact Registry.

    La compilación puede tardar un par de minutos en completarse.

  6. Crea un trabajo de Cloud Run que implemente la imagen de contenedor:

    Console

    1. En la consola de Google Cloud , ve a la página de Cloud Run:

      Ir a Cloud Run

    2. Haz clic en Crear trabajo para mostrar el formulario Crear trabajo.

      1. En el formulario, selecciona us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/parallel-job:latest como la URL de la imagen del contenedor de Artifact Registry.
      2. Opcional: En el nombre del trabajo, ingresa parallel-job.
      3. Opcional: En la región, selecciona us-central1 (Iowa).
      4. Para la cantidad de tareas que deseas ejecutar en el trabajo, ingresa 10. Todas las tareas deben realizarse con éxito para que el trabajo tenga éxito. De forma predeterminada, las tareas se ejecutan en paralelo.
    3. Expande la sección Contenedor, variables y secretos, Conexiones, Seguridad y conserva todos los valores predeterminados, excepto los siguientes parámetros de configuración:

      1. Haz clic en la pestaña General.

        1. Para el comando del contenedor, ingresa python.
        2. En el argumento del contenedor, ingresa process.py.
      2. Haz clic en la pestaña Variables y Secrets.

        1. Haz clic en Agregar variable y, luego, ingresa INPUT_BUCKET para el nombre y input-PROJECT_ID para el valor.
        2. Haz clic en Agregar variable y, luego, ingresa INPUT_FILE para el nombre y input_file.txt para el valor.
    4. Para crear el trabajo, haz clic en Crear.

    gcloud

    1. Establece la región predeterminada de Cloud Run:

      gcloud config set run/region us-central1
    2. Crea el trabajo de Cloud Run:

      gcloud run jobs create parallel-job \
          --image us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/parallel-job:latest \
          --command python \
          --args process.py \
          --tasks 10 \
          --set-env-vars=INPUT_BUCKET=input-PROJECT_ID,INPUT_FILE=input_file.txt

      Ten en cuenta que, si no especificas una etiqueta de imagen, Artifact Registry busca la imagen con la etiqueta predeterminada latest.

      Para obtener una lista completa de las opciones disponibles cuando creas un trabajo, consulta la documentación de la línea de comandos gcloud run jobs create.

      Una vez que se cree el trabajo, deberías ver un mensaje que indica que se realizó correctamente.

    Terraform

    Para crear un trabajo de Cloud Run, usa el recurso google_cloud_run_v2_job y modifica tu archivo main.tf como se muestra en el siguiente ejemplo.

    Ten en cuenta que, en un flujo de trabajo típico de Terraform, aplicas todo el plan de una vez. Sin embargo, para los fines de este instructivo, puedes segmentar un recurso específico. Por ejemplo:

    terraform apply -target="google_cloud_run_v2_job.default"

    # Create a Cloud Run job
    resource "google_cloud_run_v2_job" "default" {
      name     = "parallel-job"
      location = "us-central1"
    
      template {
        task_count = 10
        template {
          containers {
            image   = "us-central1-docker.pkg.dev/${data.google_project.project.name}/${google_artifact_registry_repository.default.repository_id}/parallel-job:latest"
            command = ["python"]
            args    = ["process.py"]
            env {
              name  = "INPUT_BUCKET"
              value = google_storage_bucket.default.name
            }
            env {
              name  = "INPUT_FILE"
              value = "input_file.txt"
            }
          }
        }
      }
    }

Implementa un flujo de trabajo que ejecute el trabajo de Cloud Run

Define e implementa un flujo de trabajo que ejecute el trabajo de Cloud Run que acabas de crear. La definición de un flujo de trabajo está compuesta por una serie de pasos descritos con la sintaxis de Workflows.

Console

  1. En la consola de Google Cloud , ve a la página Workflows:

    Ir a Workflows

  2. Haz clic en Crear.

  3. Ingresa un nombre para el flujo de trabajo nuevo, como cloud-run-job-workflow.

  4. En la región, selecciona us-central1 (Iowa).

  5. En el campo Cuenta de servicio, selecciona la cuenta de servicio que creaste antes.

    La cuenta de servicio funciona como la identidad del flujo de trabajo. Ya deberías haber otorgado el rol de Administrador de Cloud Run a la cuenta de servicio para que el flujo de trabajo pueda ejecutar el trabajo de Cloud Run.

  6. Haz clic en Siguiente.

  7. En el editor de flujos de trabajo, ingresa la siguiente definición para el flujo de trabajo:

    main:
        params: [event]
        steps:
            - init:
                assign:
                    - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                    - event_bucket: ${event.data.bucket}
                    - event_file: ${event.data.name}
                    - target_bucket: ${"input-" + project_id}
                    - job_name: parallel-job
                    - job_location: us-central1
            - check_input_file:
                switch:
                    - condition: ${event_bucket == target_bucket}
                      next: run_job
                    - condition: true
                      next: end
            - run_job:
                call: googleapis.run.v1.namespaces.jobs.run
                args:
                    name: ${"namespaces/" + project_id + "/jobs/" + job_name}
                    location: ${job_location}
                    body:
                        overrides:
                            containerOverrides:
                                env:
                                    - name: INPUT_BUCKET
                                      value: ${event_bucket}
                                    - name: INPUT_FILE
                                      value: ${event_file}
                result: job_execution
            - finish:
                return: ${job_execution}
  8. Haz clic en Implementar.

gcloud

  1. Crea un archivo de código fuente para tu flujo de trabajo:

    touch cloud-run-job-workflow.yaml
  2. Copia la siguiente definición del flujo de trabajo en tu archivo de código fuente:

    main:
        params: [event]
        steps:
            - init:
                assign:
                    - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                    - event_bucket: ${event.data.bucket}
                    - event_file: ${event.data.name}
                    - target_bucket: ${"input-" + project_id}
                    - job_name: parallel-job
                    - job_location: us-central1
            - check_input_file:
                switch:
                    - condition: ${event_bucket == target_bucket}
                      next: run_job
                    - condition: true
                      next: end
            - run_job:
                call: googleapis.run.v1.namespaces.jobs.run
                args:
                    name: ${"namespaces/" + project_id + "/jobs/" + job_name}
                    location: ${job_location}
                    body:
                        overrides:
                            containerOverrides:
                                env:
                                    - name: INPUT_BUCKET
                                      value: ${event_bucket}
                                    - name: INPUT_FILE
                                      value: ${event_file}
                result: job_execution
            - finish:
                return: ${job_execution}
  3. Para implementar el flujo de trabajo, ingresa el siguiente comando:

    gcloud workflows deploy cloud-run-job-workflow \
        --location=us-central1 \
        --source=cloud-run-job-workflow.yaml \
        --service-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

    Reemplaza lo siguiente:

    • SERVICE_ACCOUNT_NAME: el nombre de la cuenta de servicio que creaste antes
    • PROJECT_ID: Es el ID de tu proyecto deGoogle Cloud .

    La cuenta de servicio funciona como la identidad del flujo de trabajo. Ya deberías haber otorgado el rol roles/run.admin a la cuenta de servicio para que el flujo de trabajo pueda ejecutar el trabajo de Cloud Run.

Terraform

Para crear un flujo de trabajo, usa el recurso google_workflows_workflow y modifica tu archivo main.tf como se muestra en el siguiente ejemplo.

Si deseas obtener más información para aplicar o quitar una configuración de Terraform, consulta los comandos básicos de Terraform.

Ten en cuenta que, en un flujo de trabajo típico de Terraform, aplicas todo el plan de una vez. Sin embargo, para los fines de este instructivo, puedes segmentar tus anuncios para un recurso específico. Por ejemplo:

terraform apply -target="google_workflows_workflow.default"

# Create a workflow
resource "google_workflows_workflow" "default" {
  name        = "cloud-run-job-workflow"
  region      = "us-central1"
  description = "Workflow that routes a Cloud Storage event and executes a Cloud Run job"

  deletion_protection = false # set to "true" in production

  # Note that $$ is needed for Terraform
  source_contents = <<EOF
  main:
      params: [event]
      steps:
          - init:
              assign:
                  - project_id: $${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                  - event_bucket: $${event.data.bucket}
                  - event_file: $${event.data.name}
                  - target_bucket: "${google_storage_bucket.default.name}"
                  - job_name: parallel-job
                  - job_location: us-central1
          - check_input_file:
              switch:
                  - condition: $${event_bucket == target_bucket}
                    next: run_job
                  - condition: true
                    next: end
          - run_job:
              call: googleapis.run.v1.namespaces.jobs.run
              args:
                  name: $${"namespaces/" + project_id + "/jobs/" + job_name}
                  location: $${job_location}
                  body:
                      overrides:
                          containerOverrides:
                              env:
                                  - name: INPUT_BUCKET
                                    value: $${event_bucket}
                                  - name: INPUT_FILE
                                    value: $${event_file}
              result: job_execution
          - finish:
              return: $${job_execution}
  EOF
}

El flujo de trabajo hace lo siguiente:

  1. Paso init: Acepta un evento de Cloud Storage como argumento y, luego, establece las variables necesarias.

  2. Paso check_input_file: Verifica si el bucket de Cloud Storage especificado en el evento es el que usa el trabajo de Cloud Run.

    • Si es así, el flujo de trabajo continúa con el paso run_job.
    • Si la respuesta es no, el flujo de trabajo finaliza y se detiene cualquier procesamiento adicional.
  3. Paso run_job: Usa el método googleapis.run.v1.namespaces.jobs.run del conector de la API de Cloud Run Admin para ejecutar el trabajo. Los nombres del bucket de Cloud Storage y del archivo de datos se pasan como variables de anulación del flujo de trabajo al trabajo.

  4. Paso finish: Devuelve información sobre la ejecución del trabajo como resultado del flujo de trabajo.

Crea un activador de Eventarc para el flujo de trabajo

Para ejecutar automáticamente el flujo de trabajo y, a su vez, el trabajo de Cloud Run cada vez que se actualice el archivo de datos de entrada, crea un activador de Eventarc que responda a los eventos de Cloud Storage en el bucket que contiene el archivo de datos de entrada.

Console

  1. En la consola de Google Cloud , ve a la página Workflows:

    Ir a Workflows

  2. Haz clic en el nombre de tu flujo de trabajo, como cloud-run-job-workflow.

  3. En la página Detalles del flujo de trabajo, haz clic en Editar.

  4. En la página Editar flujo de trabajo, en la sección Activadores, haz clic en Agregar activador nuevo > Eventarc.

    Se abrirá el panel Evento de Eventarc.

  5. En el campo Nombre del activador, ingresa un nombre para el activador, como cloud-run-job-workflow-trigger.

  6. En la lista Proveedor de eventos, selecciona Cloud Storage.

  7. En la lista Evento, selecciona google.cloud.storage.object.v1.finalized.

  8. En el campo Bucket, selecciona el bucket que contiene el archivo de datos de entrada. El nombre del bucket tiene el formato input-PROJECT_ID.

  9. En el campo Cuenta de servicio, selecciona la cuenta de servicio que creaste antes.

    La cuenta de servicio funciona como la identidad del activador. Ya deberías haber otorgado los siguientes roles a la cuenta de servicio:

    • Receptor de eventos de Eventarc: Para recibir eventos
    • Invocador de flujos de trabajo: Para ejecutar flujos de trabajo
  10. Haz clic en Guardar activador.

    El activador de Eventarc ahora aparece en la sección Activadores de la página Editar flujo de trabajo.

  11. Haz clic en Siguiente.

  12. Haz clic en Implementar.

gcloud

Ejecuta el siguiente comando para crear un activador de Eventarc:

gcloud eventarc triggers create cloud-run-job-workflow-trigger \
    --location=us \
    --destination-workflow=cloud-run-job-workflow  \
    --destination-workflow-location=us-central1 \
    --event-filters="type=google.cloud.storage.object.v1.finalized" \
    --event-filters="bucket=input-PROJECT_ID" \
    --service-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

Reemplaza lo siguiente:

  • PROJECT_ID: Es el ID de tu proyecto de Google Cloud .
  • SERVICE_ACCOUNT_NAME: Es el nombre de la cuenta de servicio que creaste antes.

La cuenta de servicio funciona como la identidad del activador. Ya deberías haber otorgado los siguientes roles a la cuenta de servicio:

  • roles/eventarc.eventReceiver: Para recibir eventos
  • roles/workflows.invoker: Para ejecutar flujos de trabajo

Terraform

Para crear un activador, usa el recurso google_eventarc_trigger y modifica tu archivo main.tf como se muestra en el siguiente ejemplo.

Si deseas obtener más información para aplicar o quitar una configuración de Terraform, consulta los comandos básicos de Terraform.

Ten en cuenta que, en un flujo de trabajo típico de Terraform, aplicas todo el plan de una vez. Sin embargo, para los fines de este instructivo, puedes segmentar tus anuncios para un recurso específico. Por ejemplo:

terraform apply -target="google_eventarc_trigger.default"

# Create an Eventarc trigger that routes Cloud Storage events to Workflows
resource "google_eventarc_trigger" "default" {
  name     = "cloud-run-job-trigger"
  location = google_workflows_workflow.default.region

  # Capture objects changed in the bucket
  matching_criteria {
    attribute = "type"
    value     = "google.cloud.storage.object.v1.finalized"
  }
  matching_criteria {
    attribute = "bucket"
    value     = google_storage_bucket.default.name
  }

  # Send events to Workflows
  destination {
    workflow = google_workflows_workflow.default.id
  }

  service_account = google_service_account.workflows.email

}

Cada vez que se sube o se reemplaza un archivo en el bucket de Cloud Storage que contiene el archivo de datos de entrada, el flujo de trabajo se ejecuta con el evento de Cloud Storage correspondiente como argumento.

Activa el flujo de trabajo

Actualiza el archivo de datos de entrada en Cloud Storage para probar el sistema de extremo a extremo.

  1. Genera datos nuevos para el archivo de entrada y súbelos a Cloud Storage en la ubicación esperada por el trabajo de Cloud Run:

    base64 /dev/urandom | head -c 100000 >input_file.txt
    gcloud storage cp input_file.txt gs://input-PROJECT_ID/input_file.txt

    Si creaste un bucket de Cloud Storage con Terraform, puedes recuperar su nombre ejecutando el siguiente comando:

    gcloud storage buckets list gs://input*

    El trabajo de Cloud Run puede tardar unos minutos en ejecutarse.

  2. Para confirmar que el trabajo de Cloud Run se ejecutó según lo previsto, consulta las ejecuciones del trabajo:

    gcloud config set run/region us-central1
    gcloud run jobs executions list --job=parallel-job

    En el resultado, deberías ver una ejecución de trabajo exitosa que indica que se completaron las tareas de 10/10.

Obtén más información para activar un flujo de trabajo con eventos o mensajes de Pub/Sub.