Deployment in Compute Engine


Questa guida spiega come eseguire deployment blu/verde senza tempi di inattività sulle gruppi di istanze gestite di Compute Engine mediante Cloud Build e con Terraform.

Cloud Build ti consente di automatizzare vari processi degli sviluppatori, tra cui la creazione e il deployment di applicazioni su vari runtime Google Cloud come Compute Engine, Google Kubernetes Engine, GKE Enterprise e Cloud Functions.

I MIG di Compute Engine ti consentono di operare su più macchine virtuali (VM) identiche. Puoi rendere i tuoi carichi di lavoro scalabili e ad alta disponibilità sfruttando i gruppi di istanze gestite tra cui: scalabilità automatica, riparazione automatica, regione (più zone) deployment e aggiornamento automatico. Utilizzo del deployment continuo blu/verde imparerai a trasferire gradualmente il traffico degli utenti da un gruppo di istanze gestite (blu) a un altro gruppo di istanze gestite (verde), entrambi in esecuzione in produzione.

Panoramica del design

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

Modello blu/verde

A livello generale, questo modello include i seguenti componenti:

  • Due pool di VM di Compute Engine: blu e verde.
  • Tre bilanciatori del carico HTTP(S) esterni:
    • Un bilanciatore del carico blu/verde, che instrada il traffico dagli utenti finali a il pool di istanze VM blu o verde.
    • Un bilanciatore del carico blu che instrada il traffico dagli ingegneri QA gli sviluppatori al pool di istanze VM blu.
    • Un bilanciatore del carico verde che instrada il traffico dai tecnici QA gli sviluppatori al pool di istanze Green.
  • Due gruppi di utenti:
    • Gli utenti finali che hanno accesso al bilanciatore del carico blu/verde, che indica al pool di istanze blu o verde.
    • i tecnici e gli sviluppatori addetti al QA che richiedono l'accesso a entrambi i set di pool per per scopi di sviluppo e test. Possono accedere sia all'app Bilanciatori del carico verdi, che li instradano al pool di istanza blu Pool di istanze verdi.

I pool di VM blu e verdi sono implementati come gruppi di istanze gestite di Compute Engine, e gli indirizzi IP esterni vengono instradati nelle VM nel gruppo di istanze gestite utilizzando HTTP(s) esterni bilanciatori del carico. L'esempio di codice descritto in questo documento utilizza Terraform per per configurare l'infrastruttura.

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

Flusso operativo dello sviluppatore

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

Per configurare questa infrastruttura, devi eseguire uno script di configurazione che avvia il bootstrap e configurare i componenti del flusso GitOps.

Lo script di configurazione esegue una pipeline di 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 da GitHub di esempio nel 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 nel 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 di Cloud Build che tf_apply ed esegue le seguenti operazioni:

  • Crea due gruppi di istanze gestite di Compute Engine (uno per il verde e uno per il blu), Istanze VM di Compute Engine (due per il gruppo di istanze gestite verde e due per il gruppo di istanze gestite in blu MIG), i tre bilanciatori del carico (blu, verde e splitter) e tre dagli indirizzi IP pubblici.
  • Stampa gli indirizzi IP che puoi utilizzare per visualizzare i deployment le applicazioni nelle istanze blu e verde.

Il trigger di eliminazione viene attivato manualmente per eliminare tutte le risorse create l'attivatore apply.

Obiettivi

  • Utilizzare Cloud Build e Terraform per configurare il carico HTTP(S) esterno con backend di gruppi di istanze VM di Compute Engine.

  • Eseguire deployment blu/verde sulle istanze VM.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi basata sull'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud potrebbero essere idonei per una prova gratuita.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

  1. Install the Google Cloud CLI.
  2. To initialize the gcloud CLI, run the following command:

    gcloud init
  3. 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.

  4. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

Prova

  1. Esegui lo script di configurazione dal repository di esempio di codice 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 tra pochi secondi.

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

    Apri la pagina Cronologia build

  4. Fai clic sulla build più recente.

    Viene visualizzata la pagina Dettagli build, che mostra una riga di Cloud Build con tre passaggi di build: il primo passaggio crea un repository Cloud Source Repositories, il secondo passaggio clona i contenuti dell'esempio repository in GitHub a Cloud Source Repositories e il terzo passaggio aggiunge due e i 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 impegno 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. Attivatore apply è allegato al file infra/main.tfvars nel ramo main. Questo attivatore viene eseguita ogni volta che il file viene aggiornato. L'attivatore destroy è un attivatore trigger.

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

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

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

      Le modifiche apportate a infra/main.tfvars attivano l'esecuzione di 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.

    Visualizzerai il commit con la descrizione Promote green nel Cronologia nella parte inferiore della pagina.

  12. Per visualizzare l'esecuzione dell'attivatore apply, apri la pagina Cronologia di build nella console Google Cloud:

    Apri la pagina Cronologia build

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

    Vedrai la pipeline del trigger apply con due passaggi di build. Il primo il passaggio di build esegue Terraform apply per creare Compute Engine e caricare delle risorse per il deployment. Il secondo passaggio di build viene stampato l'indirizzo IP dove puoi vedere l'esecuzione dell'applicazione.

  14. Apri l'indirizzo IP corrispondente al gruppo di istanze gestite 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 le icone blu e Gruppi di istanze verdi:

    Apri la pagina Gruppo di istanze

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

    Apri la pagina Istanza VM

  17. Apri la pagina Indirizzi IP esterni per vedere 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 correlato allo script di configurazione.
  • Codice sorgente relativo alle pipeline di Cloud Build.
  • Codice sorgente relativo ai modelli Terraform.

