Execute uma tarefa do Cloud Run com o Workflows

Os fluxos de trabalho permitem-lhe executar tarefas do Cloud Run como parte de um fluxo de trabalho para realizar um tratamento de dados mais complexo ou orquestrar um sistema de tarefas existentes.

Este tutorial demonstra como usar os Workflows para executar uma tarefa do Cloud Run que processa dados transmitidos como variáveis de ambiente para a tarefa, em resposta a um evento do Cloud Storage.

Tenha em atenção que também pode armazenar os dados de eventos num contentor do Cloud Storage, o que lhe permite encriptar os dados através de chaves de encriptação geridas pelo cliente. Para mais informações, consulte o artigo Execute uma tarefa do Cloud Run que processe dados de eventos guardados no Cloud Storage.

Crie uma tarefa do Cloud Run

Este tutorial usa uma tarefa de exemplo do Cloud Run do GitHub. A tarefa lê dados de um ficheiro de entrada no Cloud Storage e realiza algum processamento arbitrário para cada linha no ficheiro.

  1. Obtenha o exemplo de código clonando o repositório da app de exemplo para o seu computador local:

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

    Em alternativa, pode transferir o exemplo como um ficheiro ZIP e extraí-lo.

  2. Altere para o diretório que contém o código de exemplo:

    cd jobs-demos/parallel-processing
  3. Crie um contentor do Cloud Storage para armazenar um ficheiro de entrada que possa ser escrito e acionar um evento:

    Consola

    1. Na Google Cloud consola, aceda à página Recipientes do Cloud Storage.

      Aceda a Recipientes

    2. Clique em adicionar Criar.
    3. Na página Criar um contentor, introduza um nome para o contentor:
      input-PROJECT_ID
      Substitua PROJECT_ID pelo ID do seu Google Cloud projeto.
    4. Mantenha as outras predefinições.
    5. Clique em Criar.

    gcloud

    Execute o comando gcloud storage buckets create:

    gcloud storage buckets create gs://input-PROJECT_ID

    Se o pedido for bem-sucedido, o comando devolve a seguinte mensagem:

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

    Terraform

    Para criar um contentor do Cloud Storage, use o recurso google_storage_bucket e modifique o ficheiro main.tf, conforme mostrado no exemplo seguinte.

    Para saber como aplicar ou remover uma configuração do Terraform, consulte os comandos básicos do Terraform.

    Tenha em atenção que, num fluxo de trabalho típico do Terraform, aplica todo o plano de uma só vez. No entanto, para efeitos deste tutorial, pode segmentar um recurso específico. Por exemplo:

    terraform apply -target="random_id.bucket_name_suffix"
    e
    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. Crie um repositório padrão do Artifact Registry onde pode armazenar a sua imagem de contentor:

    Consola

    1. Na Google Cloud consola, aceda à página do Artifact Registry Repositórios:

      Aceda a Repositórios

    2. Clique em Criar repositório.

    3. Introduza um nome para o repositório, por exemplo, my-repo. Para cada localização do repositório num projeto, os nomes dos repositórios têm de ser exclusivos.

    4. Mantenha o formato predefinido, que deve ser Docker.

    5. Mantenha o modo predefinido, que deve ser Padrão.

    6. Para a região, selecione us-central1 (Iowa).

    7. Manter todas as outras predefinições.

    8. Clique em Criar.

    gcloud

    Execute o comando:

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

    Substitua REPOSITORY por um nome exclusivo para o repositório, por exemplo, my-repo. Para cada localização do repositório num projeto, os nomes dos repositórios têm de ser exclusivos.

    Terraform

    Para criar um repositório do Artifact Registry, use o recurso google_artifact_registry_repository e modifique o ficheiro main.tf, conforme mostrado no exemplo seguinte.

    Tenha em atenção que, num fluxo de trabalho típico do Terraform, aplica todo o plano de uma só vez. No entanto, para os fins deste tutorial, pode segmentar um recurso específico. Por exemplo:

    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. Crie a imagem de contentor com um Google Cloud buildpack predefinido:

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

    Substitua REPOSITORY pelo nome do seu repositório do Artifact Registry.

    A compilação pode demorar alguns minutos a ser concluída.

  6. Crie uma tarefa do Cloud Run que implemente a imagem de contentor:

    Consola

    1. Na Google Cloud consola, aceda à página Cloud Run:

      Aceda ao Cloud Run

    2. Clique em Criar tarefa para apresentar o formulário Criar tarefa.

      1. No formulário, selecione us-central1-docker.pkg.dev/PROJECT_ID/REPOSITORY/parallel-job:latest como o URL da imagem do contentor do Artifact Registry.
      2. Opcional: para o nome do trabalho, introduza parallel-job.
      3. Opcional: para a região, selecione us-central1 (Iowa).
      4. Para o número de tarefas que quer executar no trabalho, introduza 10. Todas as tarefas têm de ser bem-sucedidas para que o trabalho seja bem-sucedido. Por predefinição, as tarefas são executadas em paralelo.
    3. Expanda a secção Contentor, variáveis e segredos, ligações, segurança e mantenha todas as predefinições, exceto as seguintes definições:

      1. Clique no separador Geral.

        1. Para o comando de contentor, introduza python.
        2. Para o argumento do contentor, introduza process.py.
      2. Clique no separador Variáveis e segredos.

        1. Clique em Adicionar variável e introduza INPUT_BUCKET para o nome e input-PROJECT_ID para o valor.
        2. Clique em Adicionar variável e introduza INPUT_FILE para o nome e input_file.txt para o valor.
    4. Para criar a tarefa, clique em Criar.

    gcloud

    1. Defina a região predefinida do Cloud Run:

      gcloud config set run/region us-central1
    2. Crie a tarefa do 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

      Tenha em atenção que, se não especificar uma etiqueta de imagem, o Artifact Registry procura a imagem com a etiqueta latest predefinida.

      Para ver uma lista completa das opções disponíveis quando cria uma tarefa, consulte a documentação da linha de comandos do gcloud run jobs create.

      Quando a tarefa for criada, deve ver uma mensagem a indicar que foi bem-sucedida.

    Terraform

    Para criar uma tarefa do Cloud Run, use o recurso google_cloud_run_v2_job e modifique o ficheiro main.tf, conforme mostrado no exemplo seguinte.

    Tenha em atenção que, num fluxo de trabalho típico do Terraform, aplica todo o plano de uma só vez. No entanto, para os fins deste tutorial, pode segmentar um recurso específico. Por exemplo:

    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"
            }
          }
        }
      }
    }

