Déployer dans Compute Engine


Ce guide explique comment effectuer des déploiements bleu/vert sans temps d'arrêt sur des groupes d'instances gérés (MIG) Compute Engine à l'aide de Cloud Build et de Terraform.

Cloud Build vous permet d'automatiser divers processus de développement, y compris la compilation et le déploiement d'applications dans différents Google Cloud environnements d'exécution, tels que Compute Engine, Google Kubernetes Engine, GKE Enterprise et les fonctions Cloud Run.

Les MIG Compute Engine vous permettent d'exécuter des applications sur plusieurs machines virtuelles (VM) identiques. Vous pouvez rendre vos charges de travail évolutives et disponibilité élevée en tirant parti des services de MIG automatisés, comme l'autoscaling, l'autoréparation, le déploiement régional (multizone) et la mise à jour automatique. À l'aide du modèle de déploiement continu bleu/vert, vous apprendrez à transférer progressivement le trafic utilisateur d'un MIG (bleu) vers un autre MIG (vert), tous deux exécutés en production.

Présentation de la conception

Le schéma suivant illustre le modèle de déploiement bleu/vert utilisé par l'exemple de code décrit dans ce document :

Modèle bleu-vert

De manière générale, ce modèle inclut les composants suivants :

  • Deux pools de VM Compute Engine : bleu et vert.
  • Trois équilibreurs de charge HTTP(S) externes :
    • Un équilibreur de charge bleu/vert qui achemine le trafic des utilisateurs finaux vers le pool bleu ou vert d'instances de VM.
    • Un équilibreur de charge bleu qui achemine le trafic des ingénieurs QA et des développeurs vers le pool d'instances de VM bleues.
    • Un équilibreur de charge vert qui achemine le trafic des ingénieurs QA et des développeurs vers le pool d'instances vertes.
  • Deux ensembles d'utilisateurs :
    • Les utilisateurs finaux ayant accès à l'équilibreur de charge bleu/vert, qui les redirige vers le pool d'instances bleu ou vert.
    • Ingénieurs QA et développeurs ayant besoin d'accéder aux deux ensembles de pools à des fins de développement et de test. Ils peuvent accéder aux équilibreurs de charge bleu et vert, qui les redirigent respectivement vers le pool d'instances bleu et le pool d'instances vert.

Les pools de VM bleu et vert sont implémentés en tant que MIG Compute Engine, et les adresses IP externes sont acheminées vers les VM du MIG à l'aide d'équilibreurs de charge HTTP(S) externes. L'exemple de code décrit dans ce document utilise Terraform pour configurer cette infrastructure.

Le schéma suivant illustre les opérations de développement qui ont lieu lors du déploiement :

Flux des opérations des développeurs

Dans le diagramme ci-dessus, les flèches rouges représentent le flux d'amorçage qui se produit lorsque vous configurez l'infrastructure de déploiement pour la première fois, et les flèches bleues représentent le flux GitOps qui se produit lors de chaque déploiement.

Pour configurer cette infrastructure, vous exécutez un script de configuration qui lance le processus d'amorçage et configure les composants du flux GitOps.

Le script de configuration exécute un pipeline Cloud Build qui effectue les opérations suivantes :

Le déclencheur apply est associé à un fichier Terraform nommé main.tfvars dans Cloud Source Repositories. Ce fichier contient les variables Terraform représentant les équilibreurs de charge bleu et vert.

Pour configurer le déploiement, mettez à jour les variables dans le fichier main.tfvars. Le déclencheur apply exécute un pipeline Cloud Build qui exécute tf_apply et effectue les opérations suivantes :

  • Crée deux MIG Compute Engine (un pour la version verte et un pour la version bleue), quatre instances de VM Compute Engine (deux pour le MIG vert et deux pour le MIG bleu), les trois équilibreurs de charge (bleu, vert et le répartiteur) et trois adresses IP publiques.
  • Affiche les adresses IP que vous pouvez utiliser pour afficher les applications déployées dans les instances bleues et vertes.

Le déclencheur de suppression est déclenché manuellement pour supprimer toutes les ressources créées par le déclencheur d'application.

