Crie uma orquestração baseada em eventos com o Eventarc e o Workflows

1. Introdução

f2f35f5c40b91a3c.png c637dcc97f298e7e.png c4a9d5b95f111710.png

O Eventarc facilita a conexão de serviços do Cloud Run com eventos de várias fontes. Ele permite criar arquiteturas orientadas a eventos em que os microsserviços são distribuídos e têm acoplamento flexível. Ele cuida da ingestão, entrega, segurança, autorização e tratamento de erros de eventos para você.

O Workflows é uma plataforma de orquestração totalmente gerenciada que executa serviços na ordem definida por você: um fluxo de trabalho. Esses fluxos de trabalho podem combinar serviços hospedados no Cloud Run ou no Cloud Functions, serviços do Google Cloud como o Cloud Vision AI e o BigQuery, além de qualquer API baseada em HTTP.

Neste codelab, você vai criar uma orquestração de microsserviços orientada por eventos para processar imagens. Você vai usar o Workflows para orquestrar a ordem, as entradas e as saídas de quatro Cloud Functions de processamento de imagens. Em seguida, você vai ativar a orquestração para responder a eventos do Cloud Storage de maneira flexível com o Eventarc.

No final, você terá uma arquitetura sem servidor flexível, mas estruturada, para processar imagens.

b75a14a4268cbe73.png

O que você vai aprender

  • Visão geral do Eventarc e dos fluxos de trabalho
  • Como implantar serviços do Cloud Functions
  • Como orquestrar serviços usando o Workflows
  • Como fazer o Workflows responder a eventos do Cloud Storage com o Eventarc

2. Configuração e requisitos

Configuração de ambiente personalizada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

295004821bab6a87.png

37d264871000675d.png

96d86d3d5655cdbe.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google e pode ser atualizada quando você quiser.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto.
  • Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não vai ser muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou exclua o projeto. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Iniciar o Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

No Console do Google Cloud, clique no ícone do Cloud Shell na barra de ferramentas superior à direita:

Ativar o Cloud Shell

O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:

Captura de tela do terminal do Google Cloud Shell mostrando que o ambiente foi conectado

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Neste codelab, todo o trabalho pode ser feito com um navegador. Você não precisa instalar nada.

Configurar a gcloud

No Cloud Shell, defina o ID do projeto e a região em que você quer implantar o aplicativo. Salve-as como variáveis PROJECT_ID e REGION. Consulte Locais do Cloud Functions para ver as regiões disponíveis.

PROJECT_ID=your-project-id
gcloud config set project $PROJECT_ID

Conseguir o código-fonte

O código-fonte do aplicativo está na pasta processing-pipelines do repositório eventarc-samples.

Clone o repositório:

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

Navegue até a pasta eventarc-samples/processing-pipelines:

cd eventarc-samples/processing-pipelines

3. Visão geral da arquitetura

A arquitetura do aplicativo é a seguinte:

7b810e1505054c0c.png

  1. Uma imagem é salva em um bucket de entrada que gera um evento de criação do Cloud Storage.
  2. O evento de criação do Cloud Storage é lido pelo Eventarc usando um gatilho do Cloud Storage e transmitido para o Workflows como um CloudEvent.
  3. Na primeira etapa do fluxo de trabalho, Filter, um serviço do Cloud Functions, usa a API Vision para determinar se a imagem é segura. Se a imagem for segura, o Workflows vai continuar com as próximas etapas.
  4. Na segunda etapa do fluxo de trabalho, Labeler, um serviço do Cloud Functions, extrai os rótulos da imagem com a API Vision e os salva no bucket de saída.
  5. Na terceira etapa, Resizer, outro serviço do Cloud Functions, redimensiona a imagem usando o ImageSharp e salva a imagem redimensionada no bucket de saída.
  6. Na última etapa, o Watermarker, outro serviço do Cloud Functions, adiciona uma marca d'água de rótulos do Labeler à imagem redimensionada usando o ImageSharp e salva a imagem no bucket de saída.

O aplicativo é acionado por um evento do Cloud Storage, portanto, é orientado a eventos. O processamento de imagens acontece em um fluxo de trabalho, portanto, é uma orquestração. No final, é uma orquestração orientada a eventos para uma arquitetura sem servidor flexível, mas estruturada, para processar imagens.

4. Criar buckets

Crie um bucket de entrada para os usuários fazerem upload das imagens e um bucket de saída para o pipeline de processamento de imagens salvar as imagens processadas.

Execute o seguinte no Cloud Shell:

REGION=us-central1
BUCKET1=$PROJECT_ID-images-input-$RANDOM
BUCKET2=$PROJECT_ID-images-output-$RANDOM

gsutil mb -l $REGION gs://$BUCKET1
gsutil mb -l $REGION gs://$BUCKET2

5. Implantar serviço de filtro

Vamos começar implantando o primeiro serviço. Esse serviço do Cloud Functions recebe as informações do bucket e do arquivo, determina se a imagem é segura com a API Vision e retorna o resultado.