Implemente um fluxo de trabalho que execute a tarefa do Cloud Run

Defina e implemente um fluxo de trabalho que execute a tarefa do Cloud Run que acabou de criar. Uma definição de fluxo de trabalho é composta por uma série de passos descritos através da sintaxe do Workflows.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Clique em Criar.

  3. Introduza um nome para o novo fluxo de trabalho, como cloud-run-job-workflow.

  4. Para a região, selecione us-central1 (Iowa).

  5. No campo Conta de serviço, selecione a conta de serviço que criou anteriormente.

    A conta de serviço funciona como a identidade do fluxo de trabalho. Já deve ter concedido a função Administrador do Cloud Run à conta de serviço para que o fluxo de trabalho possa executar a tarefa do Cloud Run.

  6. Clicar em Seguinte.

  7. No editor de fluxos de trabalho, introduza a seguinte definição para o seu fluxo de trabalho:

    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. Clique em Implementar.

gcloud

  1. Crie um ficheiro de código-fonte para o seu fluxo de trabalho:

    touch cloud-run-job-workflow.yaml
  2. Copie a seguinte definição do fluxo de trabalho para o ficheiro de código-fonte:

    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. Implemente o fluxo de trabalho introduzindo o seguinte 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

    Substitua o seguinte:

    • SERVICE_ACCOUNT_NAME: o nome da conta de serviço que criou anteriormente
    • PROJECT_ID: o ID do seu Google Cloud projeto

    A conta de serviço funciona como a identidade do fluxo de trabalho. Já deve ter concedido a função roles/run.admin à conta de serviço para que o fluxo de trabalho possa executar a tarefa do Cloud Run.

Terraform

Para criar um fluxo de trabalho, use o recurso google_workflows_workflow e modifique o ficheiro main.tf, conforme mostrado no exemplo seguinte.

Para saber como aplicar ou remover uma configuração do Terraform, consulte os comandos básicos do Terraform.

Tenha em atenção que, num fluxo de trabalho típico do Terraform, aplica todo o plano de uma só vez. No entanto, para os fins deste tutorial, pode segmentar um recurso específico. Por exemplo:

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
}

