Workflows vous permet de coordonner et d'automatiser des services dansGoogle Cloud. L'application des pratiques architecturales recommandées vous aide à améliorer la fiabilité, à optimiser les coûts d'exécution et à créer des orchestrations résilientes et faciles à gérer.
Cette liste de recommandations n'est pas exhaustive et ne vous apprend pas les bases de l'utilisation de Workflows. Ce document suppose que vous connaissez déjà le paysage Google Cloud général et Workflows. Pour en savoir plus, consultez le Google Cloud Well-Architected Framework et la présentation de Workflows.
Sélectionner un schéma de communication optimal
Lorsque vous concevez une architecture de microservices pour déployer plusieurs services, vous pouvez choisir parmi les modèles de communication suivants :
Communication directe entre services
Communication indirecte basée sur les événements (également appelée chorégraphie)
Configuration, coordination et gestion automatisées (également appelées orchestration)
Veillez à prendre en compte les avantages et les inconvénients de chacune des options précédentes et à sélectionner un modèle optimal pour votre cas d'utilisation. Par exemple, la communication directe de service à service peut être plus simple à mettre en œuvre que d'autres options, mais elle associe étroitement vos services. En revanche, une architecture basée sur des événements vous permet de coupler vos services de manière lâche. Toutefois, la surveillance et le débogage peuvent être plus compliqués. Enfin, un outil d'orchestration central comme Workflows, bien que moins flexible, vous permet de coordonner la communication entre les services sans le couplage fort de la communication directe de service à service, ni la complexité des événements chorégraphiés.
Vous pouvez également combiner des modèles de communication. Par exemple, dans l'orchestration basée sur les événements, les services étroitement liés sont gérés dans une orchestration déclenchée par un événement. De même, vous pouvez concevoir un système dans lequel une orchestration génère un message Pub/Sub vers un autre système orchestré.
Conseils généraux
Une fois que vous avez décidé d'utiliser Workflows comme orchestrateur de services, gardez à l'esprit les conseils utiles suivants.
Éviter de coder les URL en dur
Vous pouvez prendre en charge des workflows portables dans plusieurs environnements et plus faciles à gérer en évitant les URL codées en dur. Pour ce faire, procédez comme suit :
Définissez les URL en tant qu'arguments d'exécution.
Cela peut être utile lorsque votre workflow est appelé via une bibliothèque cliente ou l'API. (Toutefois, cela ne fonctionnera pas si votre workflow est déclenché par un événement d'Eventarc et que le seul argument pouvant être transmis est la charge utile de l'événement.)
Exemple
main: params: [args] steps: - init: assign: - url1: ${args.urls.url1} - url2: ${args.urls.url2}
Lorsque vous exécutez le workflow, vous pouvez spécifier les URL. Exemple :
gcloud workflows run multi-env --data='{"urls":{"url1": "URL_ONE", "url2": "URL_TWO"}}'
Utilisez des variables d'environnement et créez un workflow configuré de manière dynamique en fonction de l'environnement dans lequel il est déployé. Vous pouvez également créer un workflow qui peut être réutilisé en tant que modèle et configuré en fonction de variables d'environnement gérées séparément.
Utilisez une technique de substitution qui vous permet de créer un seul fichier de définition de workflow, mais de déployer des variantes à l'aide d'un outil qui remplace les espaces réservés dans votre workflow. Par exemple, vous pouvez utiliser Cloud Build pour déployer un workflow et, dans le fichier de configuration de compilation Cloud Build, ajouter une étape pour remplacer les URL d'espace réservé dans le workflow.
Exemple
steps: ‐ id: 'replace-urls' name: 'gcr.io/cloud-builders/gcloud' entrypoint: bash args: - -c - | sed -i -e "s~REPLACE_url1~$_URL1~" workflow.yaml sed -i -e "s~REPLACE_url2~$_URL2~" workflow.yaml ‐ id: 'deploy-workflow' name: 'gcr.io/cloud-builders/gcloud' args: ['workflows', 'deploy', 'multi-env-$_ENV', '--source', 'workflow.yaml']
Vous pouvez ensuite remplacer les valeurs des variables au moment de la compilation. Exemple :
gcloud builds submit --config cloudbuild.yaml \ --substitutions=_ENV=staging,_URL1="URL_ONE",_URL2="URL_TWO"
Pour en savoir plus, consultez Envoyer une compilation via la CLI et l'API.
Vous pouvez également utiliser Terraform pour provisionner votre infrastructure et définir un fichier de configuration qui crée des workflows pour chaque environnement à l'aide de variables d'entrée.
Exemple
variable "project_id" { type = string } variable "url1" { type = string } variable "url2" { type = string } locals { env = ["staging", "prod"] } # Define and deploy staging and production workflows resource "google_workflows_workflow" "multi-env-workflows" { for_each = toset(local.env) name = "multi-env-${each.key}" project = var.project_id region = "us-central1" source_contents = templatefile("${path.module}/workflow.yaml", { url1 : "${var.url1}-${each.key}", url2 : "${var.url2}-${each.key}" }) }
Lorsque des variables sont déclarées dans le module racine de votre configuration, vous pouvez leur attribuer des valeurs de différentes manières. Exemple
terraform apply -var="project_id=PROJECT_ID" -var="url1=URL_ONE" -var="url2=URL_TWO"
Utilisez le connecteur Secret Manager pour stocker de manière sécurisée des URL dans Secret Manager et les récupérer.
Utiliser des étapes imbriquées
Chaque workflow doit comporter au moins une étape.
Par défaut, Workflows traite les étapes comme si elles se trouvaient dans une liste ordonnée et les exécute une par une jusqu'à ce que toutes les étapes aient été exécutées. Logiquement, certaines étapes doivent être regroupées. Vous pouvez utiliser un bloc steps pour imbriquer une série d'étapes. Cela est pratique, car vous pouvez pointer vers l'étape atomique appropriée pour traiter un ensemble d'étapes.
Exemple
main: params: [input] steps: - callWikipedia: steps: - checkSearchTermInInput: switch: - condition: ${"searchTerm" in input} assign: - searchTerm: ${input.searchTerm} next: readWikipedia - getCurrentDate: call: http.get args: url: https://timeapi.io/api/Time/current/zone?timeZone=Europe/Amsterdam result: currentDate - setFromCallResult: assign: - searchTerm: ${currentDate.body.dayOfWeek} - readWikipedia: call: http.get args: url: https://en.wikipedia.org/w/api.php query: action: opensearch search: ${searchTerm} result: wikiResult - returnOutput: return: ${wikiResult.body[1]}
Encapsuler des expressions
Toutes les expressions doivent commencer par un $ et être placées entre accolades :
${EXPRESSION}Pour éviter les problèmes d'analyse YAML, vous pouvez placer les expressions entre guillemets. Par exemple, les expressions contenant des deux-points peuvent entraîner un comportement inattendu lorsque les deux-points sont interprétés comme définissant un mappage. Vous pouvez résoudre ce problème en encapsulant l'expression YAML entre guillemets simples:
'${"Name: " + myVar}'
Vous pouvez également utiliser des expressions qui s'étendent sur plusieurs lignes. Par exemple, vous devrez peut-être encapsuler une requête SQL entre guillemets lorsque vous utilisez le connecteur BigQuery de Workflows.
Exemple
- runQuery: call: googleapis.bigquery.v2.jobs.query args: projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")} body: useLegacySql: false useQueryCache: false timeoutMs: 30000 # Find top 100 titles with most views on Wikipedia query: ${ "SELECT TITLE, SUM(views) FROM `bigquery-samples.wikipedia_pageviews." + table + "` WHERE LENGTH(TITLE) > 10 GROUP BY TITLE ORDER BY SUM(VIEWS) DESC LIMIT 100" } result: queryResult
Pour obtenir la définition complète du workflow, consultez Exécuter plusieurs jobs BigQuery en parallèle.
Utiliser des appels déclaratifs
Utilisez Workflows pour appeler des services à partir du workflow lui-même et gérer les résultats, ainsi que pour exécuter des tâches simples, comme effectuer un appel HTTP. Workflows peut appeler des services, analyser les réponses et construire des entrées pour d'autres services connectés. L'appel d'un service vous permet d'éviter les complications liées aux appels supplémentaires, aux dépendances supplémentaires et aux services appelant des services. Envisagez de remplacer les services sans logique métier par des appels d'API déclaratifs et d'utiliser Workflows pour éliminer la complexité.
Toutefois, vous devez créer des services pour effectuer des tâches trop complexes pour Workflows, par exemple pour implémenter une logique métier réutilisable, des calculs complexes ou des transformations non compatibles avec les expressions Workflows et sa bibliothèque standard. Un cas complexe est généralement plus facile à implémenter dans le code, plutôt que d'utiliser YAML ou JSON et la syntaxe Workflows.
Ne stockez que ce dont vous avez besoin
Contrôlez la consommation de mémoire afin de ne pas atteindre les limites de ressources ou de ne pas rencontrer d'erreur l'indiquant, telle que ResourceLimitError, MemoryLimitExceededError ou ResultSizeLimitExceededError.
Soyez sélectif quant aux éléments que vous stockez dans les variables, en filtrant et en ne stockant que ce dont vous avez besoin. Si un service renvoie une charge utile trop volumineuse, utilisez une fonction distincte pour effectuer l'appel à votre place et ne renvoyer que ce qui est nécessaire.
Vous pouvez libérer de la mémoire en effaçant des variables. Par exemple, vous pouvez libérer de la mémoire nécessaire pour les étapes suivantes. Vous pouvez également avoir des appels dont les résultats ne vous intéressent pas et que vous pouvez omettre complètement.
Vous pouvez effacer une variable en lui attribuant la valeur null. En YAML, vous pouvez également attribuer une valeur vide ou ~ à une variable. Cela permet d'identifier la mémoire qui peut être récupérée en toute sécurité.
Exemple
- step: assign: - bigVar:
Utiliser des sous-workflows et des workflows externes
Vous pouvez utiliser des sous-workflows pour définir une logique ou un ensemble d'étapes que vous souhaitez appeler plusieurs fois, ce qui simplifie la définition du workflow. Les sous-workflows sont semblables à une fonction ou à une routine dans un langage de programmation. Elles peuvent accepter des paramètres et renvoyer des valeurs, ce qui vous permet de créer des workflows plus complexes avec un plus grand nombre d'applications.
Notez que les sous-workflows sont locaux à votre définition de workflow et ne peuvent pas être réutilisés dans d'autres workflows. Toutefois, vous pouvez appeler des workflows à partir d'autres workflows. Les connecteurs Workflows peuvent vous aider à le faire. Pour en savoir plus, consultez les présentations des connecteurs pour l'API Workflow Executions et l'API Workflows.
Utiliser les connecteurs Workflows
Workflows fournit un certain nombre de connecteurs qui facilitent l'accès à d'autres produits Google Cloud dans un workflow. Les connecteurs simplifient l'appel des services, car ils gèrent le formatage des requêtes à votre place, en fournissant des méthodes et des arguments pour que vous n'ayez pas besoin de connaître les détails d'une APIGoogle Cloud . Les connecteurs ont également un comportement intégré pour gérer les nouvelles tentatives et les opérations de longue durée, ce qui vous évite d'itérer et d'attendre que les appels se terminent. Les connecteurs s'en chargent pour vous.
Si vous devez appeler une API Google Cloud , vérifiez d'abord s'il existe un connecteur Workflows pour celle-ci. Si vous ne voyez pas de connecteur pour un produit Google Cloud , vous pouvez en demander un.
Découvrez comment utiliser un connecteur et, pour obtenir une documentation de référence détaillée sur les connecteurs disponibles, consultez la documentation de référence sur les connecteurs.
Exécuter des étapes de workflow en parallèle
Bien que Workflows puisse exécuter des étapes de manière séquentielle, vous pouvez également exécuter des étapes indépendantes en parallèle. Dans certains cas, cela peut accélérer considérablement l'exécution de votre workflow. Pour en savoir plus, consultez Exécuter des étapes de workflow en parallèle.
Appliquer les nouvelles tentatives et le modèle Saga
Concevez des workflows résilients et capables de gérer les défaillances de service temporaires et permanentes. Des erreurs peuvent être générées pour Workflows, par exemple par des requêtes HTTP, des fonctions ou des connecteurs ayant échoué, ou par votre propre code de workflow. Ajoutez la gestion des exceptions et les nouvelles tentatives afin qu'un échec à une étape n'entraîne pas l'échec de l'ensemble du workflow.
- Vous pouvez générer des erreurs personnalisées à l'aide de la syntaxe
raise. - Vous pouvez intercepter les erreurs à l'aide d'un bloc
try/except. - Vous pouvez relancer des étapes à l'aide d'un bloc
try/retryet définir le nombre maximal de tentatives.
Certaines transactions commerciales couvrent plusieurs services. Vous avez donc besoin d'un mécanisme pour mettre en œuvre des transactions qui couvrent plusieurs services. Le modèle de conception Saga permet de gérer la cohérence des données entre les microservices dans les scénarios de transactions distribuées. Une saga est une séquence de transactions qui publie un événement pour chaque transaction et qui déclenche la transaction suivante. Si une transaction échoue, la saga exécute des transactions compensatoires qui contrecarrent les échecs précédents de la séquence. Essayez le tutoriel sur les nouvelles tentatives et le modèle Saga dans Workflows sur GitHub.
Utiliser des rappels pour attendre
Les rappels permettent aux exécutions de workflow d'attendre qu'un autre service envoie une requête au point de terminaison de rappel. Cette requête reprend l'exécution du workflow.
Les rappels vous permettent de signaler à votre workflow qu'un événement spécifié s'est produit et d'attendre cet événement sans interrogation. Par exemple, vous pouvez créer un workflow qui vous avertit lorsqu'un produit est de nouveau en stock ou lorsqu'un article a été expédié, ou qui attend une interaction humaine, comme l'examen d'une commande ou la validation d'une traduction. Vous pouvez également attendre des événements à l'aide de rappels et de déclencheurs Eventarc.
Orchestrer des jobs de longue durée
Si vous devez exécuter des charges de travail de traitement par lot de longue durée, vous pouvez utiliser Batch ou des jobs Cloud Run, et vous pouvez utiliser Workflows pour gérer les services. Cela vous permet de combiner les avantages, et de provisionner et d'orchestrer efficacement l'ensemble du processus.
Batch est un service entièrement géré qui vous permet de planifier, mettre en file d'attente et exécuter des charges de travail par lot sur des instances de machines virtuelles (VM) Compute Engine. Vous pouvez utiliser le connecteur Workflows pour Batch pour planifier et exécuter un job Batch. Pour en savoir plus, suivez le tutoriel.
Les jobs Cloud Run sont utilisés pour exécuter du code qui effectue un travail (un job) et se ferme une fois le travail terminé. Workflows vous permet d'exécuter des jobs Cloud Run dans le cadre d'un workflow pour effectuer un traitement de données plus complexe ou orchestrer un système de jobs existants. Suivez ce tutoriel pour découvrir comment exécuter un job Cloud Run à l'aide de Workflows.
Aligner les délais avant expiration et les tailles de charge utile entre les services
Lorsque Workflows appelle des services Google Cloud en aval, les différences de délais avant expiration des requêtes, de limites de réponse HTTP et de limites de mémoire peuvent entraîner des échecs TimeoutError, ValueError ou MemoryLimitExceededError.
Comparez les limites de ressources de Workflows avec les limites du service cible, puis choisissez un modèle d'intégration correspondant à la durée et à la taille de la charge utile de votre charge de travail. Exemple :
| Scénario d'intégration | Limites de Workflows | Limites du service cible | Modèle recommandé |
|---|---|---|---|
Appels HTTP synchrones (http.get, http.post, http.request) vers des services Cloud Run ou des fonctions Cloud Run
|
|
Consultez Configurer le délai avant expiration des requêtes pour les services et Limites de ressources pour Cloud Run. |
Pour les charges de travail qui s'exécutent pendant plus de 30 minutes, n'utilisez pas d'appels Exécutez plutôt des jobs Cloud Run à l'aide du connecteur de l'API Cloud Run Admin ou utilisez un point de terminaison de rappel Workflows asynchrone. Le connecteur de l'API Cloud Run Admin est compatible avec l'interrogation des opérations de longue durée (LRO), qui expire par défaut après 30 minutes (1 800 secondes). Pour les jobs qui s'exécutent pendant plus de 30 minutes, configurez à la fois le délai avant expiration de la tâche du job Cloud Run (10 minutes par défaut, configurable jusqu'à 168 heures ou 7 jours) et |
Requêtes BigQuery et charges utiles d'API volumineuses (googleapis. et réponses REST)
|
|
Les résultats des requêtes BigQuery et les charges utiles de l'API REST peuvent dépasser plusieurs mégaoctets ou gigaoctets. |
Évitez d'extraire de grands ensembles de résultats dans des variables de workflow. Utilisez la pagination |
Conteneuriser les tâches de longue durée
Vous pouvez automatiser l'exécution d'un conteneur de longue durée à l'aide de Workflows et de Compute Engine. Par exemple, vous pouvez conteneuriser une tâche de longue durée afin qu'elle puisse s'exécuter n'importe où, puis exécuter le conteneur sur une VM Compute Engine pendant la durée maximale d'exécution d'un workflow (un an).
Workflows vous permet d'automatiser la création de la VM, l'exécution du conteneur sur la VM et la suppression de la VM. Cela vous permet d'utiliser un serveur et d'exécuter un conteneur, mais cela élimine la complexité de la gestion des deux, et peut être utile si vous rencontrez des limites de temps lorsque vous utilisez un service tel que Cloud Run Functions ou Cloud Run. Suivez le tutoriel Conteneurs de longue durée avec Workflows et Compute Engine sur GitHub.
Exécuter des outils de ligne de commande à partir de Workflows
Cloud Build est un service qui exécute vos compilations sur Google Cloud sous la forme d'une série d'étapes de compilation où chaque étape est exécutée dans un conteneur Docker. L'exécution des étapes de compilation est semblable à celle des commandes d'un script.
Google Cloud CLI inclut les outils de ligne de commande gcloud, bq et kubectl, mais il n'existe aucun moyen direct d'exécuter des commandes gcloud CLI à partir de Workflows. Toutefois, Cloud Build fournit des images de conteneurs qui incluent la gcloud CLI. Vous pouvez exécuter des commandes gcloud CLI dans ces conteneurs à partir d'une étape Cloud Build, et vous pouvez créer cette étape dans Workflows à l'aide du connecteur Cloud Build.
Exemple
Exécutez gcloud dans un workflow :
Run kubectl in a workflow:
Utiliser Terraform pour créer votre workflow
Terraform est un outil d'infrastructure as code qui vous permet de créer, de modifier et d'améliorer de manière prévisible votre infrastructure cloud en utilisant du code.
Vous pouvez définir et déployer un workflow à l'aide de la ressource Terraform google_workflows_workflow. Pour en savoir plus, consultez Créer un workflow à l'aide de Terraform.
Pour vous aider à gérer et à maintenir des workflows volumineux, vous pouvez créer votre workflow dans un fichier YAML distinct et l'importer dans Terraform à l'aide de la fonction templatefile, qui lit un fichier à un chemin d'accès donné et affiche son contenu en tant que modèle.
Exemple
# Define a workflow resource "google_workflows_workflow" "workflows_example" { name = "sample-workflow" region = var.region description = "A sample workflow" service_account = google_service_account.workflows_service_account.id # Import main workflow YAML file source_contents = templatefile("${path.module}/workflow.yaml",{}) }
De même, si vous avez un workflow principal qui appelle plusieurs sous-workflows, vous pouvez définir le workflow principal et les sous-workflows dans des fichiers distincts, puis utiliser la fonction templatefile pour les importer.
Exemple
# Define a workflow resource "google_workflows_workflow" "workflows_example" { name = "sample-workflow" region = var.region description = "A sample workflow" service_account = google_service_account.workflows_service_account.id # Import main workflow and subworkflow YAML files source_contents = join("", [ templatefile( "${path.module}/workflow.yaml",{} ), templatefile( "${path.module}/subworkflow.yaml",{} )]) }
Notez que si vous faites référence à des numéros de ligne lors du débogage d'un workflow, tous les fichiers YAML importés via le fichier de configuration Terraform sont fusionnés et déployés en tant que workflow unique.
Déployer un workflow à partir d'un dépôt Git
Cloud Build utilise des déclencheurs de compilation pour activer l'automatisation de l'intégration et de la livraison continues. Vous pouvez configurer des déclencheurs pour écouter les événements entrants, par exemple lorsqu'un nouveau commit est envoyé à un dépôt ou lorsqu'une demande d'extraction est initiée, puis exécuter automatiquement une compilation lorsque de nouveaux événements se produisent.
Vous pouvez utiliser un déclencheur de compilation Cloud Build pour démarrer automatiquement une compilation et déployer un workflow à partir d'un dépôt Git. Vous pouvez configurer le déclencheur pour déployer votre workflow à chaque modification du dépôt source, ou uniquement lorsque la modification répond à des critères spécifiques.
Cette approche peut vous aider à gérer le cycle de vie de votre déploiement. Par exemple, vous pouvez déployer des modifications dans un workflow dans un environnement de préproduction, exécuter des tests sur cet environnement, puis lancer progressivement ces modifications dans l'environnement de production. Pour en savoir plus, consultez Déployer un workflow à partir d'un dépôt Git à l'aide de Cloud Build.
Optimiser l'utilisation
Le coût d'exécution d'un workflow est minime. Toutefois, pour une utilisation à volume élevé, appliquez les consignes suivantes afin d'optimiser l'utilisation et de réduire les coûts :
Au lieu d'utiliser des domaines personnalisés, assurez-vous que tous les appels aux services Google Cloudutilisent
*.appspot.com,*.cloud.goog,*.cloudfunctions.netou*.run.appafin d'être facturé pour les étapes internes et non externes.Appliquez une règle de nouvelle tentative personnalisée qui équilibre vos besoins de latence et de fiabilité avec les coûts. Des nouvelles tentatives plus fréquentes réduisent la latence et augmentent la fiabilité, mais peuvent également augmenter les coûts.
Lorsque vous utilisez des connecteurs qui attendent des opérations de longue durée, définissez une règle d'interrogation personnalisée qui optimise la latence en fonction du coût. Par exemple, si vous prévoyez qu'une opération prendra plus d'une heure, vous pouvez définir une stratégie qui interroge initialement après une minute en cas d'échec immédiat, puis toutes les 15 minutes.
Combinez les devoirs en une seule étape.
Évitez d'utiliser excessivement les étapes
sys.log. Envisagez plutôt d'utiliser la journalisation des appels.Comprendre quelles opérations sont considérées comme une étape. Les opérations qui ne sont pas comptabilisées comme des étapes à part entière sont comptabilisées lorsqu'elles sont utilisées dans une étape applicable. Par exemple, l'action suivante compte comme une étape :
- type_check: return: if(get_type((int("6"))) == integer, 1, 2)Les opérations clés qui sont comptabilisées ou non dans la limite maximale d'étapes sont classées dans le tableau suivant :
Catégorie Opération Comptabilisé comme une étape - Opérations sur les données : attribution et renvoi de valeurs
- Contrôle du flux : sauts (
next), commutateurs, démarrage d'une boucleforet chaque itération d'une bouclefor - Appels : appel de
sys.get_envou d'une autre fonction de bibliothèque standard, d'un autre workflow ou d'un connecteur - Simultanéité : génération de threads et exécution parallèle
- Gestion des exceptions : chaque bloc
raise,try,retryetexceptest comptabilisé comme une étape distincte, même si d'autres opérations font partie de la même étape plus importante.Par exemple, une étape qui inclut un bloc
tryavec une opération d'appel compte comme trois étapes : une pour l'étape principale, une pour l'essai et une pour l'appel. L'ajout d'un blocretryajoute trois étapes supplémentaires (une pour la nouvelle tentative, une pour l'essai et une pour l'appel), soit un total de six étapes.
Ne compte pas comme une étape - Lire et écrire des listes, des cartes et des variables
Bien qu'une recherche individuelle n'ajoute pas d'étape supplémentaire, une étape contenant la recherche (par exemple, une étape
assign) compte comme une étape. - Fonctions d'assistance d'expression intégrées spécifiques :
len(),int()etget_type() - Opérations de comparaison et arithmétiques
- Concaténation de chaînes
- Opérations booléennes
Récapitulatif des bonnes pratiques
Le tableau suivant récapitule les conseils généraux et les bonnes pratiques recommandés dans ce document.