Primeiro, ative os serviços necessários para o Cloud Functions gen2 e a API Vision:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  run.googleapis.com \
  vision.googleapis.com

Dentro da pasta de nível superior processing-pipelines, implante o serviço:

SERVICE_NAME=filter

gcloud functions deploy $SERVICE_NAME \
  --gen2 \
  --allow-unauthenticated \
  --runtime dotnet3 \
  --trigger-http \
  --region=$REGION \
  --entry-point Filter.Function \
  --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp

Depois que a função for implantada, defina o URL do serviço em uma variável. Vamos precisar dela mais tarde:

FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')

6. Implantar o serviço de rotulagem

O segundo serviço do Cloud Functions recebe as informações do bucket e do arquivo, extrai os rótulos da imagem com a API Vision e salva os rótulos no bucket de saída.

Dentro da pasta de nível superior processing-pipelines, implante o serviço:

SERVICE_NAME=labeler

gcloud functions deploy $SERVICE_NAME \
  --gen2 \
  --allow-unauthenticated \
  --runtime dotnet3 \
  --trigger-http \
  --region=$REGION \
  --set-env-vars BUCKET=$BUCKET2 \
  --entry-point Labeler.Function \
  --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp

Depois que a função for implantada, defina o URL do serviço em uma variável. Vamos precisar dela mais tarde:

LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')

7. Implantar o serviço de redimensionamento

Esse serviço do Cloud Functions recebe as informações do bucket e do arquivo, redimensiona a imagem usando o ImageSharp e salva a imagem no bucket de saída.

Dentro da pasta de nível superior processing-pipelines, implante o serviço:

SERVICE_NAME=resizer

gcloud functions deploy $SERVICE_NAME \
  --gen2 \
  --allow-unauthenticated \
  --runtime dotnet3 \
  --trigger-http \
  --region=$REGION \
  --set-env-vars BUCKET=$BUCKET2 \
  --entry-point Resizer.Function \
  --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \
  --timeout=120s

Observe o valor timeout de dois minutos para permitir que a função de redimensionamento tenha mais tempo para processamento.

Depois que a função for implantada, defina o URL do serviço em uma variável. Vamos precisar dela mais tarde:

RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')

8. Implantar o serviço de marca-d'água

Esse serviço do Cloud Functions recebe as informações de bucket, arquivo e rótulos, lê o arquivo, adiciona os rótulos como marca d'água à imagem usando ImageSharp e salva a imagem no bucket de saída.

Dentro da pasta de nível superior processing-pipelines, implante o serviço:

SERVICE_NAME=watermarker

gcloud functions deploy $SERVICE_NAME \
  --gen2 \
  --allow-unauthenticated \
  --runtime dotnet3 \
  --trigger-http \
  --region=$REGION \
  --set-env-vars BUCKET=$BUCKET2 \
  --entry-point Watermarker.Function \
  --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp

Depois que a função for implantada, defina o URL do serviço em uma variável. Vamos precisar dela mais tarde:

WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')

Neste ponto, todas as quatro funções do Cloud precisam estar implantadas e em execução:

fe662925cb0121e9.png

9. Definir e implantar o fluxo de trabalho

Use o Workflows para reunir serviços de filtro, rotulagem, redimensionamento e marca d'água em um fluxo de trabalho. O Workflows vai orquestrar a chamada desses serviços na ordem e com os parâmetros definidos.

Primeiro, ative os serviços necessários para o Workflows:

gcloud services enable \
  workflows.googleapis.com \
  workflowexecutions.googleapis.com

Definir

O Workflows recebe um CloudEvent como parâmetro. Isso virá do Eventarc assim que criarmos um gatilho. Nas duas primeiras etapas, o Workflows registra o evento e extrai as informações do bucket e do arquivo dele:

main:
  params: [event]
  steps:
  - log_event:
      call: sys.log
      args:
          text: ${event}
          severity: INFO
  - extract_bucket_and_file:
      assign:
      - bucket: ${event.data.bucket}
      - file: ${event.data.name}

Na etapa filter, o Workflows faz uma chamada para o serviço de filtro que implantamos anteriormente. Em seguida, ele registra e verifica a segurança do arquivo:

  - filter:
      call: http.post
      args:
        url: FILTER_URL # TODO: Replace
        auth:
          type: OIDC
        body:
            bucket: ${bucket}
            file: ${file}
      result: filterResponse
  - log_safety:
      call: sys.log
      args:
          text: ${filterResponse.body.safe}
          severity: INFO
  - check_safety:
      switch:
        - condition: ${filterResponse.body.safe == true}
          next: label
      next: end

Na etapa label, o Workflows faz uma chamada para o serviço de rotulagem e captura a resposta (três principais rótulos):

  - label:
      call: http.post
      args:
        url: LABELER_URL # TODO: Replace
        auth:
          type: OIDC
        body:
            bucket: ${bucket}
            file: ${file}
      result: labelResponse

