Execute uma tarefa em lote através dos Workflows

O Batch é um serviço totalmente gerido que lhe permite agendar, colocar em fila e executar cargas de trabalho de processamento em lote em instâncias de máquinas virtuais (VMs) do Compute Engine. Aprovisiona recursos em lote e gere a capacidade em seu nome, o que permite que as cargas de trabalho em lote sejam executadas em grande escala.

Os fluxos de trabalho permitem-lhe executar os serviços de que precisa numa ordem que define, descrita através da sintaxe dos fluxos de trabalho.

Neste tutorial, vai usar o conetor Workflows para o Batch para agendar e executar uma tarefa do Batch que executa seis tarefas em paralelo em duas VMs do Compute Engine. A utilização de processos em lote e fluxos de trabalho permite-lhe combinar as vantagens que oferecem e aprovisionar e orquestrar de forma eficiente todo o processo.

Crie um repositório do Artifact Registry

Crie um repositório para armazenar a sua imagem de contentor Docker.

Consola

  1. Na Google Cloud consola, aceda à página Repositórios.

    Aceda a Repositórios

  2. Clique em Criar repositório.

  3. Introduza containers como o nome do repositório.

  4. Em Formato, escolha Docker.

  5. Para Tipo de localização, escolha Região.

  6. Na lista Região, selecione us-central1.

  7. Clique em Criar.

gcloud

Execute o seguinte comando:

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

Criou um repositório do Artifact Registry com o nome containers na região us-central1. Para mais informações sobre as regiões suportadas, consulte o artigo Localizações do Artifact Registry.

Obtenha os exemplos de código

Google Cloud armazena o código fonte da aplicação para este tutorial no GitHub. Pode clonar esse repositório ou transferir os exemplos.

  1. Clone o repositório da app de exemplo para a sua máquina local:

    git clone https://github.com/GoogleCloudPlatform/batch-samples.git
    

    Em alternativa, pode transferir os exemplos no ficheiro main.zip e extraí-los.

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

    cd batch-samples/primegen
    

Agora, tem o código-fonte da aplicação no seu ambiente de desenvolvimento.

Crie a imagem Docker com o Cloud Build

O Dockerfile contém as informações necessárias para criar uma imagem do Docker com o Cloud Build. Execute o seguinte comando para o criar:

gcloud builds submit \
  -t us-central1-docker.pkg.dev/PROJECT_ID/containers/primegen-service:v1 PrimeGenService/

Substitua PROJECT_ID pelo seu Google Cloud ID do projeto.

Quando a compilação estiver concluída, deverá ver um resultado semelhante ao seguinte:

DONE
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ID: a54818cc-5d14-467b-bfda-5fc9590af68c
CREATE_TIME: 2022-07-29T01:48:50+00:00
DURATION: 48S
SOURCE: gs://project-name_cloudbuild/source/1659059329.705219-17aee3a424a94679937a7200fab15bcf.tgz
IMAGES: us-central1-docker.pkg.dev/project-name/containers/primegen-service:v1
STATUS: SUCCESS

Usando um Dockerfile, criou uma imagem Docker denominada primegen-service e enviou a imagem para um repositório do Artifact Registry denominado containers.

Implemente um fluxo de trabalho que agende e execute uma tarefa em lote

