Communication entre services dans une configuration à microservices

Last reviewed 2024-06-26 UTC

Ce document est le troisième d'une série en quatre parties sur la conception, la création et le déploiement de microservices. Cette série décrit les différents éléments d'une architecture à microservices. La série inclut des informations sur les avantages et les inconvénients du modèle d'architecture à microservices et sur la façon de l'appliquer.

  1. Présentation des microservices
  2. Refactoriser un monolithe en microservices
  3. Communication entre services dans une configuration à microservices (le présent document)
  4. Traçage distribué dans une application à microservices

Cette série est destinée aux développeurs et aux architectes d'applications qui conçoivent et mettent en œuvre la migration pour refactoriser une application monolithique en application à microservices.

Ce document décrit les différences entre la messagerie asynchrone et les API synchrones pour les microservices. Il décrit la déconstruction d'une application monolithique et vous montre comment convertir une requête synchrone dans l'application d'origine en un flux asynchrone dans la nouvelle configuration basée sur des microservices. Cette conversion inclut la mise en œuvre de transactions distribuées entre les services.

Exemple d'application

Dans ce document, vous allez utiliser une application e-commerce prédéfinie appelée Online Boutique. L'application met en œuvre des flux e-commerce de base tels que la consultation d'articles, l'ajout de produits à un panier et le règlement. L'application propose également des recommandations et des publicités en fonction de la sélection de l'utilisateur.

Séparation logique du service

Dans ce document, vous isolez le service de paiement du reste de l'application. Tous les flux de l'application Online Boutique d'origine sont synchrones. Dans l'application refactorisée, le processus de paiement est converti en flux asynchrone. Par conséquent, lorsque vous recevez une demande d'achat, vous fournissez à l'utilisateur une confirmation "demande reçue" plutôt que de la traiter immédiatement. En arrière-plan, une requête asynchrone est déclenchée afin de traiter le paiement par l'intermédiaire du service de paiement.

Avant de déplacer les données et la logique de paiement dans un nouveau service, vous devez isoler les données et la logique de paiement du monolithe. Lorsque vous isolez les données et la logique de paiement du monolithe, il est plus facile de refactoriser votre code dans la même codebase si les limites du service de paiement sont incorrectes (logique métier ou données).

Les composants de l'application monolithique présentée dans ce document sont déjà modulaires, c'est-à-dire qu'ils sont isolés les uns des autres. Si votre application présente des interdépendances plus strictes, vous devez isoler la logique métier et créer des classes et des modules distincts. Vous devez également dissocier toutes les dépendances de base de données dans leurs propres tables et créer des classes de dépôt distinctes. Lorsque vous dissociez les dépendances de base de données, des relations de clés étrangères peuvent exister entre les tables fractionnées. Cependant, une fois que vous avez complètement dissocié le service du monolithe, ces dépendances cessent d'exister et le service interagit exclusivement via des API ou des contrats RPC prédéfinis.

Transactions distribuées et échecs partiels

Une fois que vous avez isolé le service et que vous l'avez séparé du monolithe, une transaction locale dans le système monolithique d'origine devient une transaction distribuée entre plusieurs services. Dans la mise en œuvre monolithique, le processus de paiement suit la séquence illustrée dans le schéma suivant.

Séquence de paiement distribuée sur plusieurs services.

Figure 1 : Séquence du processus de paiement dans une mise en œuvre monolithique.

Dans la figure 1, lorsque l'application reçoit un bon de commande, le contrôleur de paiement appelle le service de paiement et le service de commande pour traiter le paiement et enregistrer la commande, respectivement. Si une étape échoue, la transaction de base de données peut faire l'objet d'un rollback. Prenons un exemple dans lequel la requête de commande est bien enregistrée dans la table des commandes, mais le paiement échoue. Dans ce scénario, l'intégralité de la transaction fait l'objet d'un rollback et l'entrée est supprimée de la table des commandes.