O fluxo de trabalho faz o seguinte:

  1. init: aceita um evento do Cloud Storage como argumento e, em seguida, define as variáveis necessárias.

  2. check_input_file: verifica se o contentor do Cloud Storage especificado no evento é o contentor usado pela tarefa do Cloud Run.

    • Em caso afirmativo, o fluxo de trabalho avança para o passo run_job.
    • Se não, o fluxo de trabalho termina, interrompendo qualquer processamento adicional.
  3. run_job passo: usa o método googleapis.run.v1.namespaces.jobs.run do conector da API Cloud Run Admin para executar a tarefa. O contentor do Cloud Storage e os nomes dos ficheiros de dados são transmitidos como variáveis de substituição do fluxo de trabalho para a tarefa.

  4. Passo finish: devolve informações sobre a execução da tarefa como resultado do fluxo de trabalho.

Crie um acionador do Eventarc para o fluxo de trabalho

Para executar automaticamente o fluxo de trabalho e, por sua vez, a tarefa do Cloud Run sempre que o ficheiro de dados de entrada for atualizado, crie um acionador do Eventarc que responda a eventos do Cloud Storage no contentor que contém o ficheiro de dados de entrada.

Consola

  1. Na Google Cloud consola, aceda à página Fluxos de trabalho:

    Aceda a Fluxos de trabalho

  2. Clique no nome do fluxo de trabalho, como cloud-run-job-workflow.

  3. Na página Detalhes do fluxo de trabalho, clique em Editar.

  4. Na página Editar fluxo de trabalho, na secção Acionadores, clique em Adicionar novo acionador > Eventarc.

    É aberto o painel Acionador do Eventarc.

  5. No campo Nome do acionador, introduza um nome para o acionador, como cloud-run-job-workflow-trigger.

  6. Na lista Fornecedor de eventos, selecione Cloud Storage.

  7. Na lista Evento, selecione google.cloud.storage.object.v1.finalized.

  8. No campo Recipiente, selecione o recipiente que contém o ficheiro de dados de entrada. O nome do contentor tem o formato input-PROJECT_ID.

  9. No campo Conta de serviço, selecione a conta de serviço que criou anteriormente.

    A conta de serviço funciona como a identidade do acionador. Já deve ter concedido as seguintes funções à conta de serviço:

    • Eventarc Event Receiver: para receber eventos
    • Workflows Invoker: para executar fluxos de trabalho
  10. Clique em Guardar acionador.

    O acionador do Eventarc aparece agora na secção Acionadores na página Editar fluxo de trabalho.

  11. Clicar em Seguinte.

  12. Clique em Implementar.

gcloud

Crie um acionador do Eventarc executando o seguinte comando:

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

Substitua o seguinte:

  • PROJECT_ID: o ID do seu Google Cloud projeto
  • SERVICE_ACCOUNT_NAME: o nome da conta de serviço que criou anteriormente.

A conta de serviço funciona como a identidade do acionador. Já deve ter concedido as seguintes funções à conta de serviço:

  • roles/eventarc.eventReceiver: para receber eventos
  • roles/workflows.invoker: para executar fluxos de trabalho

Terraform

Para criar um acionador, use o recurso google_eventarc_trigger e modifique o ficheiro main.tf, conforme mostrado no exemplo seguinte.

Para saber como aplicar ou remover uma configuração do Terraform, consulte os comandos básicos do Terraform.

Tenha em atenção que, num fluxo de trabalho típico do Terraform, aplica todo o plano de uma só vez. No entanto, para os fins deste tutorial, pode segmentar um recurso específico. Por exemplo:

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

}

Sempre que um ficheiro é carregado ou substituído no contentor do Cloud Storage que contém o ficheiro de dados de entrada, o fluxo de trabalho é executado com o evento do Cloud Storage correspondente como argumento.

Acione o fluxo de trabalho

Teste o sistema ponto a ponto atualizando o ficheiro de dados de entrada no Google Cloud Storage.

  1. Gere novos dados para o ficheiro de entrada e carregue-os para o Cloud Storage na localização esperada pela tarefa do Cloud Run:

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

    Se criou um contentor do Cloud Storage com o Terraform, pode obter o nome do contentor executando o seguinte comando:

    gcloud storage buckets list gs://input*

    A tarefa do Cloud Run pode demorar alguns minutos a ser executada.

  2. Confirme que a tarefa do Cloud Run foi executada conforme esperado, consultando as execuções da tarefa:

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

    Deverá ver uma execução bem-sucedida da tarefa no resultado, o que indica que 10/10 tarefas foram concluídas.

Saiba como acionar um fluxo de trabalho com eventos ou mensagens do Pub/Sub.