Script di configurazione

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

  • Abilita Cloud Build, Resource Manager Compute Engine e le API Cloud Source Repositories.
  • Concede il ruolo IAM roles/editor all'account nel tuo progetto. Questo ruolo è richiesta per Cloud Build per creare e configurare Componenti GitOps per il deployment.
  • Concede il ruolo IAM roles/source.admin all'account nel tuo progetto. Questo ruolo è richiesta per l'account di servizio Cloud Build per creare Cloud Source Repositories del progetto e clona i contenuti dell'esempio il repository GitHub nel tuo Cloud Source Repositories.
  • Genera una pipeline Cloud Build denominata bootstrap.cloudbuild.yaml in linea, che:

    • Crea un nuovo repository in Cloud Source Repositories.
    • Copia il codice sorgente dal repository GitHub di esempio nel un nuovo repository in Cloud Source Repositories.
    • Crea i trigger di build apply e di eliminazione.
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 I file di configurazione di Cloud Build utilizzati dallo script di configurazione per il flusso GitOps. apply.cloudbuild.yaml contiene due passaggi di build:

  • tf_apply build passaggio di 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 definiti in bash_utils.sh e il passaggio di build utilizza il comando source per chiamare che li rappresentano.
  • describe_deployment passaggio di build che chiama la funzione describe_deployment che stampa gli indirizzi IP del carico bilanciatori del carico e bilanciatori del carico.

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

Le funzioni tf_install_in_cloud_build_step, tf_apply, describe_deployment e tf_destroy sono definiti nel file bash_utils.sh. I file di configurazione di compilazione 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 che è definita in bash_utils.sh. I file di configurazione di compilazione chiamano questa funzione a per installare Terraform al volo. Crea un bucket Cloud Storage e 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. Innanzitutto chiama terraform init, che carica tutti i moduli librerie personalizzate, quindi esegue terraform apply per caricare le variabili il 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 librerie 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 tutte le variabili e tutti i file di configurazione di Terraform copy-of-gcp-mig-simple/infra/ cartella.

  • main.tf: questo è il file di configurazione di Terraform
  • main.tfvars: questo file definisce le variabili Terraform.
  • mig/ e splitter/: queste cartelle contengono i moduli che definiscono bilanciatori del carico. La cartella mig/ contiene il file di configurazione di Terraform che definisce il gruppo di istanze gestite per i bilanciatori del carico blu e verde. L'architettura blu e i gruppi di istanze gestite sono identici, perciò vengono definiti e creazione di un'istanza per gli oggetti blu e verde. La configurazione di Terraform del bilanciatore del carico splitter si trova nella cartella splitter/ .

Il seguente snippet di codice mostra i contenuti di infra/main.tfvars. it contiene tre variabili: due che determinano la versione dell'applicazione di cui eseguire il deployment alle piscine 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:

  • Viene definita una variabile per il progetto Google Cloud.
  • Google è impostato come provider Terraform.
  • Viene definita una variabile per lo spazio dei nomi. Tutti gli oggetti creati da Terraform preceduta da questa variabile in modo che più versioni dell'applicazione possano essere distribuiti nello stesso progetto e i nomi degli oggetti non sono in conflitto con e l'altro.
  • Le variabili MIG_VER_BLUE, MIG_VER_BLUE e MIG_ACTIVE_COLOR sono 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 da infra/main.tf mostra l'istanza del separatore. Questo modulo assume il colore attivo in modo che lo strumento di ripartizione si carichi sa quale gruppo di istanze gestite 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 da infra/main.tf definisce due moduli identici per i gruppi di istanze gestite blu e verdi. Prende il colore, la rete e la subnet definiti nel modulo di suddivisione.

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 che vengono creati per l'attributo splitter MIG. Di seguito è riportato uno snippet di codice di splitter/main.tf che contiene la logica per passare tra il MIG verde e quello blu. È supportato da il servizio google_compute_region_backend_service, che può instradare il traffico a due regioni di backend: var.instance_group_blue o var.instance_group_green. capacity_scaler definisce la quantità di traffico da indirizzare.

Il seguente codice indirizza il 100% del traffico al colore specificato, ma puoi aggiornare questo codice per il deployment canary in modo da instradare il traffico a un sottoinsieme per conto degli 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 al blu e al verde gruppi di istanze gestite. Il seguente snippet di codice di questo file definisce utilizzato per creare i pool di VM. Tieni presente che questa istanza ha la proprietà del ciclo di vita di Terraform impostata su create_before_destroy. Questo perché, quando aggiorni la versione del pool, non puoi usare il metodo per creare la nuova versione dei pool quando viene ancora utilizzato la versione precedente del pool. Ma se la versione precedente del pool prima di creare il nuovo modello, ci sarà un periodo di tempo le piscine non sono disponibili. Per evitare questo scenario, impostiamo il ciclo di vita di Terraform su create_before_destroy in modo che venga creata prima la versione più recente di un pool di VM prima dell'eliminazione della versione precedente.

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 Trigger, individua la riga corrispondente all'eliminazione e fai clic su Esegui. Quando il trigger completa l'esecuzione, le risorse create dall'attivatore apply vengono eliminate.

  2. Elimina le risorse create durante il bootstrap 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

    Elimina un progetto Google Cloud:

    gcloud projects delete PROJECT_ID

Passaggi successivi