Une fois le paiement dissocié dans son propre service, le processus de paiement modifié ressemble au schéma suivant :

Processus de paiement impliquant plusieurs services et plusieurs bases de données.

Figure 2. Une séquence de traitement survenant après le paiement est dissociée dans son propre service.

Dans la figure 2, la transaction implique désormais plusieurs services ainsi que les bases de données respectives de ces services. Il s'agit donc d'une transaction distribuée. À la réception d'une requête de commande, le contrôleur de paiement enregistre les détails de la commande dans sa base de données locale et appelle d'autres services pour finaliser la commande. Ces services, tels que le service de paiement, peuvent utiliser leur propre base de données locale pour stocker les détails de la commande.

Dans l'application monolithique, le système de base de données garantit que les transactions locales sont atomiques. Toutefois, par défaut, un système basé sur des microservices qui possède une base de données distincte pour chaque service ne dispose pas d'un coordinateur de transactions global couvrant les différentes bases de données. Comme les transactions ne sont pas coordonnées de manière centralisée, une défaillance lors du traitement d'un paiement n'entraîne pas l'annulation des modifications validées dans le service de commande. Par conséquent, le système peut présenter des incohérences.

Les modèles suivants sont généralement utilisés pour gérer les transactions distribuées :

  • Protocole de validation en deux phases (2PC) : Faisant partie d'une famille de protocoles de consensus, le protocole 2PC coordonne le commit d'une transaction distribuée et garantit atomicité, cohérence, isolation et durabilité (ACID). Le protocole est divisé en phases de préparation et de commit. Une transaction n'est validée que si tous les participants ont voté pour elle. Si les participants ne parviennent pas à un consensus, l'intégralité de la transaction fait l'objet d'un rollback.
  • Saga : le modèle Saga consiste à exécuter des transactions locales dans chaque microservice impliqué dans la transaction distribuée. Un événement est déclenché à la fin de chaque opération en fonction du résultat (réussite ou échec). Tous les microservices impliqués dans la transaction distribuée s'abonnent à ces événements. Si les microservices suivants reçoivent un événement de réussite, ils exécutent leur opération. En cas de défaillance, les microservices précédents mettent en œuvre des actions compensatoires pour annuler les modifications. Saga fournit une vue cohérente du système en garantissant que lorsque toutes les étapes sont terminées, soit toutes les opérations aboutissent, soit des actions compensatoires annulent toutes les opérations effectuées.

Nous recommandons Saga pour les transactions de longue durée. Dans une application basée sur des microservices, les appels interservices et la communication avec des systèmes tiers sont fréquents. Par conséquent, une conception favorisant la cohérence à terme est préférable : il faut réessayer pour les erreurs récupérables tout en exposant des événements compensatoires pour annuler les modifications en cas d'erreurs non-récupérables.

Il existe différentes manières de mettre en œuvre le modèle Saga. Par exemple, vous pouvez utiliser des moteurs de tâches et de workflows tels que Apache Airflow ou Apache Camel. Vous pouvez également écrire vos propres gestionnaires d'événements à l'aide de systèmes basés sur Kafka, RabbitMQ ou ActiveMQ.

L'application Online Boutique utilise le service de paiement pour orchestrer les services de paiement, d'expédition et de notification par e-mail. Le service de paiement gère également le workflow de l'entreprise et des commandes. Au lieu de créer votre propre moteur de workflow, vous pouvez utiliser un composant tiers tel que Zeebe. Zeebe propose un modèle basé sur interface utilisateur. Nous vous recommandons d'évaluer soigneusement les options disponibles pour l'orchestration des microservices en fonction des exigences de votre application. Ce choix est très important pour l'exécution et le scaling de vos microservices.

Application refactorisée

Pour activer les transactions distribuées dans l'application refactorisée, le service de paiement gère la communication entre le service de paiement, d'expédition et d'e-mail. Le workflow BPMN (Business Process Model and Notation) général utilise le flux suivant :

