Créer une orchestration basée sur des événements avec Eventarc et Workflows

1. Introduction

cb762f29e9183a3f.png 1c05e3d0c2bd2b45.png a03f943ca09ac4c.png

Eventarc facilite la connexion des services Cloud Run à des événements provenant de différentes sources. Il vous permet de créer des architectures basées sur des événements dans lesquelles des microservices sont faiblement couplés et distribués. Il gère pour vous l'ingestion, la diffusion, la sécurité, l'autorisation et la gestion des erreurs des événements.

Workflows est une plate-forme d'orchestration entièrement gérée qui exécute les services dans un ordre que vous définissez: un workflow. Ces workflows peuvent combiner des services hébergés sur Cloud Run ou Cloud Functions, des services Google Cloud tels que Cloud Vision AI et BigQuery, et n'importe quelle API HTTP.

Dans cet atelier de programmation, vous allez créer une orchestration de microservices basée sur des événements pour traiter les images. Vous utiliserez Workflows pour orchestrer l'ordre, les entrées et les sorties de quatre fonctions de traitement d'images Cloud Functions. Vous permettrez ensuite à l'orchestration de répondre aux événements Cloud Storage de manière faiblement couplée avec Eventarc.

Au final, vous vous retrouverez avec une architecture sans serveur flexible et structurée pour traiter les images.

e372ceed8c26c5fb.png

Points abordés

  • Présentation d'Eventarc et de Workflows
  • Déployer des services Cloud Functions
  • Orchestrer des services à l'aide de Workflows
  • Faire en sorte que Workflows réponde aux événements Cloud Storage avec Eventarc

2. Préparation

Configuration de l'environnement d'auto-formation

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pouvez le modifier à tout moment.
  • L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Cloud génère automatiquement une chaîne unique. généralement, vous ne vous souciez pas de ce que c’est. Dans la plupart des ateliers de programmation, vous devrez référencer l'ID du projet (il est généralement identifié comme PROJECT_ID). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre au hasard. Vous pouvez également essayer la vôtre pour voir si elle est disponible. Il ne peut pas être modifié après cette étape et restera actif pendant toute la durée du projet.
  • Pour votre information, il existe une troisième valeur, le numéro de projet, utilisé par certaines API. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour arrêter les ressources afin d'éviter que des frais ne vous soient facturés au-delà de ce tutoriel, vous pouvez supprimer les ressources que vous avez créées ou l'ensemble du projet. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai gratuit pour bénéficier d'un crédit de 300 $.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Dans la console Google Cloud, cliquez sur l'icône Cloud Shell dans la barre d'outils supérieure :

55efc1aaa7a4d3ad.png

Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :

7ffe5cbb04455448.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez effectuer toutes les tâches de cet atelier de programmation dans un navigateur. Vous n'avez rien à installer.

Configurer gcloud

Dans Cloud Shell, définissez l'ID de votre projet et la région dans laquelle vous souhaitez déployer votre application. Enregistrez-les en tant que variables PROJECT_ID et REGION. Consultez la page Emplacements Cloud Functions pour connaître les régions disponibles.

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

Obtenir le code source

Le code source de l'application se trouve dans le dossier processing-pipelines du dépôt eventarc-samples.

Clonez le dépôt :

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

Accédez au dossier eventarc-samples/processing-pipelines :

cd eventarc-samples/processing-pipelines

3. Présentation de l'architecture

L'architecture de l'application est la suivante:

6aa6fbc7721dd6b6.png

  1. Une image est enregistrée dans un bucket d'entrée qui génère un événement de création Cloud Storage.
  2. L'événement de création Cloud Storage est lu par Eventarc via un déclencheur Cloud Storage, puis transmis à Workflows en tant que CloudEvent.
  3. Lors de la première étape du workflow, Filter, un service Cloud Functions, utilise l'API Vision pour déterminer si l'image est sûre. Si l'image ne présente aucun risque, Workflows passe aux étapes suivantes.
  4. Lors de la deuxième étape du workflow, Labeler, un service Cloud Functions, extrait les étiquettes de l'image avec l'API Vision et les enregistre dans le bucket de sortie.
  5. Lors de la troisième étape, Resizer, un autre service Cloud Functions, redimensionne l'image à l'aide d'ImageSharp et l'enregistre dans le bucket de sortie.
  6. Lors de la dernière étape, Watermarker, un autre service Cloud Functions, ajoute un filigrane d'étiquettes de Labeler à l'image redimensionnée à l'aide d'ImageSharp et enregistre l'image dans le bucket de sortie.

L'application est déclenchée par un événement Cloud Storage. Elle est donc basée sur des événements. Le traitement des images s'effectue dans un workflow, il s'agit donc d'une orchestration. En fin de compte, il s'agit d'une orchestration basée sur des événements pour une architecture sans serveur flexible et structurée permettant de traiter les images.

4. Créer des buckets

Créez un bucket d'entrée dans lequel les utilisateurs pourront importer les images, et un bucket de sortie pour le pipeline de traitement des images afin d'enregistrer les images traitées.

Exécutez la commande suivante dans Cloud Shell :

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

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

5. Déployer le service de filtre

Commençons par déployer le premier service. Ce service Cloud Functions reçoit les informations sur le bucket et le fichier, détermine si l'image est sûre avec l'API Vision et renvoie le résultat.

Commencez par activer les services requis pour Cloud Functions 2e génération et l'API Vision:

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

Dans le dossier racine processing-pipelines, déployez le service:

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

Une fois la fonction déployée, définissez l'URL du service dans une variable. Nous en aurons besoin ultérieurement:

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

6. Déployer le service d'étiqueteur

