Men-deploy ke Compute Engine


Panduan ini menjelaskan cara melakukan deployment biru/hijau tanpa downtime di Grup Instance Terkelola (MIG) Compute Engine menggunakan Cloud Build dan Terraform.

Cloud Build memungkinkan Anda mengotomatiskan berbagai proses developer, termasuk membangun dan men-deploy aplikasi ke berbagai runtime seperti Compute Engine, Google Kubernetes Engine, GKE Enterprise, dan fungsi Cloud Run. Google Cloud

MIG Compute Engine memungkinkan Anda mengoperasikan aplikasi di beberapa Mesin Virtual (VM) yang identik. Anda dapat membuat beban kerja yang skalabel dan sangat tersedia dengan memanfaatkan layanan MIG otomatis, termasuk: penskalaan otomatis, autohealing, deployment regional (beberapa zona), dan update otomatis. Dengan menggunakan model deployment berkelanjutan biru/hijau, Anda akan mempelajari cara mentransfer traffic pengguna secara bertahap dari satu MIG (biru) ke MIG lain (hijau), yang keduanya berjalan dalam produksi.

Ringkasan desain

Diagram berikut menunjukkan model deployment biru/hijau yang digunakan oleh contoh kode yang dijelaskan dalam dokumen ini:

Model biru/hijau

Secara umum, model ini mencakup komponen berikut:

  • Dua kumpulan VM Compute Engine: Biru dan Hijau.
  • Tiga load balancer HTTP(S) eksternal:
    • Load balancer Blue/Green, yang merutekan traffic dari pengguna akhir ke kumpulan instance VM Blue atau Green.
    • Load balancer Biru yang merutekan traffic dari engineer dan developer QA ke kumpulan instance VM Biru.
    • Load balancer Green yang merutekan traffic dari engineer dan developer QA ke kumpulan instance Green.
  • Dua set pengguna:
    • Pengguna akhir yang memiliki akses ke load balancer Biru/Hijau, yang mengarahkan mereka ke kumpulan instance Biru atau Hijau.
    • Engineer QA dan developer yang memerlukan akses ke kedua set kumpulan untuk tujuan pengembangan dan pengujian. Mereka dapat mengakses load balancer Biru dan Hijau, yang masing-masing merutekan mereka ke kumpulan Instance Biru dan kumpulan instance Hijau.

Kumpulan VM Biru dan Hijau diimplementasikan sebagai MIG Compute Engine, dan alamat IP eksternal dirutekan ke VM di MIG menggunakan load balancer HTTP(s) eksternal. Contoh kode yang dijelaskan dalam dokumen ini menggunakan Terraform untuk mengonfigurasi infrastruktur ini.

Diagram berikut menggambarkan operasi developer yang terjadi dalam deployment:

Alur operasi developer

Dalam diagram di atas, panah merah menunjukkan alur bootstrapping yang terjadi saat Anda menyiapkan infrastruktur deployment untuk pertama kalinya, dan panah biru menunjukkan alur GitOps yang terjadi selama setiap deployment.

Untuk menyiapkan infrastruktur ini, Anda menjalankan skrip penyiapan yang memulai proses bootstrap dan menyiapkan komponen untuk alur GitOps.

Skrip penyiapan menjalankan pipeline Cloud Build yang melakukan operasi berikut:

  • Membuat repositori di Cloud Source Repositories bernama copy-of-gcp-mig-simple dan menyalin kode sumber dari repositori contoh GitHub ke repositori di Cloud Source Repositories.
  • Membuat dua pemicu Cloud Build bernama apply dan destroy.

Pemicu apply dilampirkan ke file Terraform bernama main.tfvars di Cloud Source Repositories. File ini berisi variabel Terraform yang merepresentasikan load balancer biru dan hijau.

Untuk menyiapkan deployment, Anda memperbarui variabel dalam file main.tfvars. Pemicu apply menjalankan pipeline Cloud Build yang mengeksekusi tf_apply dan melakukan operasi berikut:

  • Membuat dua MIG Compute Engine (satu untuk hijau dan satu untuk biru), empat instance VM Compute Engine (dua untuk MIG hijau dan dua untuk MIG biru), tiga load balancer (biru, hijau, dan pemisah), serta tiga alamat IP publik.
  • Mencetak alamat IP yang dapat Anda gunakan untuk melihat aplikasi yang di-deploy di instance biru dan hijau.