Transactions dans une application refactorisée suivant un workflow BPMN.

Figure 3. Workflow de commande qui garantit des transactions distribuées dans des microservices types.

Le schéma précédent représente le workflow suivant :

  • Le service d'interface reçoit une requête de commande, puis effectue les opérations suivantes :
    • Envoie les articles de la commande au service de panier d'achat. Le service de panier enregistre ensuite les détails de la commande (Redis).
    • Redirige vers la page de paiement. Le service de paiement extrait les commandes du service de panier, définit l'état de la commande sur Pending et demande au client le paiement.
    • Confirme le paiement de l'utilisateur. Une fois la confirmation effectuée, le service de paiement demande au service de messagerie de générer un e-mail de confirmation et de l'envoyer au client.
  • Le service de paiement traite ensuite la demande.
    • Si la demande de paiement aboutit, le service de paiement met à jour l'état de la commande sur Complete.
    • Si la requête de paiement échoue, le service de paiement lance une transaction compensatoire.
      • La demande de paiement est annulée.
      • Le service de paiement définit l'état de la commande sur Failed.
    • Si le service de paiement n'est pas disponible, la requête expire au bout de N secondes et le service de paiement lance une transaction compensatoire.
    • Le service de paiement définit l'état de la commande sur Failed.

Objectifs

  • Déployer l'application monolithique Online Boutique sur Google Kubernetes Engine (GKE).
  • Validez le processus de paiement monolithique.
  • Déployer la version basée sur les microservices de l'application monolithique refactorisée
  • Vérifier que le nouveau flux de paiement fonctionne.
  • Vérifier que les transactions distribuées et les actions compensatoires fonctionnent correctement en cas d'échec.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous aurez terminé de suivre ce document, vous pourrez éviter de continuer à payer des frais en supprimant les ressources créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  4. Activez les API pour Compute Engine, Google Kubernetes Engine, Cloud SQL, Artifact Analysis et Container Registry :

     gcloud services enable \
         compute.googleapis.com \
         sql-component.googleapis.com \
         servicenetworking.googleapis.com\
         container.googleapis.com \
         containeranalysis.googleapis.com \
         containerregistry.googleapis.com \
         sqladmin.googleapis.com
    
  5. Exportez les variables d'environnement suivantes :

    export PROJECT=$(gcloud config get-value project)
    export CLUSTER=$PROJECT-gke
    export REGION="us-central1"
    

Déployer le monolithe e-commerce

Dans cette section, vous déployez l'application monolithique Online Boutique dans un cluster GKE. L'application utilise Cloud SQL comme base de données relationnelle. Le schéma suivant illustre l'architecture de l'application monolithique :

Application utilisant une architecture monolithique.

Figure 4. Un client se connecte à l'application dans un cluster GKE, et l'application se connecte à une base de données Cloud SQL.