Le second service Cloud Functions reçoit les informations sur le bucket et le fichier, extrait les étiquettes de l'image avec l'API Vision et les enregistre dans le bucket de sortie.

Dans le dossier racine processing-pipelines, déployez le service:

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

Une fois la fonction déployée, définissez l'URL du service dans une variable. Nous en aurons besoin ultérieurement:

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

7. Déployer le service redimensionnement

Ce service Cloud Functions reçoit les informations sur le bucket et le fichier, redimensionne l'image avec ImageSharp et l'enregistre dans le bucket de sortie.

Dans le dossier racine processing-pipelines, déployez le service:

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

Notez que la valeur timeout est de deux minutes afin de laisser plus de temps au traitement de la fonction de redimensionnement.

Une fois la fonction déployée, définissez l'URL du service dans une variable. Nous en aurons besoin ultérieurement:

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

8. Déployer le service de filigrane

Ce service Cloud Functions reçoit les informations sur le bucket, le fichier et les étiquettes, lit le fichier, ajoute les étiquettes en filigrane à l'image à l'aide d'ImageSharp, puis enregistre l'image dans le bucket de sortie.

Dans le dossier racine processing-pipelines, déployez le service:

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

Une fois la fonction déployée, définissez l'URL du service dans une variable. Nous en aurons besoin ultérieurement:

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

À ce stade, les quatre fonctions Cloud doivent être déployées et en cours d'exécution:

76a218568982c90c.png

9. Définir et déployer le workflow

Utilisez Workflows pour regrouper les services de filtre, d'étiqueteur, de redimensionnement et de filigrane dans un workflow. Les workflows orchestrent les appels de ces services dans l'ordre et avec les paramètres que nous définissons.

Commencez par activer les services requis pour Workflows:

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

Définir

Workflows reçoit un CloudEvent en tant que paramètre. Il proviendra d'Eventarc une fois que nous aurons créé un déclencheur. Au cours des deux premières étapes, Workflows consigne l'événement et en extrait les informations sur le bucket et le fichier:

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}

À l'étape filter, Workflows appelle le service de filtrage que nous avons déployé précédemment. Il consigne et vérifie ensuite la sécurité des fichiers:

  - 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

À l'étape label, Workflows appelle le service d'étiqueteur et capture la réponse (trois étiquettes principales):

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

À l'étape resize, Workflows appelle le service redimensionner et capture la réponse (le bucket et le fichier de l'image redimensionnée):

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

À l'étape watermark, Workflows appelle le service de filigrane avec l'image redimensionnée et les étiquettes, puis capture le résultat (l'image redimensionnée et en filigrane):

  - 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

À l'étape final, Workflows renvoie le code d'état HTTP des services étiqueteurs, redimensionnements et filigranes:

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

Déployer

Avant de déployer le workflow, assurez-vous de remplacer les URL de service par les URL des fonctions déployées, manuellement ou à l'aide de sed:

Dans le dossier racine processing-pipelines, accédez au dossier image-v3 où se trouve le fichier workflows.yaml:

cd image-v3/

Exécutez sed pour remplacer les URL d'espace réservé par les URL réelles des services déployés:

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

Déployez le workflow :

WORKFLOW_NAME=image-processing

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

Après quelques secondes, vous devriez voir le workflow déployé dans la console:

92cf4e758bdc3dde.png

10. Créer un déclencheur

Maintenant que le workflow est déployé, la dernière étape consiste à le connecter aux événements Cloud Storage à l'aide d'un déclencheur Eventarc.

Configuration unique

Commencez par activer les services requis pour Eventarc:

gcloud services enable \
 eventarc.googleapis.com

Créez un compte de service que vous utiliserez dans le déclencheur Eventarc.

SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa

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

Attribuez le rôle workflows.invoker afin que le compte de service puisse être utilisé pour appeler des workflows à partir d'Eventarc:

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

Accordez le rôle eventarc.eventReceiver pour que le compte de service puisse être utilisé dans un

Déclencheur Cloud Storage:

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

Accordez le rôle pubsub.publisher au compte de service Cloud Storage. Cette opération est nécessaire pour le déclencheur Cloud Storage d'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

Créer

Exécutez la commande suivante pour créer un déclencheur. Ce déclencheur filtre les événements de création de fichiers issus du bucket Cloud Storage d'entrée et les transmet au workflow que nous avons défini précédemment:

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

Vous pouvez constater que le déclencheur est créé et prêt dans la section Eventarc de Cloud Console:

14330c4fa2451bc0.png

11. Tester le pipeline

Le pipeline de traitement d'images est prêt à recevoir des événements de Cloud Storage. Pour tester le pipeline, importez une image dans le bucket d'entrée:

gsutil cp beach.jpg gs://$BUCKET1

Dès que vous importez l'image, vous devriez voir une exécution de Workflows à l'état actif:

36d07cb63c39e7d9.png

Au bout d'une minute environ, l'exécution doit s'effectuer correctement. Vous pouvez également afficher l'entrée et la sortie du workflow:

229200c79d989c25.png

Si vous listez le contenu du bucket de sortie, vous devriez voir l'image redimensionnée, l'image redimensionnée avec un filigrane, ainsi que les étiquettes de l'image:

gsutil ls gs://$BUCKET2

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

Pour vérifier, ouvrez l'image redimensionnée avec un filigrane pour voir le résultat:

75f3c0019ca842ce.jpeg

12. Félicitations

Félicitations, vous avez terminé cet atelier de programmation.

Points abordés

  • Présentation d'Eventarc et de Workflows
  • Déployer des services Cloud Functions
  • Orchestrer des services à l'aide de Workflows
  • Faire en sorte que Workflows réponde aux événements Cloud Storage avec Eventarc