Deployment in Compute Engine


Questa guida spiega come eseguire deployment blu/verde senza tempi di inattività sui gruppi di istanze gestite (MIG) di Compute Engine utilizzando Cloud Build e Terraform.

Cloud Build ti consente di automatizzare una serie di processi per sviluppatori, tra cui la creazione e il deployment di applicazioni in vari Google Cloud runtime come Compute Engine, Google Kubernetes Engine, GKE Enterprise e funzioni Cloud Run.

I MIG di Compute Engine ti consentono di utilizzare le applicazioni su più macchine virtuali (VM) identiche. Puoi rendere i tuoi workload scalabili e ad alta affidabilità sfruttando i servizi MIG automatizzati, tra cui: scalabilità automatica, riparazione automatica, deployment regionale (più zone) e aggiornamento automatico. Utilizzando il modello di deployment continuo blu/verde, imparerai a trasferire gradualmente il traffico utente da un MIG (blu) a un altro MIG (verde), entrambi in esecuzione in produzione.

Panoramica del progetto

Il seguente diagramma mostra il modello di deployment blu/verde utilizzato dall'esempio di codice descritto in questo documento:

Modello blu/verde

In linea generale, questo modello include i seguenti componenti:

  • Due pool di VM Compute Engine: blu e verde.
  • Tre bilanciatori del carico HTTP(S) esterni:
    • Un bilanciatore del carico blu/verde, che indirizza il traffico degli utenti finali al pool blu o verde di istanze VM.
    • Un bilanciatore del carico blu che indirizza il traffico degli ingegneri QA e degli sviluppatori al pool di istanze VM blu.
    • Un bilanciatore del carico verde che instrada il traffico degli ingegneri QA e degli sviluppatori al pool di istanze verde.
  • Due gruppi di utenti:
    • Gli utenti finali che hanno accesso al bilanciatore del carico blu/verde, che li indirizza al pool di istanze blu o verde.
    • Ingegneri e sviluppatori del QA che richiedono l'accesso a entrambi i set di pool per scopi di sviluppo e test. Possono accedere sia ai bilanciatori del carico blu che a quelli verdi, che li indirizzano rispettivamente al pool di istanze blu e al pool di istanze verdi.

I pool di VM blu e verdi sono implementati come MIG Compute Engine e gli indirizzi IP esterni vengono instradati nelle VM nel MIG utilizzando i bilanciatori del carico HTTP(S) esterni. Il esempio di codice descritto in questo documento utilizza Terraform per configurare questa infrastruttura.

Il seguente diagramma illustra le operazioni dello sviluppatore che si verificano nel deployment:

Flusso delle operazioni dello sviluppatore

Nel diagramma precedente, le frecce rosse rappresentano il flusso di bootstrapping che si verifica quando configuri l'infrastruttura di deployment per la prima volta, mentre le frecce blu rappresentano il flusso GitOps che si verifica durante ogni deployment.

Per configurare questa infrastruttura, esegui uno script di configurazione che avvia il processo di bootstrap e configura i componenti per il flusso GitOps.

Lo script di configurazione esegue una pipeline Cloud Build che esegue le seguenti operazioni:

  • Crea un repository in Cloud Source Repositories denominato copy-of-gcp-mig-simple e copia il codice sorgente dal repository di esempio GitHub al repository in Cloud Source Repositories.
  • Crea due trigger di Cloud Build denominati apply e destroy.

Il trigger apply è collegato a un file Terraform denominato main.tfvars in Cloud Source Repositories. Questo file contiene le variabili Terraform che rappresentano i bilanciatori del carico blu e verde.

Per configurare il deployment, aggiorna le variabili nel file main.tfvars. Il trigger apply esegue una pipeline Cloud Build che esegue tf_apply ed esegue le seguenti operazioni:

  • Crea due MIG di Compute Engine (uno per il verde e uno per il blu), quattro istanze VM di Compute Engine (due per il MIG verde e due per il MIG blu), i tre bilanciatori del carico (blu, verde e lo splitter) e tre indirizzi IP pubblici.
  • Stampa gli indirizzi IP che puoi utilizzare per visualizzare le applicazioni di cui è stato eseguito il deployment nelle istanze blu e verdi.