Pour déployer l'application, procédez comme suit :

  1. Clonez le dépôt GitHub.

    git clone https://github.com/GoogleCloudPlatform/monolith-to-microservices-example
    
  2. Remplacez l'espace réservé PROJECT_ID dans le fichier de manifeste des variables Terraform :

    cd monolith-to-microservices-example/setup && \
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" terraform.tfvars
    
  3. Exécutez les scripts Terraform pour terminer la configuration de l'infrastructure et la déployer. Pour en savoir plus sur Terraform, consultez la page Premiers pas avec Terraform sur Google Cloud :

    terraform init && terraform apply -auto-approve
    

    Le script Terraform crée les éléments suivants :

    • Un réseau VPC nommé PROJECT_ID-vpc
    • Un cluster GKE nommé PROJECT_ID-gke
    • Une instance Cloud SQL nommée PROJECT_ID-mysql
      • Une base de données nommée ecommerce et utilisée par l'application
      • Un utilisateur root avec le mot de passe défini sur password

    Vous pouvez modifier le script Terraform pour générer automatiquement un mot de passe. Cette configuration utilise un exemple simplifié à ne pas utiliser en production.

    Le provisionnement de l'infrastructure peut prendre jusqu'à 10 minutes. Une fois le script exécuté avec succès, le résultat ressemble à ceci :

    ...
    
    Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    kubernetes_cluster_name = PROJECT_ID-gke
    sql_database_name = PROJECT_ID-mysql
    vpc_name = PROJECT_ID-vpc
    
  4. Connectez-vous au cluster et créez un espace de noms nommé monolith. Vous déployez l'application dans son propre espace de noms dans le cluster GKE :

    gcloud container clusters get-credentials $CLUSTER \
       --region $REGION \
       --project $PROJECT && \
       kubectl create ns monolith
    
  5. L'application exécutée sur GKE utilise des secrets Kubernetes pour accéder à la base de données Cloud SQL. Créez un secret qui utilise les identifiants utilisateur de la base de données :

    kubectl create secret generic dbsecret \
      --from-literal=username=root \
      --from-literal=password=password -n monolith
    
  6. Créez l'image "monolith" et importez-la dans Container Registry :

    cd ~/monolith
    gcloud builds submit --tag gcr.io/$PROJECT_ID/ecomm
    
  7. Mettez à jour la référence dans le fichier deploy.yaml vers l'image Docker nouvellement créée :

    cd ~/monolith
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" deploy.yaml
    
  8. Remplacez les espaces réservés dans les fichiers de manifeste de déploiement, puis déployez l'application :

    cd .. && \
    DB_IP=$(gcloud sql instances describe $PROJECT-mysql | grep "ipAddress:" | tail -1 | awk -F ":" '{print $NF}')
    
    sed -i -e "s/\[DB_IP\]/$DB_IP/g" monolith/deploy.yaml
    kubectl apply -f monolith/deploy.yaml
    
  9. Vérifiez l'état du déploiement :

    kubectl rollout status deployment/ecomm -n monolith
    

    Le résultat est semblable à ce qui suit.

    Waiting for deployment "ecomm" rollout to finish: 0 of 1 updated replicas are available...
    deployment "ecomm" successfully rolled out
    
  10. Obtenez l'adresse IP de l'application déployée :

    kubectl get svc ecomm -n monolith \
            -o jsonpath="{.status.loadBalancer.ingress[*].ip}" -w
    

    Attendez que l'adresse IP de l'équilibreur de charge soit publiée. Pour quitter la commande, appuyez sur Ctrl+C. Notez l'adresse IP de l'équilibreur de charge, puis accédez à l'application à l'URL http://IP_ADDRESS. Il peut s'écouler un certain temps avant que l'équilibreur de charge ne soit opérationnel et commence à transmettre du trafic.

Valider le flux de paiement monolithique

Dans cette section, vous allez créer une commande test afin de valider le flux de paiement.

  1. Accédez à l'URL que vous avez notée dans la section précédente, http://IP_ADDRESS.
  2. Sur la page d'accueil de l'application qui s'affiche, sélectionnez un produit puis cliquez sur Ajouter au panier.
  3. Pour créer un achat test, cliquez sur Passer votre commande :
  4. Une fois le paiement effectué, la fenêtre de confirmation de commande s'affiche avec un ID de confirmation de commande.
  5. Pour afficher les détails de la commande, connectez-vous à la base de données :

    gcloud sql connect $PROJECT-mysql --user=root
    

    Vous pouvez également utiliser n'importe quelle autre méthode compatible pour vous connecter à la base de données. Lorsque vous y êtes invité, saisissez le mot de passe en tant que password.

  6. Pour afficher les détails d'une commande enregistrée, exécutez la commande suivante :

    select cart_id from ecommerce.cart;
    
  7. La sortie ressemble à ceci :

    +--------------------------------------+
    | cart_id                              |
    +--------------------------------------+
    | 7cb9ab11-d268-477f-bf4d-4913d64c5b27 |
    +--------------------------------------+
    