O fluxo de trabalho seguinte agenda e executa uma tarefa em lote que executa um contentor Docker como seis tarefas em paralelo em duas VMs do Compute Engine. O resultado é a geração de seis lotes de números primos, armazenados num contentor do Cloud Storage.

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 batch-workflow.

  4. Na lista Região, selecione us-central1.

  5. Selecione a conta de serviço que criou anteriormente.

  6. Clicar em Seguinte.

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

    YAML

    main:
      params: [args]
      steps:
        - init:
            assign:
              - projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
              - region: "us-central1"
              - imageUri: ${region + "-docker.pkg.dev/" + projectId + "/containers/primegen-service:v1"}
              - jobId: ${"job-primegen-" + string(int(sys.now()))}
              - bucket: ${projectId + "-" + jobId}
        - createBucket:
            call: googleapis.storage.v1.buckets.insert
            args:
              query:
                project: ${projectId}
              body:
                name: ${bucket}
        - logCreateBucket:
            call: sys.log
            args:
              data: ${"Created bucket " + bucket}
        - logCreateBatchJob:
            call: sys.log
            args:
              data: ${"Creating and running the batch job " + jobId}
        - createAndRunBatchJob:
            call: googleapis.batch.v1.projects.locations.jobs.create
            args:
                parent: ${"projects/" + projectId + "/locations/" + region}
                jobId: ${jobId}
                body:
                  taskGroups:
                    taskSpec:
                      runnables:
                        - container:
                            imageUri: ${imageUri}
                          environment:
                            variables:
                              BUCKET: ${bucket}
                    # Run 6 tasks on 2 VMs
                    taskCount: 6
                    parallelism: 2
                  logsPolicy:
                    destination: CLOUD_LOGGING
            result: createAndRunBatchJobResponse
        # You can delete the batch job or keep it for debugging
        - logDeleteBatchJob:
            call: sys.log
            args:
              data: ${"Deleting the batch job " + jobId}
        - deleteBatchJob:
            call: googleapis.batch.v1.projects.locations.jobs.delete
            args:
                name: ${"projects/" + projectId + "/locations/" + region + "/jobs/" + jobId}
            result: deleteResult
        - returnResult:
            return:
              jobId: ${jobId}
              bucket: ${bucket}

    JSON

    {
      "main": {
        "params": [
          "args"
        ],
        "steps": [
          {
            "init": {
              "assign": [
                {
                  "projectId": "${sys.get_env(\"GOOGLE_CLOUD_PROJECT_ID\")}"
                },
                {
                  "region": "us-central1"
                },
                {
                  "imageUri": "${region + \"-docker.pkg.dev/\" + projectId + \"/containers/primegen-service:v1\"}"
                },
                {
                  "jobId": "${\"job-primegen-\" + string(int(sys.now()))}"
                },
                {
                  "bucket": "${projectId + \"-\" + jobId}"
                }
              ]
            }
          },
          {
            "createBucket": {
              "call": "googleapis.storage.v1.buckets.insert",
              "args": {
                "query": {
                  "project": "${projectId}"
                },
                "body": {
                  "name": "${bucket}"
                }
              }
            }
          },
          {
            "logCreateBucket": {
              "call": "sys.log",
              "args": {
                "data": "${\"Created bucket \" + bucket}"
              }
            }
          },
          {
            "logCreateBatchJob": {
              "call": "sys.log",
              "args": {
                "data": "${\"Creating and running the batch job \" + jobId}"
              }
            }
          },
          {
            "createAndRunBatchJob": {
              "call": "googleapis.batch.v1.projects.locations.jobs.create",
              "args": {
                "parent": "${\"projects/\" + projectId + \"/locations/\" + region}",
                "jobId": "${jobId}",
                "body": {
                  "taskGroups": {
                    "taskSpec": {
                      "runnables": [
                        {
                          "container": {
                            "imageUri": "${imageUri}"
                          },
                          "environment": {
                            "variables": {
                              "BUCKET": "${bucket}"
                            }
                          }
                        }
                      ]
                    },
                    "taskCount": 6,
                    "parallelism": 2
                  },
                  "logsPolicy": {
                    "destination": "CLOUD_LOGGING"
                  }
                }
              },
              "result": "createAndRunBatchJobResponse"
            }
          },
          {
            "logDeleteBatchJob": {
              "call": "sys.log",
              "args": {
                "data": "${\"Deleting the batch job \" + jobId}"
              }
            }
          },
          {
            "deleteBatchJob": {
              "call": "googleapis.batch.v1.projects.locations.jobs.delete",
              "args": {
                "name": "${\"projects/\" + projectId + \"/locations/\" + region + \"/jobs/\" + jobId}"
              },
              "result": "deleteResult"
            }
          },
          {
            "returnResult": {
              "return": {
                "jobId": "${jobId}",
                "bucket": "${bucket}"
              }
            }
          }
        ]
      }
    }
    
  8. Clique em Implementar.

