1. Introduction
Workflows vous permet de créer des workflows sans serveur qui associent une série de tâches sans serveur dans un ordre que vous définissez. Vous pouvez combiner la puissance des API Google Cloud, des produits sans serveur tels que Cloud Functions et Cloud Run, et des appels à des API externes pour créer des applications sans serveur flexibles.
Les workflows ne nécessitent aucune gestion de l'infrastructure et s'adaptent parfaitement à la demande, y compris en cas de scaling à zéro instance. Avec son modèle de paiement à l'utilisation, vous ne payez que pour la durée d'exécution.
Dans cet atelier de programmation, vous allez apprendre à connecter divers services Google Cloud et API HTTP externes à Workflows. Plus précisément, vous allez connecter deux services Cloud Functions publics, un service Cloud Run privé et une API HTTP publique externe dans un workflow.
Points abordés
- Principes de base des workflows.
- Connecter des fonctions Cloud publiques à Workflows
- Connecter des services Cloud Run privés avec Workflows
- Connecter des API HTTP externes avec Workflows
2. Préparation
Configuration de l'environnement d'auto-formation
- Connectez-vous à Cloud Console, puis créez un projet ou réutilisez un projet existant. (Si vous n'avez pas encore de compte Gmail ou G Suite, vous devez en créer un.)
Mémorisez l'ID du projet. Il s'agit d'un nom unique permettant de différencier chaque projet Google Cloud (le nom ci-dessus est déjà pris ; vous devez en trouver un autre). Il sera désigné par le nom PROJECT_ID
tout au long de cet atelier de programmation.
- Vous devez ensuite activer la facturation dans Cloud Console pour pouvoir utiliser les ressources Google Cloud.
L'exécution de cet atelier de programmation est très peu coûteuse, voire gratuite. Veillez à suivre les instructions de la section "Nettoyer" qui indique comment désactiver les ressources afin d'éviter les frais une fois ce tutoriel terminé. 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.
Depuis la console GCP, cliquez sur l'icône Cloud Shell de la barre d'outils située dans l'angle supérieur droit :
Le provisionnement et la connexion à l'environnement prennent quelques instants seulement. Une fois l'opération terminée, le résultat devrait ressembler à ceci :
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 réaliser toutes les activités de cet atelier dans un simple navigateur.
3. Présentation des workflows
Principes de base
Un workflow est composé d'une série d'étapes décrites à l'aide de la syntaxe basée sur YAML de Workflows. Il s'agit de la définition du workflow. Pour en savoir plus sur la syntaxe YAML de Workflows, consultez la page de référence sur la syntaxe.
Lorsqu'un workflow est créé, il est déployé, ce qui le prépare à être exécuté. Il s'agit d'une exécution unique de la logique contenue dans la définition d'un workflow. Toutes les exécutions de workflow sont indépendantes, et le produit accepte un grand nombre d'exécutions simultanées.
Activer des services
Dans cet atelier de programmation, vous allez connecter Cloud Functions et des services Cloud Run à Workflows. Vous utiliserez également Cloud Build et Cloud Storage lors de la création de services.
Activez tous les services nécessaires :
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
À l'étape suivante, vous allez connecter deux fonctions Cloud dans un workflow.
4. Déployer la première fonction Cloud
La première fonction est un générateur de nombres aléatoires en Python.
Créez un répertoire pour le code de la fonction et accédez-y:
mkdir ~/randomgen cd ~/randomgen
Dans le répertoire, créez un fichier main.py
avec le contenu suivant:
import random, json from flask import jsonify def randomgen(request): randomNum = random.randint(1,100) output = {"random":randomNum} return jsonify(output)
Lorsqu'elle reçoit une requête HTTP, cette fonction génère un nombre aléatoire compris entre 1 et 100 et la renvoie au format JSON à l'appelant.
La fonction s'appuie sur Flask pour le traitement HTTP et nous devons l'ajouter en tant que dépendance. Dans Python, les dépendances sont gérées avec pip et exprimées dans un fichier de métadonnées appelé requirements.txt
.
Dans le même répertoire, créez un fichier requirements.txt
avec le contenu suivant:
flask>=1.0.2
Déployez la fonction avec un déclencheur HTTP et en autorisant les requêtes non authentifiées à l'aide de cette commande:
gcloud functions deploy randomgen \ --runtime python37 \ --trigger-http \ --allow-unauthenticated
Une fois la fonction déployée, vous pouvez voir son URL sous la propriété httpsTrigger.url
affichée dans la console ou avec la commande gcloud functions describe
.
Vous pouvez également accéder à cette URL de la fonction à l'aide de la commande curl
suivante:
curl $(gcloud functions describe randomgen --format='value(httpsTrigger.url)')
La fonction est prête pour le workflow.
5. Déployer une deuxième fonction Cloud
La seconde fonction est un multiplicateur. Elle multiplie l'entrée reçue par 2.
Créez un répertoire pour le code de la fonction et accédez-y:
mkdir ~/multiply cd ~/multiply
Dans le répertoire, créez un fichier main.py
avec le contenu suivant:
import random, json from flask import jsonify def multiply(request): request_json = request.get_json() output = {"multiplied":2*request_json['input']} return jsonify(output)
Lorsqu'elle reçoit une requête HTTP, cette fonction extrait la valeur input
du corps JSON, la multiplie par 2 et la renvoie au format JSON à l'appelant.
Créez le même fichier requirements.txt
dans le même répertoire avec le contenu suivant:
flask>=1.0.2
Déployez la fonction avec un déclencheur HTTP et en autorisant les requêtes non authentifiées à l'aide de cette commande:
gcloud functions deploy multiply \ --runtime python37 \ --trigger-http \ --allow-unauthenticated
Une fois la fonction déployée, vous pouvez également accéder à son URL à l'aide de la commande curl
suivante:
curl $(gcloud functions describe multiply --format='value(httpsTrigger.url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
La fonction est prête pour le workflow.
6. Connecter deux fonctions Cloud
Dans le premier workflow, associez les deux fonctions.
Créez un fichier workflow.yaml
avec le contenu suivant.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - returnResult: return: ${multiplyResult}
Dans ce workflow, vous obtenez un nombre aléatoire généré par la première fonction, puis vous le transmettez à la seconde fonction. Le résultat est le nombre aléatoire multiplié.
Déployez le premier workflow:
gcloud workflows deploy workflow --source=workflow.yaml
Exécutez le premier workflow:
gcloud workflows execute workflow
Une fois le workflow exécuté, vous pouvez voir le résultat en transmettant l'ID d'exécution indiqué à l'étape précédente:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Le résultat inclura result
et state
:
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. Connecter une API HTTP externe
Vous allez maintenant connecter math.js en tant que service externe dans le workflow.
Dans math.js, vous pouvez évaluer des expressions mathématiques comme ceci:
curl https://api.mathjs.org/v4/?'expr=log(56)'
Cette fois, vous allez utiliser la console Cloud pour mettre à jour notre workflow. Recherchez Workflows
dans la console Google Cloud:
Recherchez votre workflow, puis cliquez sur l'onglet Definition
:
Modifiez la définition du workflow et incluez un appel à math.js
.
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - returnResult: return: ${logResult}
Le workflow insère désormais la sortie de la fonction de multiplication dans un appel de fonction journal dans math.js
.
L'interface utilisateur vous guidera pour modifier et déployer le workflow. Une fois déployé, cliquez sur Execute
pour exécuter le workflow. Les détails de l'exécution s'affichent:
Notez le code d'état 200
et une body
avec le résultat de la fonction de journal.
Vous venez d'intégrer un service externe à notre workflow, c'est super !
8. Déployer un service Cloud Run
Enfin, finalisez le workflow en appelant un service Cloud Run privé. Cela signifie que le workflow doit être authentifié pour appeler le service Cloud Run.
Le service Cloud Run renvoie la valeur math.floor
du nombre transmis.
Créez un répertoire pour le code du service et accédez-y:
mkdir ~/floor cd ~/floor
Dans le répertoire, créez un fichier app.py
avec le contenu suivant:
import json import logging import os import math from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) def handle_post(): content = json.loads(request.data) input = float(content['input']) return f"{math.floor(input)}", 200 if __name__ != '__main__': # Redirect Flask logs to Gunicorn logs gunicorn_logger = logging.getLogger('gunicorn.error') app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level) app.logger.info('Service started...') else: app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run déploie les conteneurs. Vous avez donc besoin d'un Dockerfile
et votre conteneur doit être lié aux variables d'environnement 0.0.0.0
et PORT
, d'où le code ci-dessus.
Lorsqu'elle reçoit une requête HTTP, cette fonction extrait input
du corps JSON, appelle math.floor et renvoie le résultat à l'appelant.
Dans le même répertoire, créez le fichier Dockerfile
suivant:
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
Créez le conteneur :
export SERVICE_NAME=floor gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
Une fois le conteneur créé, déployez-le sur Cloud Run. Notez l'indicateur no-allow-unauthenticated
. Cela permet de s'assurer que le service n'accepte que les appels authentifiés:
gcloud run deploy ${SERVICE_NAME} \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \ --platform managed \ --no-allow-unauthenticated
Une fois déployé, le service est prêt pour le workflow.
9. Connecter le service Cloud Run
Avant de pouvoir configurer Workflows pour appeler le service privé Cloud Run, vous devez créer un compte de service que Workflows doit utiliser:
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
Attribuez le rôle run.invoker
au compte de service. Le compte de service pourra ainsi appeler des services Cloud Run authentifiés:
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role "roles/run.invoker"
Mettez à jour la définition du workflow dans workflow.yaml
pour inclure le service Cloud Run. Notez que vous incluez également le champ auth
pour vous assurer que Workflows transmet le jeton d'authentification dans ses appels au service Cloud Run:
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - floorFunction: call: http.post args: url: https://floor-<random-hash>.run.app auth: type: OIDC body: input: ${logResult.body} result: floorResult - returnResult: return: ${floorResult}
Mettez à jour le workflow. Cette fois, en transmettant le compte de service:
gcloud workflows deploy workflow \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
Exécutez le workflow :
gcloud workflows execute workflow
En quelques secondes, vous pouvez examiner l'exécution du workflow pour voir le résultat:
gcloud workflows executions describe <your-execution-id> --workflow workflow
Le résultat inclut les nombres entiers result
et state
:
result: '{"body":"5","code":200 ... } ... state: SUCCEEDED
10. Félicitations !
Bravo ! Vous avez terminé cet atelier de programmation.
Points abordés
- Principes de base des workflows.
- Connecter des fonctions Cloud publiques à Workflows
- Connecter des services Cloud Run privés avec Workflows
- Connecter des API HTTP externes avec Workflows