Na etapa resize, o Workflows faz uma chamada para o serviço de redimensionamento e captura a resposta (o bucket e o arquivo da imagem redimensionada):

  - resize:
      call: http.post
      args:
        url: RESIZER_URL # TODO: Replace
        auth:
          type: OIDC
        body:
            bucket: ${bucket}
            file: ${file}
      result: resizeResponse

Na etapa watermark, o Workflows chama o serviço de marca-d'água com a imagem redimensionada e os rótulos e captura o resultado (a imagem redimensionada e com marca-d'água):

  - watermark:
      call: http.post
      args:
        url: WATERMARKER_URL # TODO: Replace
        auth:
          type: OIDC
        body:
            bucket: ${resizeResponse.body.bucket}
            file: ${resizeResponse.body.file}
            labels: ${labelResponse.body.labels}
      result: watermarkResponse

Na etapa final, o Workflows retorna o código de status HTTP dos serviços de rotulagem, redimensionamento e marca d'água:

  - final:
      return:
        label: ${labelResponse.code}
        resize: ${resizeResponse.code}
        watermark: ${watermarkResponse.code}

Implantar

Antes de implantar o fluxo de trabalho, verifique se os URLs de serviço foram substituídos por URLs das funções implantadas manualmente ou usando sed:

Na pasta de nível superior processing-pipelines, navegue até a pasta image-v3, onde o arquivo workflows.yaml está localizado:

cd image-v3/

Execute sed para substituir os URLs de marcador de posição pelos URLs reais dos serviços implantados:

sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml
sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml
sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml
sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml

Implante o fluxo de trabalho:

WORKFLOW_NAME=image-processing

gcloud workflows deploy $WORKFLOW_NAME \
    --source=workflow.yaml \
    --location=$REGION

Em alguns segundos, o fluxo de trabalho implantado vai aparecer no console:

a5f537f2b3f3bd3.png

10. Criar gatilho

Agora que o fluxo de trabalho foi implantado, a última etapa é conectá-lo a eventos do Cloud Storage com um gatilho do Eventarc.

Configuração única

Primeiro, ative os serviços necessários para o Eventarc:

gcloud services enable \
 eventarc.googleapis.com

Crie uma conta de serviço que será usada no gatilho do Eventarc.

SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Eventarc trigger image processing service account"

Conceda o papel workflows.invoker para que a conta de serviço possa ser usada para invocar fluxos de trabalho do Eventarc:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --role roles/workflows.invoker \
  --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

Conceda o papel eventarc.eventReceiver para que a conta de serviço possa ser usada em um

Gatilho do Cloud Storage:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --role roles/eventarc.eventReceiver \
  --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

Conceda o papel pubsub.publisher à conta de serviço do Cloud Storage. Isso é necessário para o gatilho do Cloud Storage do Eventarc:

STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)"

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:$STORAGE_SERVICE_ACCOUNT \
    --role roles/pubsub.publisher

Criar

Execute o comando a seguir para criar um gatilho. Esse gatilho filtra eventos de criação de arquivos do bucket de entrada do Cloud Storage e os transmite para o fluxo de trabalho que definimos anteriormente:

TRIGGER_NAME=trigger-image-processing

gcloud eventarc triggers create $TRIGGER_NAME \
  --location=$REGION \
  --destination-workflow=$WORKFLOW_NAME \
  --destination-workflow-location=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.finalized" \
  --event-filters="bucket=$BUCKET1" \
  --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

É possível ver que o gatilho foi criado e está pronto na seção do Eventarc no Console do Cloud:

a5f4301863d7d9e4.png

11. Testar o pipeline

O pipeline de processamento de imagens está pronto para receber eventos do Cloud Storage. Para testar o pipeline, faça upload de uma imagem para o bucket de entrada:

gsutil cp beach.jpg gs://$BUCKET1

Assim que você fizer upload da imagem, uma execução do Workflows vai aparecer no estado ativo:

2c914341950b5fde.png

Depois de um minuto, a execução será concluída. Também é possível conferir a entrada e a saída do fluxo de trabalho:

9abba6c28c51a9b5.png

Se você listar o conteúdo do bucket de saída, vai encontrar a imagem redimensionada, a imagem redimensionada e com marca-d'água e os rótulos da imagem:

gsutil ls gs://$BUCKET2

gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400-watermark.jpeg
gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400.png
gs://$PROJECT_ID-images-output-$RANDOM/beach-labels.txt

Para verificar novamente, abra a imagem redimensionada e com marca-d'água para conferir o resultado:

46d375cb05a8aae4.jpeg

12. Parabéns

Parabéns, você concluiu o codelab.

O que aprendemos

  • Visão geral do Eventarc e dos fluxos de trabalho
  • Como implantar serviços do Cloud Functions
  • Como orquestrar serviços usando o Workflows
  • Como fazer o Workflows responder a eventos do Cloud Storage com o Eventarc