gcloud

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

    touch batch-workflow.JSON_OR_YAML

    Substitua JSON_OR_YAML por yaml ou json, consoante o formato do seu fluxo de trabalho.

  2. Num editor de texto, copie o seguinte fluxo de trabalho para o ficheiro de código-fonte:

    YAML

    main:
      params: [args]
      steps:
        - init:
            assign:
              - projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
              - region: "us-central1"
              - imageUri: ${region + "-docker.pkg.dev/" + projectId + "/containers/primegen-service:v1"}
              - jobId: ${"job-primegen-" + string(int(sys.now()))}
              - bucket: ${projectId + "-" + jobId}
        - createBucket:
            call: googleapis.storage.v1.buckets.insert
            args:
              query:
                project: ${projectId}
              body:
                name: ${bucket}
        - logCreateBucket:
            call: sys.log
            args:
              data: ${"Created bucket " + bucket}
        - logCreateBatchJob:
            call: sys.log
            args:
              data: ${"Creating and running the batch job " + jobId}
        - createAndRunBatchJob:
            call: googleapis.batch.v1.projects.locations.jobs.create
            args:
                parent: ${"projects/" + projectId + "/locations/" + region}
                jobId: ${jobId}
                body:
                  taskGroups:
                    taskSpec:
                      runnables:
                        - container:
                            imageUri: ${imageUri}
                          environment:
                            variables:
                              BUCKET: ${bucket}
                    # Run 6 tasks on 2 VMs
                    taskCount: 6
                    parallelism: 2
                  logsPolicy:
                    destination: CLOUD_LOGGING
            result: createAndRunBatchJobResponse
        # You can delete the batch job or keep it for debugging
        - logDeleteBatchJob:
            call: sys.log
            args:
              data: ${"Deleting the batch job " + jobId}
        - deleteBatchJob:
            call: googleapis.batch.v1.projects.locations.jobs.delete
            args:
                name: ${"projects/" + projectId + "/locations/" + region + "/jobs/" + jobId}
            result: deleteResult
        - returnResult:
            return:
              jobId: ${jobId}
              bucket: ${bucket}

    JSON

    {
      "main": {
        "params": [
          "args"
        ],
        "steps": [
          {
            "init": {
              "assign": [
                {
                  "projectId": "${sys.get_env(\"GOOGLE_CLOUD_PROJECT_ID\")}"
                },
                {
                  "region": "us-central1"
                },
                {
                  "imageUri": "${region + \"-docker.pkg.dev/\" + projectId + \"/containers/primegen-service:v1\"}"
                },
                {
                  "jobId": "${\"job-primegen-\" + string(int(sys.now()))}"
                },
                {
                  "bucket": "${projectId + \"-\" + jobId}"
                }
              ]
            }
          },
          {
            "createBucket": {
              "call": "googleapis.storage.v1.buckets.insert",
              "args": {
                "query": {
                  "project": "${projectId}"
                },
                "body": {
                  "name": "${bucket}"
                }
              }
            }
          },
          {
            "logCreateBucket": {
              "call": "sys.log",
              "args": {
                "data": "${\"Created bucket \" + bucket}"
              }
            }
          },
          {
            "logCreateBatchJob": {
              "call": "sys.log",
              "args": {
                "data": "${\"Creating and running the batch job \" + jobId}"
              }
            }
          },
          {
            "createAndRunBatchJob": {
              "call": "googleapis.batch.v1.projects.locations.jobs.create",
              "args": {
                "parent": "${\"projects/\" + projectId + \"/locations/\" + region}",
                "jobId": "${jobId}",
                "body": {
                  "taskGroups": {
                    "taskSpec": {
                      "runnables": [
                        {
                          "container": {
                            "imageUri": "${imageUri}"
                          },
                          "environment": {
                            "variables": {
                              "BUCKET": "${bucket}"
                            }
                          }
                        }
                      ]
                    },
                    "taskCount": 6,
                    "parallelism": 2
                  },
                  "logsPolicy": {
                    "destination": "CLOUD_LOGGING"
                  }
                }
              },
              "result": "createAndRunBatchJobResponse"
            }
          },
          {
            "logDeleteBatchJob": {
              "call": "sys.log",
              "args": {
                "data": "${\"Deleting the batch job \" + jobId}"
              }
            }
          },
          {
            "deleteBatchJob": {
              "call": "googleapis.batch.v1.projects.locations.jobs.delete",
              "args": {
                "name": "${\"projects/\" + projectId + \"/locations/\" + region + \"/jobs/\" + jobId}"
              },
              "result": "deleteResult"
            }
          },
          {
            "returnResult": {
              "return": {
                "jobId": "${jobId}",
                "bucket": "${bucket}"
              }
            }
          }
        ]
      }
    }
    
  3. Implemente o fluxo de trabalho introduzindo o seguinte comando:

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

    Substitua SERVICE_ACCOUNT_NAME pelo nome da conta de serviço que criou anteriormente.