Déployer l'application e-commerce basée sur des microservices

Dans cette section, vous allez déployer l'application refactorisée. Ce document se concentre uniquement sur la dissociation des services d'interface et de paiement. Le document suivant de cette série, Traçage distribué dans une application à microservices, décrit d'autres services que vous pouvez dissocier de l'application monolithique (services de recommandation et de publicité). Le service de paiement gère les transactions distribuées entre les services d'interface et de paiement et est déployé en tant que service Kubernetes dans le cluster GKE, comme illustré dans le schéma suivant :

Services d'interface et de paiement dissociés du monolithe.

Figure 5. Le service de paiement orchestre les transactions entre les services de panier, de paiement et de messagerie.

Déployer les microservices

Dans cette section, vous utilisez l'infrastructure que vous avez provisionnée précédemment pour déployer des microservices dans leur propre espace de noms microservice :

  1. Assurez-vous d'avoir les ressources suivantes :

    • Projet Google Cloud
    • Environnement de shell avec gcloud, git et kubectl
  2. Dans Cloud Shell, clonez le dépôt de microservices :

    git clone https://github.com/GoogleCloudPlatform/microservices-demo
    cd microservices-demo/
    
  3. Définissez la région et le projet Google Cloud, et assurez-vous que l'API GKE est activée :

    export PROJECT_ID=PROJECT_ID
    export REGION=us-central1
    gcloud services enable container.googleapis.com \
    --project=${PROJECT_ID}
    

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud.

  4. Créez un cluster GKE et obtenez les identifiants associés :

    gcloud container clusters create-auto online-boutique \
        --project=${PROJECT_ID} --region=${REGION}
    

    La création du cluster peut prendre quelques minutes.

  5. Déployez des microservices sur le cluster :

    kubectl apply -f ./release/kubernetes-manifests.yaml
    
  6. Attendez que les pods soient prêts :

    kubectl get pods
    

    Après quelques minutes, les pods s'affichent avec l'état Running.

  7. Accédez à l'interface Web dans un navigateur à l'aide de son adresse IP externe :

    kubectl get service frontend-external | awk '{print $4}'
    

    Accédez à http://EXTERNAL_IP dans un navigateur Web pour accéder à votre instance de Boutique en ligne.