Objectifs

  • Utilisez Cloud Build et Terraform pour configurer des équilibreurs de charge HTTP(S) externes avec des backends de groupes d'instances de VM Compute Engine.

  • Effectuez des déploiements bleu-vert sur les instances de VM.

Coûts

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

Pour obtenir une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à gcloud CLI avec votre identité fédérée.

  4. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Install the Google Cloud CLI.

  8. Si vous utilisez un fournisseur d'identité (IdP) externe, vous devez d'abord vous connecter à gcloud CLI avec votre identité fédérée.

  9. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  10. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  11. Verify that billing is enabled for your Google Cloud project.

  12. Essayez-le !

    1. Exécutez le script d'installation à partir du dépôt d'exemples de code Google :

      bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/setup.sh)
      
    2. Lorsque le script de configuration demande le consentement de l'utilisateur, saisissez yes.

      L'exécution du script se termine en quelques secondes.

    3. Dans la console Google Cloud , ouvrez la page Historique de compilation de Cloud Build :

      Ouvrir la page "Historique de compilation"

    4. Cliquez sur la dernière version.

      La page Détails de la compilation s'affiche. Elle présente un pipeline Cloud Build avec trois étapes de compilation : la première crée un dépôt dans Cloud Source Repositories, la deuxième clone le contenu du dépôt d'exemple dans GitHub vers Cloud Source Repositories et la troisième ajoute deux déclencheurs de compilation.

    5. Ouvrez Cloud Source Repositories :

      Ouvrir Cloud Source Repositories

    6. Dans la liste des dépôts, cliquez sur copy-of-gcp-mig-simple.

      Dans l'onglet Historique en bas de la page, vous verrez un commit avec la description A copy of https://github.com/GoogleCloudPlatform/cloud-build-samples.git créé par Cloud Build pour créer un dépôt nommé copy-of-gcp-mig-simple.

    7. Accédez à la page Déclencheurs de Cloud Build :

      Ouvrir la page Déclencheurs

    8. Deux déclencheurs de compilation nommés apply et destroy s'affichent. Le déclencheur apply est associé au fichier infra/main.tfvars dans la branche main. Ce déclencheur est exécuté chaque fois que le fichier est modifié. Le déclencheur destroy est un déclencheur manuel.

    9. Pour lancer le processus de déploiement, mettez à jour le fichier infra/main.tfvars :

      1. Dans votre fenêtre de terminal, créez un dossier nommé deploy-compute-engine et accédez-y :

        mkdir ~/deploy-compute-engine
        cd ~/deploy-compute-engine
        
      2. Clonez le dépôt copy-of-gcp-mig-simple :

        gcloud source repos clone copy-of-mig-blue-green
        
      3. Accédez au répertoire cloné :

        cd ./copy-of-mig-blue-green
        
      4. Mettez à jour infra/main.tfvars pour remplacer "blue" par "green" :

        sed -i'' -e 's/blue/green/g' infra/main.tfvars
        
      5. Ajoutez le fichier modifié :

        git add .
        
      6. Validez le fichier :

        git commit -m "Promote green"
        
      7. Transférez le fichier :

        git push
        

        Toute modification apportée à infra/main.tfvars déclenche l'exécution du déclencheur apply, qui lance le déploiement.

    10. Ouvrez Cloud Source Repositories :

      Ouvrir Cloud Source Repositories

    11. Dans la liste des dépôts, cliquez sur copy-of-gcp-mig-simple.

      Le commit avec la description Promote green s'affiche dans l'onglet Historique en bas de la page.

    12. Pour afficher l'exécution du déclencheur apply, ouvrez la page Historique de compilation dans la console Google Cloud  :

      Ouvrir la page "Historique de compilation"

    13. Ouvrez la page Informations sur le build en cliquant sur le premier build.

      Le pipeline de déclencheur apply s'affiche avec deux étapes de compilation. La première étape de compilation exécute Terraform apply pour créer les ressources Compute Engine et d'équilibrage de charge pour le déploiement. La deuxième étape de compilation affiche l'adresse IP à laquelle vous pouvez voir l'application en cours d'exécution.

    14. Ouvrez l'adresse IP correspondant au MIG vert dans un navigateur. Une capture d'écran semblable à celle ci-dessous s'affiche pour indiquer le déploiement :

      Déploiement

    15. Accédez à la page Groupe d'instances de Compute Engine pour afficher les groupes d'instances "Bleu" et "Vert" :

      Ouvrir la page "Groupe d'instances"

    16. Ouvrez la page Instances de VM pour afficher les quatre instances de VM :

      Ouvrir la page "Instances de VM"

    17. Ouvrez la page Adresses IP externes pour afficher les trois équilibreurs de charge :

      Ouvrir la page "Adresses IP externes"

    Comprendre le code

    Le code source de cet exemple de code comprend les éléments suivants :

    • Code source lié au script de configuration.
    • Code source associé aux pipelines Cloud Build.
    • Code source lié aux modèles Terraform.

    Script de configuration

    setup.sh est le script de configuration qui exécute le processus d'amorçage et crée les composants pour le déploiement bleu-vert. Le script effectue les opérations suivantes :

    • Active les API Cloud Build, Resource Manager, Compute Engine et Cloud Source Repositories.
    • Attribue le rôle IAM roles/editor au compte de service Cloud Build dans votre projet. Ce rôle est requis pour que Cloud Build puisse créer et configurer les composants GitOps nécessaires au déploiement.
    • Attribue le rôle IAM roles/source.admin au compte de service Cloud Build dans votre projet. Ce rôle est requis pour que le compte de service Cloud Build puisse créer les dépôts Cloud Source Repositories dans votre projet et cloner le contenu de l'exemple de dépôt GitHub dans vos dépôts Cloud Source Repositories.
    • Génère un pipeline Cloud Build nommé bootstrap.cloudbuild.yaml en ligne, qui :

      • Crée un dépôt dans Cloud Source Repositories.
      • Copie le code source de l'exemple de dépôt GitHub dans le nouveau dépôt Cloud Source Repositories.
      • Crée les déclencheurs de compilation "apply" et "destroy".
    set -e
    
    BLUE='\033[1;34m'
    RED='\033[1;31m'
    GREEN='\033[1;32m'
    NC='\033[0m'
    
    echo -e "\n${GREEN}######################################################"
    echo -e "#                                                    #"
    echo -e "#  Zero-Downtime Blue/Green VM Deployments Using     #"
    echo -e "#  Managed Instance Groups, Cloud Build & Terraform  #"
    echo -e "#                                                    #"
    echo -e "######################################################${NC}\n"
    
    echo -e "\nSTARTED ${GREEN}setup.sh:${NC}"
    
    echo -e "\nIt's ${RED}safe to re-run${NC} this script to ${RED}recreate${NC} all resources.\n"
    echo "> Checking GCP CLI tool is installed"
    gcloud --version > /dev/null 2>&1
    
    readonly EXPLICIT_PROJECT_ID="$1"
    readonly EXPLICIT_CONSENT="$2"
    
    if [ -z "$EXPLICIT_PROJECT_ID" ]; then
        echo "> No explicit project id provided, trying to infer"
        PROJECT_ID="$(gcloud config get-value project)"
    else
        PROJECT_ID="$EXPLICIT_PROJECT_ID"
    fi
    
    if [ -z "$PROJECT_ID" ]; then
        echo "ERROR: GCP project id was not provided as parameter and could not be inferred"
        exit 1
    else
        readonly PROJECT_NUM="$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')"
        if [ -z "$PROJECT_NUM" ]; then
            echo "ERROR: GCP project number could not be determined"
            exit 1
        fi
        echo -e "\nYou are about to:"
        echo -e "  * modify project ${RED}${PROJECT_ID}/${PROJECT_NUM}${NC}"
        echo -e "  * ${RED}enable${NC} various GCP APIs"
        echo -e "  * make Cloud Build ${RED}editor${NC} of your project"
        echo -e "  * ${RED}execute${NC} Cloud Builds and Terraform plans to create"
        echo -e "  * ${RED}4 VMs${NC}, ${RED}3 load balancers${NC}, ${RED}3 public IP addresses${NC}"
        echo -e "  * incur ${RED}charges${NC} in your billing account as a result\n"
    fi
    
    if [ "$EXPLICIT_CONSENT" == "yes" ]; then
      echo "Proceeding under explicit consent"
      readonly CONSENT="$EXPLICIT_CONSENT"
    else
        echo -e "Enter ${BLUE}'yes'${NC} if you want to proceed:"
        read CONSENT
    fi
    
    if [ "$CONSENT" != "yes" ]; then
        echo -e "\nERROR: Aborted by user"
        exit 1
    else
        echo -e "\n......................................................"
        echo -e "\n> Received user consent"
    fi
    
    #
    # Executes action with one randomly delayed retry.
    #
    function do_with_retry {
        COMMAND="$@"
        echo "Trying $COMMAND"
        (eval $COMMAND && echo "Success on first try") || ( \
            echo "Waiting few seconds to retry" &&
            sleep 10 && \
            echo "Retrying $COMMAND" && \
            eval $COMMAND \
        )
    }
    
    echo "> Enabling required APIs"
    # Some of these can be enabled later with Terraform, but I personally
    # prefer to do all API enablement in one place with gcloud.
    gcloud services enable \
        --project=$PROJECT_ID \
        cloudbuild.googleapis.com \
        cloudresourcemanager.googleapis.com \
        compute.googleapis.com \
        sourcerepo.googleapis.com \
        --no-user-output-enabled \
        --quiet
    
    echo "> Adding Cloud Build to roles/editor"
    gcloud projects add-iam-policy-binding \
        "$PROJECT_ID" \
        --member="serviceAccount:$PROJECT_NUM@cloudbuild.gserviceaccount.com" \
        --role='roles/editor' \
        --condition=None \
        --no-user-output-enabled \
        --quiet
    
    echo "> Adding Cloud Build to roles/source.admin"
    gcloud projects add-iam-policy-binding \
        "$PROJECT_ID" \
        --member="serviceAccount:$PROJECT_NUM@cloudbuild.gserviceaccount.com" \
        --condition=None \
        --role='roles/source.admin' \
        --no-user-output-enabled \
        --quiet
    
    echo "> Configuring bootstrap job"
    rm -rf "./bootstrap.cloudbuild.yaml"
    cat <<'EOT_BOOT' > "./bootstrap.cloudbuild.yaml"
    tags:
    - "mig-blue-green-bootstrapping"
    steps:
    - id: create_new_cloud_source_repo
      name: "gcr.io/cloud-builders/gcloud"
      script: |
        #!/bin/bash
        set -e
    
        echo "(Re)Creating source code repository"
    
        gcloud source repos delete \
            "copy-of-mig-blue-green" \
            --quiet || true
    
        gcloud source repos create \
            "copy-of-mig-blue-green" \
            --quiet
    
    - id: copy_demo_source_into_new_cloud_source_repo
      name: "gcr.io/cloud-builders/gcloud"
      env:
        - "PROJECT_ID=$PROJECT_ID"
        - "PROJECT_NUMBER=$PROJECT_NUMBER"
      script: |
        #!/bin/bash
        set -e
    
        readonly GIT_REPO="https://github.com/GoogleCloudPlatform/cloud-build-samples.git"
    
        echo "Cloning demo source repo"
        mkdir /workspace/from/
        cd /workspace/from/
        git clone $GIT_REPO ./original
        cd ./original
    
        echo "Cloning new empty repo"
        mkdir /workspace/to/
        cd /workspace/to/
        gcloud source repos clone \
            "copy-of-mig-blue-green"
        cd ./copy-of-mig-blue-green
    
        echo "Making a copy"
        cp -r /workspace/from/original/mig-blue-green/* ./
    
        echo "Setting git identity"
        git config user.email \
            "$PROJECT_NUMBER@cloudbuild.gserviceaccount.com"
        git config user.name \
            "Cloud Build"
    
        echo "Commit & push"
        git add .
        git commit \
            -m "A copy of $GIT_REPO"
        git push
    
    - id: add_pipeline_triggers
      name: "gcr.io/cloud-builders/gcloud"
      env:
        - "PROJECT_ID=$PROJECT_ID"
      script: |
        #!/bin/bash
        set -e
    
        echo "(Re)Creating destroy trigger"
        gcloud builds triggers delete "destroy" --quiet || true
        gcloud builds triggers create manual \
            --name="destroy" \
            --repo="https://source.developers.google.com/p/$PROJECT_ID/r/copy-of-mig-blue-green" \
            --branch="master" \
            --build-config="pipelines/destroy.cloudbuild.yaml" \
            --repo-type=CLOUD_SOURCE_REPOSITORIES \
            --quiet
    
        echo "(Re)Creating apply trigger"
        gcloud builds triggers delete "apply" --quiet || true
        gcloud builds triggers create cloud-source-repositories \
            --name="apply" \
            --repo="copy-of-mig-blue-green" \
            --branch-pattern="master" \
            --build-config="pipelines/apply.cloudbuild.yaml" \
            --included-files="infra/main.tfvars" \
            --quiet
    
    EOT_BOOT
    
    echo "> Waiting API enablement propagation"
    do_with_retry "(gcloud builds list --project "$PROJECT_ID" --quiet && gcloud compute instances list --project "$PROJECT_ID" --quiet && gcloud source repos list --project "$PROJECT_ID" --quiet) > /dev/null 2>&1" > /dev/null 2>&1
    
    echo "> Executing bootstrap job"
    gcloud beta builds submit \
        --project "$PROJECT_ID" \
        --config ./bootstrap.cloudbuild.yaml \
        --no-source \
        --no-user-output-enabled \
        --quiet
    rm ./bootstrap.cloudbuild.yaml
    
    echo -e "\n${GREEN}All done. Now you can:${NC}"
    echo -e "  * manually run 'apply' and 'destroy' triggers to manage deployment lifecycle"
    echo -e "  * commit change to 'infra/main.tfvars' and see 'apply' pipeline trigger automatically"
    
    echo -e "\n${GREEN}Few key links:${NC}"
    echo -e "  * Dashboard: https://console.cloud.google.com/home/dashboard?project=$PROJECT_ID"
    echo -e "  * Repo: https://source.cloud.google.com/$PROJECT_ID/copy-of-mig-blue-green"
    echo -e "  * Cloud Build Triggers: https://console.cloud.google.com/cloud-build/triggers;region=global?project=$PROJECT_ID"
    echo -e "  * Cloud Build History: https://console.cloud.google.com/cloud-build/builds?project=$PROJECT_ID"
    
    echo -e "\n............................."
    
    echo -e "\n${GREEN}COMPLETED!${NC}"

    Pipelines Cloud Build

    apply.cloudbuild.yaml et destroy.cloudbuild.yaml sont les fichiers de configuration Cloud Build que le script d'installation utilise pour configurer les ressources du flux GitOps. apply.cloudbuild.yaml contient deux étapes de compilation :

    • Étape de compilation tf_apply build qui appelle la fonction tf_install_in_cloud_build_step, qui installe Terraform. tf_apply qui crée les ressources utilisées dans le flux GitOps. Les fonctions tf_install_in_cloud_build_step et tf_apply sont définies dans bash_utils.sh, et l'étape de compilation utilise la commande source pour les appeler.
    • Étape de compilation describe_deployment qui appelle la fonction describe_deployment qui affiche les adresses IP des équilibreurs de charge.

    destroy.cloudbuild.yaml appelle tf_destroy qui supprime toutes les ressources créées par tf_apply.

    Les fonctions tf_install_in_cloud_build_step, tf_apply, describe_deployment et tf_destroy sont définies dans le fichier bash_utils.sh. Les fichiers de configuration de compilation utilisent la commande source pour appeler les fonctions.

    steps:
      - id: run-terraform-apply
        name: "gcr.io/cloud-builders/gcloud"
        env:
          - "PROJECT_ID=$PROJECT_ID"
        script: |
          #!/bin/bash
          set -e
          source /workspace/lib/bash_utils.sh
          tf_install_in_cloud_build_step
          tf_apply
    
      - id: describe-deployment
        name: "gcr.io/cloud-builders/gcloud"
        env:
          - "PROJECT_ID=$PROJECT_ID"
        script: |
          #!/bin/bash
          set -e
          source /workspace/lib/bash_utils.sh
          describe_deployment
    
    tags:
      - "mig-blue-green-apply"
    steps:
      - id: run-terraform-destroy
        name: "gcr.io/cloud-builders/gcloud"
        env:
          - "PROJECT_ID=$PROJECT_ID"
        script: |
          #!/bin/bash
          set -e
          source /workspace/lib/bash_utils.sh
          tf_install_in_cloud_build_step
          tf_destroy
    
    tags:
      - "mig-blue-green-destroy"

    Le code suivant montre la fonction tf_install_in_cloud_build_step définie dans bash_utils.sh. Les fichiers de configuration de compilation appellent cette fonction pour installer Terraform à la volée. Il crée un bucket Cloud Storage pour enregistrer l'état Terraform.

    function tf_install_in_cloud_build_step {
        echo "Installing deps"
        apt update
        apt install \
            unzip \
            wget \
            -y
    
        echo "Manually installing Terraform"
        wget https://releases.hashicorp.com/terraform/1.3.4/terraform_1.3.4_linux_386.zip
        unzip -q terraform_1.3.4_linux_386.zip
        mv ./terraform /usr/bin/
        rm -rf terraform_1.3.4_linux_386.zip
    
        echo "Verifying installation"
        terraform -v
    
        echo "Creating Terraform state storage bucket $BUCKET_NAME"
        gcloud storage buckets create \
            "gs://$BUCKET_NAME" || echo "Already exists..."
    
        echo "Configure Terraform provider and state bucket"
    cat <<EOT_PROVIDER_TF > "/workspace/infra/provider.tf"
    terraform {
      required_version = ">= 0.13"
      backend "gcs" {
        bucket = "$BUCKET_NAME"
      }
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = ">= 3.77, < 5.0"
        }
      }
    }
    EOT_PROVIDER_TF
    
        echo "$(cat /workspace/infra/provider.tf)"
    }

    L'extrait de code suivant montre la fonction tf_apply définie dans bash_utils.sh. Il appelle d'abord terraform init qui charge tous les modules et bibliothèques personnalisées, puis exécute terraform apply pour charger les variables à partir du fichier main.tfvars.

    function tf_apply {
        echo "Running Terraform init"
        terraform \
            -chdir="$TF_CHDIR" \
            init
    
        echo "Running Terraform apply"
        terraform \
            -chdir="$TF_CHDIR" \
            apply \
            -auto-approve \
            -var project="$PROJECT_ID" \
            -var-file="main.tfvars"
    }

    L'extrait de code suivant montre la fonction describe_deployment définie dans bash_utils.sh. Il utilise gcloud compute addresses describe pour récupérer les adresses IP des équilibreurs de charge à l'aide du nom et les affiche.

    function describe_deployment {
        NS="ns1-"
        echo -e "Deployment configuration:\n$(cat infra/main.tfvars)"
        echo -e \
          "Here is how to connect to:" \
          "\n\t* active color MIG: http://$(gcloud compute addresses describe ${NS}splitter-address-name --region=us-west1 --format='value(address)')/" \
          "\n\t* blue color MIG: http://$(gcloud compute addresses describe ${NS}blue-address-name --region=us-west1 --format='value(address)')/" \
          "\n\t* green color MIG: http://$(gcloud compute addresses describe ${NS}green-address-name --region=us-west1 --format='value(address)')/"
        echo "Good luck!"
    }

    L'extrait de code suivant montre la fonction tf_destroy définie dans bash_utils.sh. Il appelle terraform init qui charge tous les modules et bibliothèques personnalisées, puis exécute terraform destroy qui décharge les variables Terraform.

    function tf_destroy {
        echo "Running Terraform init"
        terraform \
            -chdir="$TF_CHDIR" \
            init
    
        echo "Running Terraform destroy"
        terraform \
            -chdir="$TF_CHDIR" \
            destroy \
            -auto-approve \
            -var project="$PROJECT_ID" \
            -var-file="main.tfvars"
    }

    Modèles Terraform

    Vous trouverez tous les fichiers et variables de configuration Terraform dans le dossier copy-of-gcp-mig-simple/infra/.

    • main.tf : fichier de configuration Terraform
    • main.tfvars : ce fichier définit les variables Terraform.
    • mig/ et splitter/ : ces dossiers contiennent les modules qui définissent les équilibreurs de charge. Le dossier mig/ contient le fichier de configuration Terraform qui définit le MIG pour les équilibreurs de charge bleu et vert. Les MIG bleus et verts sont identiques. Ils sont donc définis une seule fois et instanciés pour les objets bleus et verts. Le fichier de configuration Terraform pour l'équilibreur de charge de répartiteur se trouve dans le dossier splitter/ .

    L'extrait de code suivant montre le contenu de infra/main.tfvars. Il contient trois variables : deux qui déterminent la version de l'application à déployer dans les pools bleu et vert, et une variable pour la couleur active (bleu ou vert). Les modifications apportées à ce fichier déclenchent le déploiement.

    MIG_VER_BLUE     = "v1"
    MIG_VER_GREEN    = "v1"
    MIG_ACTIVE_COLOR = "blue"

    Voici un extrait de code de infra/main.tf. Dans cet extrait :

    • Une variable est définie pour le projet Google Cloud .
    • Google est défini comme fournisseur Terraform.
    • Une variable est définie pour l'espace de noms. Tous les objets créés par Terraform sont préfixés avec cette variable afin que plusieurs versions de l'application puissent être déployées dans le même projet et que les noms d'objets ne se chevauchent pas.
    • Les variables MIG_VER_BLUE, MIG_VER_BLUE et MIG_ACTIVE_COLOR sont les liaisons pour les variables du fichier infra/main.tfvars.
    variable "project" {
      type        = string
      description = "GCP project we are working in."
    }
    
    provider "google" {
      project = var.project
      region  = "us-west1"
      zone    = "us-west1-a"
    }
    
    variable "ns" {
      type        = string
      default     = "ns1-"
      description = "The namespace used for all resources in this plan."
    }
    
    variable "MIG_VER_BLUE" {
      type        = string
      description = "Version tag for 'blue' deployment."
    }
    
    variable "MIG_VER_GREEN" {
      type        = string
      description = "Version tag for 'green' deployment."
    }
    
    variable "MIG_ACTIVE_COLOR" {
      type        = string
      description = "Active color (blue | green)."
    }

    L'extrait de code suivant de infra/main.tf montre l'instanciation du module de fractionnement. Ce module prend en compte la couleur active afin que l'équilibreur de charge du répartiteur sache quel MIG déployer l'application.

    module "splitter-lb" {
      source               = "./splitter"
      project              = var.project
      ns                   = "${var.ns}splitter-"
      active_color         = var.MIG_ACTIVE_COLOR
      instance_group_blue  = module.blue.google_compute_instance_group_manager_default.instance_group
      instance_group_green = module.green.google_compute_instance_group_manager_default.instance_group
    }

    L'extrait de code suivant de infra/main.tf définit deux modules identiques pour les MIG bleues et vertes. Il prend en compte la couleur, le réseau et le sous-réseau définis dans le module de fractionnement.

    module "blue" {
      source                               = "./mig"
      project                              = var.project
      app_version                          = var.MIG_VER_BLUE
      ns                                   = var.ns
      color                                = "blue"
      google_compute_network               = module.splitter-lb.google_compute_network
      google_compute_subnetwork            = module.splitter-lb.google_compute_subnetwork_default
      google_compute_subnetwork_proxy_only = module.splitter-lb.google_compute_subnetwork_proxy_only
    }
    
    module "green" {
      source                               = "./mig"
      project                              = var.project
      app_version                          = var.MIG_VER_GREEN
      ns                                   = var.ns
      color                                = "green"
      google_compute_network               = module.splitter-lb.google_compute_network
      google_compute_subnetwork            = module.splitter-lb.google_compute_subnetwork_default
      google_compute_subnetwork_proxy_only = module.splitter-lb.google_compute_subnetwork_proxy_only
    }

    Le fichier splitter/main.tf définit les objets créés pour le MIG du répartiteur. Voici un extrait de code de splitter/main.tf qui contient la logique permettant de basculer entre les MIG vertes et bleues. Il est soutenu par le service google_compute_region_backend_service, qui peut acheminer le trafic vers deux régions de backend : var.instance_group_blue ou var.instance_group_green. capacity_scaler définit la part du trafic à acheminer.

    Le code suivant achemine 100 % du trafic vers la couleur spécifiée, mais vous pouvez le modifier pour le déploiement Canary afin d'acheminer le trafic vers un sous-ensemble d'utilisateurs.

    resource "google_compute_region_backend_service" "default" {
      name                  = local.l7-xlb-backend-service
      region                = "us-west1"
      load_balancing_scheme = "EXTERNAL_MANAGED"
      health_checks         = [google_compute_region_health_check.default.id]
      protocol              = "HTTP"
      session_affinity      = "NONE"
      timeout_sec           = 30
      backend {
        group           = var.instance_group_blue
        balancing_mode  = "UTILIZATION"
        capacity_scaler = var.active_color == "blue" ? 1 : 0
      }
      backend {
        group           = var.instance_group_green
        balancing_mode  = "UTILIZATION"
        capacity_scaler = var.active_color == "green" ? 1 : 0
      }
    }

    Le fichier mig/main.tf définit les objets liés aux MIG bleus et verts. L'extrait de code suivant de ce fichier définit le modèle d'instance Compute Engine utilisé pour créer les pools de VM. Notez que la propriété de cycle de vie Terraform de ce modèle d'instance est définie sur create_before_destroy. En effet, lorsque vous mettez à jour la version du pool, vous ne pouvez pas utiliser le modèle pour créer la nouvelle version des pools tant qu'il est encore utilisé par la version précédente du pool. Toutefois, si l'ancienne version du pool est détruite avant la création du nouveau modèle, les pools seront indisponibles pendant un certain temps. Pour éviter ce scénario, nous définissons le cycle de vie Terraform sur create_before_destroy afin que la version la plus récente d'un pool de VM soit créée avant la suppression de l'ancienne version.

    resource "google_compute_instance_template" "default" {
      name = local.l7-xlb-backend-template
      disk {
        auto_delete  = true
        boot         = true
        device_name  = "persistent-disk-0"
        mode         = "READ_WRITE"
        source_image = "projects/debian-cloud/global/images/family/debian-10"
        type         = "PERSISTENT"
      }
      labels = {
        managed-by-cnrm = "true"
      }
      machine_type = "n1-standard-1"
      metadata = {
        startup-script = <<EOF
        #! /bin/bash
        sudo apt-get update
        sudo apt-get install apache2 -y
        sudo a2ensite default-ssl
        sudo a2enmod ssl
        vm_hostname="$(curl -H "Metadata-Flavor:Google" \
        http://169.254.169.254/computeMetadata/v1/instance/name)"
        sudo echo "<html><body style='font-family: Arial; margin: 64px; background-color: light${var.color};'><h3>Hello, World!<br><br>version: ${var.app_version}<br>ns: ${var.ns}<br>hostname: $vm_hostname</h3></body></html>" | \
        tee /var/www/html/index.html
        sudo systemctl restart apache2
        EOF
      }
      network_interface {
        access_config {
          network_tier = "PREMIUM"
        }
        network    = var.google_compute_network.id
        subnetwork = var.google_compute_subnetwork.id
      }
      region = "us-west1"
      scheduling {
        automatic_restart   = true
        on_host_maintenance = "MIGRATE"
        provisioning_model  = "STANDARD"
      }
      tags = ["load-balanced-backend"]
    
      # NOTE: the name of this resource must be unique for every update;
      #       this is wy we have a app_version in the name; this way
      #       new resource has a different name vs old one and both can
      #       exists at the same time
      lifecycle {
        create_before_destroy = true
      }
    }

    Effectuer un nettoyage

    Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

    Supprimer des ressources individuelles

    1. Supprimez les ressources Compute Engine créées par le déclencheur d'application :

      1. Accédez à la page Déclencheurs de Cloud Build :

        Ouvrir la page Déclencheurs

      2. Dans le tableau Déclencheurs, recherchez la ligne correspondant au déclencheur destroy, puis cliquez sur Exécuter. Une fois le déclencheur exécuté, les ressources créées par le déclencheur apply sont supprimées.

    2. Supprimez les ressources créées lors de l'amorçage en exécutant la commande suivante dans la fenêtre de votre terminal :

      bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/teardown.sh)
      

    Supprimer le projet

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    Étapes suivantes