Execute o fluxo de trabalho

A execução de um fluxo de trabalho executa a definição do fluxo de trabalho atual associada ao fluxo de trabalho.

Consola

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

    Aceda a Fluxos de trabalho

  2. Na página Fluxos de trabalho, clique no fluxo de trabalho batch-workflow para aceder à respetiva página de detalhes.

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

  4. Clique novamente em Executar.

    A execução do fluxo de trabalho deve demorar alguns minutos.

  5. Veja os resultados do fluxo de trabalho no painel Saída.

    Os resultados devem ter um aspeto semelhante ao seguinte:

    {
      "bucket": "project-name-job-primegen-TIMESTAMP",
      "jobId": "job-primegen-TIMESTAMP"
    }
    

gcloud

  1. Execute o fluxo de trabalho:

    gcloud workflows run batch-workflow \
      --location=us-central1

    A execução do fluxo de trabalho deve demorar alguns minutos.

  2. Pode verificar o estado de uma execução de longa duração.

  3. Para obter o estado da última execução concluída, execute o seguinte comando:

    gcloud workflows executions describe-last

    Os resultados devem ser semelhantes aos seguintes:

    name: projects/PROJECT_NUMBER/locations/us-central1/workflows/batch-workflow/executions/EXECUTION_ID
    result: '{"bucket":"project-name-job-primegen-TIMESTAMP","jobId":"job-primegen-TIMESTAMP"}'
    startTime: '2022-07-29T16:08:39.725306421Z'
    state: SUCCEEDED
    status:
      currentSteps:
      - routine: main
        step: returnResult
    workflowRevisionId: 000001-9ba
    

Indique os objetos no contentor de saída

Pode confirmar que os resultados são os esperados listando os objetos no seu contentor de saída do Cloud Storage.

Consola

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

    Aceda a Recipientes

  2. Na lista de contentores, clique no nome do contentor cujo conteúdo quer ver.

    Os resultados devem ser semelhantes aos seguintes, com um total de seis ficheiros e cada ficha a representar um lote de 10 000 números primos:

    primes-1-10000.txt
    primes-10001-20000.txt
    primes-20001-30000.txt
    primes-30001-40000.txt
    primes-40001-50000.txt
    primes-50001-60000.txt
    

gcloud

  1. Obtenha o nome do contentor de saída:

    gcloud storage ls

    O resultado é semelhante ao seguinte:

    gs://PROJECT_ID-job-primegen-TIMESTAMP/

  2. Liste os objetos no seu contentor de saída:

    gcloud storage ls gs://PROJECT_ID-job-primegen-TIMESTAMP/** --recursive

    Substitua TIMESTAMP pela data/hora devolvida pelo comando anterior.

    A saída deve ser semelhante à seguinte, com seis ficheiros no total e cada um a listar um lote de 10 000 números primos:

    gs://project-name-job-primegen-TIMESTAMP/primes-1-10000.txt
    gs://project-name-job-primegen-TIMESTAMP/primes-10001-20000.txt
    gs://project-name-job-primegen-TIMESTAMP/primes-20001-30000.txt
    gs://project-name-job-primegen-TIMESTAMP/primes-30001-40000.txt
    gs://project-name-job-primegen-TIMESTAMP/primes-40001-50000.txt
    gs://project-name-job-primegen-TIMESTAMP/primes-50001-60000.txt