Il trigger destroy viene attivato manualmente per eliminare tutte le risorse create dal trigger apply.

Obiettivi

  • Utilizza Cloud Build e Terraform per configurare bilanciatori del carico HTTP(S) esterni con backend di gruppi di istanze VM di Compute Engine.

  • Esegui i deployment blu/verde sulle istanze VM.

Costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova gratuita.

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, vedi Pulizia.

Prima di iniziare

  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. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.

  4. Per inizializzare gcloud CLI, esegui questo comando:

    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. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere alla gcloud CLI con la tua identità federata.

  9. Per inizializzare gcloud CLI, esegui questo comando:

    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. Prova

    1. Esegui lo script di configurazione dal repository di esempio di codice di Google:

      bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/setup.sh)
      
    2. Quando lo script di configurazione chiede il consenso dell'utente, inserisci yes.

      L'esecuzione dello script termina in pochi secondi.

    3. Nella Google Cloud console, apri la pagina Cronologia build di Cloud Build:

      Apri la pagina Cronologia build

    4. Fai clic sull'ultima build.

      Viene visualizzata la pagina Dettagli build, che mostra una pipeline Cloud Build con tre passaggi di build: il primo passaggio crea un repository in Cloud Source Repositories, il secondo clona i contenuti del repository di esempio in GitHub in Cloud Source Repositories e il terzo aggiunge due trigger di build.

    5. Apri Cloud Source Repositories:

      Apri Cloud Source Repositories

    6. Nell'elenco dei repository, fai clic su copy-of-gcp-mig-simple.

      Nella scheda Cronologia nella parte inferiore della pagina, vedrai un commit con la descrizione A copy of https://github.com/GoogleCloudPlatform/cloud-build-samples.git creato da Cloud Build per creare un repository denominato copy-of-gcp-mig-simple.

    7. Apri la pagina Trigger di Cloud Build:

      Apri la pagina Trigger

    8. Vedrai due trigger di build denominati apply e destroy. Il trigger apply è collegato al file infra/main.tfvars nel ramo main. Questo trigger viene eseguito ogni volta che il file viene aggiornato. Il trigger destroy è un trigger manuale.

    9. Per avviare la procedura di deployment, aggiorna il file infra/main.tfvars:

      1. Nella finestra del terminale, crea una cartella denominata deploy-compute-engine e accedi:

        mkdir ~/deploy-compute-engine
        cd ~/deploy-compute-engine
        
      2. Clona il repository copy-of-gcp-mig-simple:

        gcloud source repos clone copy-of-mig-blue-green
        
      3. Vai alla directory clonata:

        cd ./copy-of-mig-blue-green
        
      4. Aggiorna infra/main.tfvars per sostituire il blu con il verde:

        sed -i'' -e 's/blue/green/g' infra/main.tfvars
        
      5. Aggiungi il file aggiornato:

        git add .
        
      6. Esegui il commit del file:

        git commit -m "Promote green"
        
      7. Esegui il push del file:

        git push
        

        L'apporto di modifiche a infra/main.tfvars attiva l'esecuzione del trigger apply, che avvia il deployment.

    10. Apri Cloud Source Repositories:

      Apri Cloud Source Repositories

    11. Nell'elenco dei repository, fai clic su copy-of-gcp-mig-simple.

      Vedrai il commit con la descrizione Promote green nella scheda Cronologia nella parte inferiore della pagina.

    12. Per visualizzare l'esecuzione del trigger apply, apri la pagina Cronologia build nella console Google Cloud :

      Apri la pagina Cronologia build

    13. Apri la pagina Dettagli build facendo clic sulla prima build.

      Vedrai la pipeline di trigger apply con due passaggi di build. Il primo passaggio di build esegue Terraform apply per creare le risorse Compute Engine e di bilanciamento del carico per il deployment. Il secondo passaggio di build stampa l'indirizzo IP in cui puoi vedere l'applicazione in esecuzione.

    14. Apri l'indirizzo IP corrispondente al MIG verde in un browser. Vedrai uno screenshot simile al seguente che mostra il deployment:

      Deployment

    15. Vai alla pagina Gruppo di istanze di Compute Engine per visualizzare i gruppi di istanze blu e verdi:

      Apri la pagina Gruppo di istanze

    16. Apri la pagina Istanze VM per visualizzare le quattro istanze VM:

      Apri la pagina Istanza VM

    17. Apri la pagina Indirizzi IP esterni per visualizzare i tre bilanciatori del carico:

      Apri la pagina Indirizzi IP esterni

    Nozioni di base sul codice

    Il codice sorgente per questo esempio di codice include:

    • Codice sorgente relativo allo script di configurazione.
    • Codice sorgente correlato alle pipeline Cloud Build.
    • Codice sorgente correlato ai modelli Terraform.

    Script di configurazione

    setup.sh è lo script di configurazione che esegue il processo di bootstrap e crea i componenti per il deployment blu/verde. Lo script esegue le seguenti operazioni:

    • Abilita le API Cloud Build, Resource Manager, Compute Engine e Cloud Source Repositories.
    • Concede il ruolo IAM roles/editor all'account di servizio Cloud Build nel tuo progetto. Questo ruolo è necessario a Cloud Build per creare e configurare i componenti GitOps necessari per il deployment.
    • Concede il ruolo IAM roles/source.admin all'account di servizio Cloud Build nel tuo progetto. Questo ruolo è necessario per consentire al account di servizio Cloud Build di creare Cloud Source Repositories nel tuo progetto e clonare i contenuti del repository GitHub di esempio in Cloud Source Repositories.
    • Genera una pipeline Cloud Build denominata bootstrap.cloudbuild.yaml inline, che:

      • Crea un nuovo repository in Cloud Source Repositories.
      • Copia il codice sorgente dal repository GitHub di esempio nel nuovo repository in Cloud Source Repositories.
      • Crea i trigger di build apply e 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}"

    Pipeline di Cloud Build

    apply.cloudbuild.yaml e destroy.cloudbuild.yaml sono i file di configurazione di Cloud Build che lo script di configurazione utilizza per configurare le risorse per il flusso GitOps. apply.cloudbuild.yaml contiene due passaggi di build:

    • Passaggio di build tf_apply build che chiama la funzione tf_install_in_cloud_build_step, che installa Terraform. tf_apply che crea le risorse utilizzate nel flusso GitOps. Le funzioni tf_install_in_cloud_build_step e tf_apply sono definite in bash_utils.sh e il passaggio di build utilizza il comando source per chiamarle.
    • Passaggio di compilazione describe_deployment che chiama la funzione describe_deployment che stampa gli indirizzi IP dei bilanciatori del carico.

    destroy.cloudbuild.yaml chiama tf_destroy che elimina tutte le risorse create da tf_apply.

    Le funzioni tf_install_in_cloud_build_step, tf_apply, describe_deployment e tf_destroy sono definite nel file bash_utils.sh. I file di configurazione della build utilizzano il comando source per chiamare le funzioni.

    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"

    Il seguente codice mostra la funzione tf_install_in_cloud_build_step definita in bash_utils.sh. I file di configurazione di compilazione chiamano questa funzione per installare Terraform al volo. Crea un bucket Cloud Storage per registrare lo stato di 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)"
    }

    Il seguente snippet di codice mostra la funzione tf_apply definita in bash_utils.sh. Chiama prima terraform init, che carica tutti i moduli e le librerie personalizzate, quindi esegue terraform apply per caricare le variabili dal file 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"
    }

    Il seguente snippet di codice mostra la funzione describe_deployment definita in bash_utils.sh. Utilizza gcloud compute addresses describe per recuperare gli indirizzi IP dei bilanciatori del carico utilizzando il nome e li stampa.

    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!"
    }

    Il seguente snippet di codice mostra la funzione tf_destroy definita in bash_utils.sh. Chiama terraform init che carica tutti i moduli e le librerie personalizzate e poi esegue terraform destroy che scarica le variabili 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"
    }

    Modelli Terraform

    Troverai tutti i file di configurazione e le variabili Terraform nella cartella copy-of-gcp-mig-simple/infra/.

    • main.tf: questo è il file di configurazione Terraform
    • main.tfvars: questo file definisce le variabili Terraform.
    • mig/ e splitter/: queste cartelle contengono i moduli che definiscono i bilanciatori del carico. La cartella mig/ contiene il file di configurazione Terraform che definisce il MIG per i bilanciatori del carico blu e verde. I MIG blu e verdi sono identici, pertanto vengono definiti una sola volta e istanziati per gli oggetti blu e verdi. Il file di configurazione Terraform per il bilanciatore del carico splitter si trova nella cartella splitter/ .

    Il seguente snippet di codice mostra i contenuti di infra/main.tfvars. Contiene tre variabili: due che determinano la versione dell'applicazione da eseguire il deployment nei pool blu e verde e una variabile per il colore attivo: blu o verde. Le modifiche a questo file attivano il deployment.

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

    Di seguito è riportato uno snippet di codice di infra/main.tf. In questo snippet:

    • È definita una variabile per il progetto Google Cloud .
    • Google è impostato come provider Terraform.
    • Una variabile è definita per lo spazio dei nomi. Tutti gli oggetti creati da Terraform sono preceduti da questa variabile, in modo che più versioni dell'applicazione possano essere implementate nello stesso progetto e i nomi degli oggetti non entrino in conflitto tra loro.
    • Le variabili MIG_VER_BLUE, MIG_VER_BLUE e MIG_ACTIVE_COLOR sono i binding per le variabili nel file 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)."
    }

    Il seguente snippet di codice di infra/main.tf mostra l'istanza del modulo di separazione. Questo modulo accetta il colore attivo in modo che il bilanciamento del carico dello splitter sappia in quale MIG eseguire il deployment dell'applicazione.

    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
    }

    Il seguente snippet di codice di infra/main.tf definisce due moduli identici per i MIG blu e verdi. Prende il colore, la rete e la subnet definiti nel modulo splitter.

    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
    }

    Il file splitter/main.tf definisce gli oggetti creati per il MIG splitter. Di seguito è riportato un snippet di codice di splitter/main.tf che contiene la logica per passare dal MIG verde a quello blu. È supportato dal servizio google_compute_region_backend_service, che può instradare il traffico verso due regioni di backend: var.instance_group_blue o var.instance_group_green. capacity_scaler definisce la quantità di traffico da instradare.

    Il seguente codice indirizza il 100% del traffico al colore specificato, ma puoi aggiornarlo per il deployment canary in modo da indirizzare il traffico a un sottoinsieme di utenti.

    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
      }
    }

    Il file mig/main.tf definisce gli oggetti relativi ai MIG blu e verdi. Il seguente snippet di codice di questo file definisce il modello di istanza Compute Engine utilizzato per creare i pool di VM. Tieni presente che questo modello di istanza ha la proprietà del ciclo di vita Terraform impostata su create_before_destroy. Questo perché, quando aggiorni la versione del pool, non puoi utilizzare il modello per creare la nuova versione dei pool mentre è ancora in uso nella versione precedente del pool. Tuttavia, se la versione precedente del pool viene eliminata prima della creazione del nuovo modello, si verificherà un periodo di tempo in cui i pool non saranno disponibili. Per evitare questo scenario, impostiamo il ciclo di vita di Terraform su create_before_destroy in modo che la versione più recente di un pool di VM venga creata prima che quella precedente venga eliminata.

    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
      }
    }

    Esegui la pulizia

    Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

    Elimina singole risorse

    1. Elimina le risorse Compute Engine create dal trigger di applicazione:

      1. Apri la pagina Trigger di Cloud Build:

        Apri la pagina Trigger

      2. Nella tabella Attivatori, individua la riga corrispondente all'attivatore destroy e fai clic su Esegui. Al termine dell'esecuzione del trigger, le risorse create dal trigger apply vengono eliminate.

    2. Elimina le risorse create durante il bootstrapping eseguendo questo comando nella finestra del terminale:

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

    Elimina il progetto

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    Passaggi successivi