Pemicu penghancuran dipicu secara manual untuk menghapus semua resource yang dibuat oleh pemicu penerapan.

Tujuan

  • Gunakan Cloud Build dan Terraform untuk menyiapkan load balancer HTTP(S) eksternal dengan backend grup instance VM Compute Engine.

  • Lakukan blue/green deployment pada instance VM.

Biaya

Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Pengguna Google Cloud baru mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  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. Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.

  4. Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:

    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. Jika Anda menggunakan penyedia identitas (IdP) eksternal, Anda harus login ke gcloud CLI dengan identitas gabungan Anda terlebih dahulu.

  9. Untuk melakukan inisialisasi gcloud CLI, jalankan perintah berikut:

    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. Melakukan Percobaan

    1. Jalankan skrip penyiapan dari repositori contoh kode Google:

      bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/setup.sh)
      
    2. Saat skrip penyiapan meminta izin pengguna, masukkan yes.

      Skrip akan selesai berjalan dalam beberapa detik.

    3. Di konsol Google Cloud , buka halaman Build history Cloud Build:

      Buka halaman Histori build

    4. Klik build terbaru.

      Anda akan melihat halaman Build details, yang menampilkan pipeline Cloud Build dengan tiga langkah build: langkah build pertama membuat repositori di Cloud Source Repositories, langkah kedua meng-clone konten repositori contoh di GitHub ke Cloud Source Repositories, dan langkah ketiga menambahkan dua pemicu build.

    5. Buka Cloud Source Repositories:

      Membuka Cloud Source Repositories

    6. Dari daftar repositori, klik copy-of-gcp-mig-simple.

      Di tab History di bagian bawah halaman, Anda akan melihat satu commit dengan deskripsi A copy of https://github.com/GoogleCloudPlatform/cloud-build-samples.git yang dibuat oleh Cloud Build untuk membuat repositori bernama copy-of-gcp-mig-simple.

    7. Buka halaman Pemicu Cloud Build:

      Buka halaman Pemicu

    8. Anda akan melihat dua pemicu build bernama apply dan destroy. Pemicu apply dilampirkan ke file infra/main.tfvars di cabang main. Pemicu ini dijalankan setiap kali file diperbarui. Pemicu destroy adalah pemicu manual.

    9. Untuk memulai proses deployment, perbarui file infra/main.tfvars:

      1. Di jendela terminal, buat dan buka folder bernama deploy-compute-engine:

        mkdir ~/deploy-compute-engine
        cd ~/deploy-compute-engine
        
      2. Clone repo copy-of-gcp-mig-simple:

        gcloud source repos clone copy-of-mig-blue-green
        
      3. Buka direktori yang di-clone:

        cd ./copy-of-mig-blue-green
        
      4. Perbarui infra/main.tfvars untuk mengganti biru dengan hijau:

        sed -i'' -e 's/blue/green/g' infra/main.tfvars
        
      5. Tambahkan file yang telah diperbarui:

        git add .
        
      6. Lakukan commit file:

        git commit -m "Promote green"
        
      7. Kirim file:

        git push
        

        Melakukan perubahan pada infra/main.tfvars akan memicu eksekusi pemicu apply, yang memulai deployment.

    10. Buka Cloud Source Repositories:

      Membuka Cloud Source Repositories

    11. Dari daftar repositori, klik copy-of-gcp-mig-simple.

      Anda akan melihat commit dengan deskripsi Promote green di tab Histori di bagian bawah halaman.

    12. Untuk melihat eksekusi pemicu apply, buka halaman Build history di konsol Google Cloud :

      Buka halaman Histori build

    13. Buka halaman Build details dengan mengklik build pertama.

      Anda akan melihat pipeline pemicu apply dengan dua langkah build. Langkah build pertama menjalankan penerapan Terraform untuk membuat resource Compute Engine dan load balancing untuk deployment. Langkah build kedua mencetak alamat IP tempat Anda dapat melihat aplikasi berjalan.

    14. Buka alamat IP yang sesuai dengan MIG hijau di browser. Anda akan melihat screenshot yang mirip dengan berikut yang menunjukkan deployment:

      Deployment

    15. Buka halaman Instance group Compute Engine untuk melihat grup instance Biru dan Hijau:

      Buka halaman Instance group

    16. Buka halaman VM instances untuk melihat empat instance VM:

      Buka halaman Instance VM

    17. Buka halaman External IP addresses untuk melihat tiga load balancer:

      Buka halaman Alamat IP eksternal

    Memahami kode

    Kode sumber untuk contoh kode ini mencakup:

    • Kode sumber yang terkait dengan skrip penyiapan.
    • Kode sumber yang terkait dengan pipeline Cloud Build.
    • Kode sumber yang terkait dengan template Terraform.

    Skrip penyiapan

    setup.sh adalah skrip penyiapan yang menjalankan proses bootstrap dan membuat komponen untuk deployment biru/hijau. Skrip akan melakukan operasi berikut:

    • Mengaktifkan Cloud Build, Resource Manager, Compute Engine, dan Cloud Source Repositories API.
    • Memberikan peran IAM roles/editor ke akun layanan Cloud Build di project Anda. Peran ini diperlukan agar Cloud Build dapat membuat dan menyiapkan komponen GitOps yang diperlukan untuk deployment.
    • Memberikan peran IAM roles/source.admin ke akun layanan Cloud Build di project Anda. Peran ini diperlukan agar akun layanan Cloud Build dapat membuat Cloud Source Repositories di project Anda dan meng-clone konten repositori GitHub contoh ke Cloud Source Repositories Anda.
    • Membuat pipeline Cloud Build bernama bootstrap.cloudbuild.yaml secara inline, yang:

      • Membuat repositori baru di Cloud Source Repositories.
      • Menyalin kode sumber dari repositori GitHub contoh ke repositori baru di Cloud Source Repositories.
      • Membuat pemicu build penerapan dan penghancuran.
    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 Cloud Build

    apply.cloudbuild.yaml dan destroy.cloudbuild.yaml adalah file konfigurasi Cloud Build yang digunakan skrip penyiapan untuk menyiapkan resource untuk alur GitOps. apply.cloudbuild.yaml berisi dua langkah build:

    • Langkah build tf_apply build yang memanggil fungsi tf_install_in_cloud_build_step, yang menginstal Terraform. tf_apply yang membuat resource yang digunakan dalam alur GitOps. Fungsi tf_install_in_cloud_build_step dan tf_apply ditentukan di bash_utils.sh dan langkah build menggunakan perintah source untuk memanggilnya.
    • Langkah build describe_deployment yang memanggil fungsi describe_deployment yang mencetak alamat IP load balancer.

    Panggilan destroy.cloudbuild.yaml memanggil tf_destroy yang menghapus semua resource yang dibuat oleh tf_apply.

    Fungsi tf_install_in_cloud_build_step, tf_apply, describe_deployment, dan tf_destroy ditentukan dalam file bash_utils.sh. File konfigurasi build menggunakan perintah source untuk memanggil fungsi.

    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"

    Kode berikut menunjukkan fungsi tf_install_in_cloud_build_step yang ditentukan di bash_utils.sh. File konfigurasi build memanggil fungsi ini untuk menginstal Terraform secara langsung. Tindakan ini akan membuat bucket Cloud Storage untuk mencatat status 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)"
    }

    Cuplikan kode berikut menunjukkan fungsi tf_apply yang ditentukan di bash_utils.sh. Pertama-tama, fungsi ini memanggil terraform init yang memuat semua modul dan library kustom, lalu menjalankan terraform apply untuk memuat variabel dari 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"
    }

    Cuplikan kode berikut menunjukkan fungsi describe_deployment yang ditentukan di bash_utils.sh. Perintah ini menggunakan gcloud compute addresses describe untuk mengambil alamat IP load balancer menggunakan nama dan mencetaknya.

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

    Cuplikan kode berikut menunjukkan fungsi tf_destroy yang ditentukan di bash_utils.sh. Kemudian, terraform init akan memuat semua modul dan library kustom, lalu menjalankan terraform destroy yang membatalkan pemuatan variabel 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"
    }

    Template Terraform

    Anda akan menemukan semua file dan variabel konfigurasi Terraform di folder copy-of-gcp-mig-simple/infra/.

    • main.tf: ini adalah file konfigurasi Terraform
    • main.tfvars: file ini menentukan variabel Terraform.
    • mig/ dan splitter/: folder ini berisi modul yang menentukan load balancer. Folder mig/ berisi file konfigurasi Terraform yang menentukan MIG untuk load balancer Biru dan Hijau. MIG Biru dan MIG Hijau identik, sehingga ditentukan satu kali dan di-instansiasi untuk objek biru dan hijau. File konfigurasi Terraform untuk load balancer pemisah berada di folder splitter/ .

    Cuplikan kode berikut menunjukkan konten infra/main.tfvars. File ini berisi tiga variabel: dua variabel yang menentukan versi aplikasi yang akan di-deploy ke pool Biru dan Hijau, serta satu variabel untuk warna aktif: Biru atau Hijau. Perubahan pada file ini akan memicu deployment.

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

    Berikut adalah cuplikan kode dari infra/main.tf. Dalam cuplikan ini:

    • Variabel ditentukan untuk project Google Cloud .
    • Google ditetapkan sebagai penyedia Terraform.
    • Variabel ditentukan untuk namespace. Semua objek yang dibuat oleh Terraform diberi awalan dengan variabel ini sehingga beberapa versi aplikasi dapat di-deploy dalam project yang sama dan nama objek tidak bertabrakan satu sama lain.
    • Variabel MIG_VER_BLUE, MIG_VER_BLUE, dan MIG_ACTIVE_COLOR adalah binding untuk variabel dalam 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)."
    }

    Cuplikan kode berikut dari infra/main.tf menunjukkan instansiasi modul pemisah. Modul ini mengambil warna aktif sehingga load balancer pemisah mengetahui MIG mana yang akan men-deploy aplikasi.

    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
    }

    Cuplikan kode berikut dari infra/main.tf menentukan dua modul identik untuk MIG Biru dan Hijau. Fungsi ini menerima warna, jaringan, dan subnetwork yang ditentukan dalam modul pemisah.

    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
    }

    File splitter/main.tf menentukan objek yang dibuat untuk MIG pemisah. Berikut adalah cuplikan kode dari splitter/main.tf yang berisi logika untuk beralih antara MIG Hijau dan Biru. Layanan ini didukung oleh layanan google_compute_region_backend_service, yang dapat merutekan traffic ke dua region backend: var.instance_group_blue atau var.instance_group_green. capacity_scaler menentukan seberapa banyak traffic yang akan dirutekan.

    Kode berikut merutekan 100% traffic ke warna yang ditentukan, tetapi Anda dapat memperbarui kode ini untuk deployment canary guna merutekan traffic ke subset pengguna.

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

    File mig/main.tf menentukan objek yang berkaitan dengan MIG Biru dan Hijau. Cuplikan kode berikut dari file ini menentukan template instance Compute Engine yang digunakan untuk membuat kumpulan VM. Perhatikan bahwa template instance ini memiliki properti siklus proses Terraform yang ditetapkan ke create_before_destroy. Hal ini karena, saat memperbarui versi pool, Anda tidak dapat menggunakan template untuk membuat versi baru pool saat masih digunakan oleh versi pool sebelumnya. Namun, jika versi pool yang lebih lama dihapus sebelum template baru dibuat, akan ada periode waktu saat pool tidak berfungsi. Untuk menghindari skenario ini, kita menetapkan siklus proses Terraform ke create_before_destroy sehingga versi yang lebih baru dari kumpulan VM dibuat terlebih dahulu sebelum versi yang lebih lama dihapus.

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

    Pembersihan

    Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

    Menghapus resource satu per satu

    1. Hapus resource Compute Engine yang dibuat oleh pemicu penerapan:

      1. Buka halaman Pemicu Cloud Build:

        Buka halaman Pemicu

      2. Di tabel Triggers, temukan baris yang sesuai dengan pemicu destroy, lalu klik Run. Setelah pemicu selesai dieksekusi, resource yang dibuat oleh pemicu apply akan dihapus.

    2. Hapus resource yang dibuat selama bootstrapping dengan menjalankan perintah berikut di jendela terminal:

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

    Menghapus project

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    Langkah berikutnya