Valider le nouveau flux de paiement

  1. Pour vérifier le flux de traitement de paiement, sélectionnez un produit et passez une commande comme décrit dans la section précédente Valider le flux de paiement monolithique.
  2. Une fois le paiement effectué, la fenêtre de confirmation n'affiche pas d'ID de confirmation. Au lieu de cela, la fenêtre de confirmation vous invite à consulter votre messagerie pour obtenir plus de détails sur la confirmation.
  3. Pour vérifier que la commande a bien été reçue, que le service de paiement a bien traité le paiement et que les détails de la commande ont bien été mis à jour, exécutez la commande suivante :

    kubectl logs -f deploy/checkoutservice --tail=100
    

    La sortie ressemble à ceci :

    [...]
    {"message":"[PlaceOrder] user_id=\"98828e7a-b2b3-47ce-a663-c2b1019774a3\" user_currency=\"CAD\"","severity":"info","timestamp":"2023-08-10T04:19:20.498893921Z"}
    {"message":"payment went through (transaction_id: f0b4a592-026f-4b4a-9892-ce86d2711aed)","severity":"info","timestamp":"2023-08-10T04:19:20.528338189Z"}
    {"message":"order confirmation email sent to \"someone@example.com\"","severity":"info","timestamp":"2023-08-10T04:19:20.540275988Z"}
    

    Pour quitter les journaux, appuyez sur Ctrl+C.

  4. Vérifiez que le paiement a bien été effectué :

    kubectl logs -f deploy/paymentservice -n --tail=100
    

    La sortie ressemble à ceci :

    [...]
    {"severity":"info","time":1691641282208,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-charge","message":"Transaction processed: visa ending 0454     Amount: CAD119.30128260"}
    {"severity":"info","time":1691641300051,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-server","message":"PaymentService#Charge invoked with request {\"amount\":{\"currency_code\":\"USD\",\"units\":\"137\",\"nanos\":850000000},\"credit_card\":{\"credit_card_number\":\"4432-8015-6152-0454\",\"credit_card_cvv\":672,\"credit_card_expiration_year\":2039,\"credit_card_expiration_month\":1}}"}
    

    Pour quitter les journaux, appuyez sur Ctrl+C.

  5. Vérifiez que l'e-mail de confirmation de commande est envoyé :

    kubectl logs -f deploy/emailservice -n --tail=100
    

    La sortie ressemble à ceci :

    [...]
    {"timestamp": 1691642217.5026057, "severity": "INFO", "name": "emailservice-server", "message": "A request to send order confirmation email to kalani@examplepetstore.com has been received."}
    

    Les messages de journal de chaque microservice indiquent que la transaction distribuée sur les services de paiement, de messagerie et de paiement a bien abouti.

Valider une action compensatoire dans une transaction distribuée

Cette section simule un scénario dans lequel un client passe une commande et le service de paiement tombe en panne.

  1. Pour simuler l'indisponibilité du service, supprimez le déploiement et le service de paiement :

    kubectl delete deploy paymentservice && \
    kubectl delete svc paymentservice
    
  2. Accédez de nouveau à l'application et suivez le flux de paiement. Dans cet exemple, si le service de paiement ne répond pas, la requête expire et une action compensatoire est déclenchée.

  3. Dans l'interface utilisateur, cliquez sur le bouton Commander. Le résultat se présente comme suit :

    HTTP Status: 500 Internal Server Error
    rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host"
    failed to complete the order
    main.(*frontendServer).placeOrderHandler
        /src/handlers.go:360
    
  4. Consultez les journaux du service d'interface :

    kubectl logs -f deploy/frontend --tail=100
    

    Le résultat se présente comme suit :

    [...]
    {"error":"failed to complete the order: rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host\"","http.req.id":"0a4cb058-ee9b-470a-9bb1-3a965636022e","http.req.method":"POST","http.req.path":"/cart/checkout","message":"request error","session":"96c94881-a435-4490-9801-c788dc400cc1","severity":"error","timestamp":"2023-08-11T18:25:47.127294259Z"}
    
  5. Consultez les journaux du service de paiement :

    kubectl logs -f deploy/frontend --tail=100
    

    Le résultat se présente comme suit :

    [...]
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T18:25:46.947901041Z"}
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T19:54:21.796343643Z"}
    

    Notez qu'aucun appel ultérieur au service de messagerie n'est effectué pour envoyer une notification. Il n'y a pas de journal de transactions, comme payment went through (transaction_id: 06f0083f-fa47-4d91-8258-6d61edfab1ca).

  6. Consultez les journaux du service de messagerie :

    kubectl logs -f deploy/emailservice --tail=100
    

    Notez qu'aucune entrée de journal n'est créée pour l'échec de la transaction sur le service de messagerie.

En tant qu'orchestrateur, si un appel de service échoue, le service de paiement renvoie un état d'erreur et ferme le processus de paiement.

Effectuer un nettoyage

Si vous envisagez de suivre les étapes décrites du document suivant de cette série, traçage distribué dans une application à microservices, vous pouvez réutiliser le projet et les ressources plutôt que de les supprimer.

Supprimer le projet

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Supprimer les ressources

Si vous souhaitez conserver le projet Google Cloud que vous avez utilisé dans ce document, supprimez les ressources individuelles.

  1. Dans Cloud Shell, exécutez la commande suivante :

    cd setup && terraform destroy -auto-approve
    
  2. Pour supprimer le cluster de microservices à l'aide de la Google Cloud CLI, exécutez la commande suivante :

    gcloud container clusters delete online-boutique \
        --location $REGION
    

Étapes suivantes