This guide explains how to perform zero-downtime blue/green deployments on Compute Engine Managed Instance Groups (MIGs) using Cloud Build and Terraform.
Cloud Build enables you to automate a variety of developer processes, including building and deploying applications to various Google Cloud runtimes such as Compute Engine, Google Kubernetes Engine, GKE Enterprise, and Cloud Run functions.
Compute Engine MIGs enable you to operate applications on multiple identical Virtual Machines (VMs). You can make your workloads scalable and highly available by taking advantage of automated MIG services, including: autoscaling, autohealing, regional (multiple zone) deployment, and automatic updating. Using the blue/green continuous deployment model, you will learn how to gradually transfer user traffic from one MIG (blue) to another MIG (green), both of which are running in production.
Design overview
The following diagram shows the blue/green deployment model used by the code sample described in this document:
At a high level, this model includes the following components:
- Two Compute Engine VM pools: Blue and Green.
- Three external HTTP(S) load balancers:
- A Blue/Green load balancer, that routes traffic from end users to either the Blue or the Green pool of VM instances.
- A Blue load balancer that routes traffic from QA engineers and developers to the Blue VM instance pool.
- A Green load balancer that routes traffic from QA engineers and developers to the Green instance pool.
- Two sets of users:
- End users who have access to the Blue/Green load balancer, which points them to either the Blue or the Green instance pool.
- QA engineers and developers who require access to both sets of pools for development and testing purposes. They can access both the Blue and the Green load balancers, which routes them to the Blue Instance pool and the Green instance pool respectively.
The Blue and the Green VMs pools are implemented as Compute Engine MIGs, and external IP addresses are routed into the VMs in the MIG using external HTTP(s) load balancers. The code sample described in this document uses Terraform to configure this infrastructure.
The following diagram illustrates the developer operations that happens in the deployment:
In the diagram above, the red arrows represent the bootstrapping flow that occurs when you set up the deployment infrastructure for the first time, and the blue arrows represent the GitOps flow that occurs during every deployment.
To set up this infrastructure, you run a setup script that starts the bootstrap process and sets up the components for the GitOps flow.
The setup script executes a Cloud Build pipeline that performs the following operations:
- Creates a repository in Cloud Source Repositories
named
copy-of-gcp-mig-simple
and copies the source code from the GitHub sample repository to the repository in Cloud Source Repositories. - Creates two Cloud Build triggers named
apply
anddestroy
.
The apply
trigger is attached to a Terraform file named main.tfvars
in the
Cloud Source Repositories. This file contains the Terraform variables representing
the blue and the green load balancers.
To set up the deployment, you update the variables in the main.tfvars
file.
The apply
trigger runs a Cloud Build pipeline that executes
tf_apply
and performs the following operations:
- Creates two Compute Engine MIGs (one for green and one for blue), four Compute Engine VM instances (two for the green MIG and two for the blue MIG), the three load balancers (blue, green, and the splitter), and three public IP addresses.
- Prints out the IP addresses that you can use to see the deployed applications in the blue and the green instances.
The destroy trigger is triggered manually to delete all the resources created by the apply trigger.
Objectives
Use Cloud Build and Terraform to set up external HTTP(S) load balancers with Compute Engine VM instance group backends.
Perform blue/green deployments on the VM instances.
Costs
In this document, you use the following billable components of Google Cloud:
To generate a cost estimate based on your projected usage,
use the pricing calculator.
When you finish the tasks that are described in this document, you can avoid continued billing by deleting the resources that you created. For more information, see Clean up.
Before you begin
- 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.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
Trying it out
Run the setup script from the Google code sample repository:
bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/setup.sh)
When the setup script asks for user consent, enter yes.
The script finishes running in a few seconds.
In the Google Cloud console, open the Cloud Build Build history page:
Click on the latest build.
You see the Build details page, which shows a Cloud Build pipeline with three build steps: the first build step creates a repository in Cloud Source Repositories, the second step clones the contents of the sample repository in GitHub to Cloud Source Repositories, and the third step adds two build triggers.
Open Cloud Source Repositories:
From the repositories list, click
copy-of-gcp-mig-simple
.In the History tab at the bottom of the page, you'll see one commit with the description
A copy of https://github.com/GoogleCloudPlatform/cloud-build-samples.git
made by Cloud Build to create a repository namedcopy-of-gcp-mig-simple
.Open the Cloud Build Triggers page:
To start the deploy process, update the
infra/main.tfvars
file:In your terminal window, create and navigate into a folder named
deploy-compute-engine
:mkdir ~/deploy-compute-engine cd ~/deploy-compute-engine
Clone the
copy-of-gcp-mig-simple
repo:gcloud source repos clone copy-of-mig-blue-green
Navigate into the cloned directory:
cd ./copy-of-mig-blue-green
Update
infra/main.tfvars
to replace blue with green:sed -i'' -e 's/blue/green/g' infra/main.tfvars
Add the updated file:
git add .
Commit the file:
git commit -m "Promote green"
Push the file:
git push
Making changes to
infra/main.tfvars
triggers the execution of theapply
trigger, which starts the deployment.
Open Cloud Source Repositories:
From the repositories list, click
copy-of-gcp-mig-simple
.You'll see the commit with the description
Promote green
in the History tab at the bottom of the page.To view the execution of the
apply
trigger, open the Build history page in the Google Cloud console:Open the Build details page by clicking on the first build.
You will see the
apply
trigger pipeline with two build steps. The first build step executes Terraform apply to create the Compute Engine and load balancing resources for the deployment. The second build step prints out the IP address where you can see the application running.Open the IP address corresponding to the green MIG in a browser. You'll see a screenshot similar to the following showing the deployment:
Go to the Compute Engine Instance group page to see the Blue and the Green instance groups:
Open the VM instances page to see the four VM instances:
Open the External IP addresses page to see the three load balancers:
You'll see two build triggers named apply
and destroy
. The apply
trigger
is attached to the infra/main.tfvars
file in the main
branch. This trigger
is executed anytime the file is updated. The destroy
trigger is a manual
trigger.
Understanding the code
Source code for this code sample includes:
- Source code related to the setup script.
- Source code related to the Cloud Build pipelines.
- Source code related to the Terraform templates.
Setup script
setup.sh
is the setup script that runs the bootstrap process and creates the
components for the blue/green deployment. The script performs the following
operations:
- Enables the Cloud Build, Resource Manager, Compute Engine, and Cloud Source Repositories APIs.
- Grants the
roles/editor
IAM role to the Cloud Build service account in your project. This role is required for Cloud Build to create and set up the necessary GitOps components for the deployment. - Grants the
roles/source.admin
IAM role to the Cloud Build service account in your project. This role is required for the Cloud Build service account to create the Cloud Source Repositories in your project and clone the contents of the sample GitHub repository to your Cloud Source Repositories. Generates a Cloud Build pipeline named
bootstrap.cloudbuild.yaml
inline, that:- Creates a new repository in Cloud Source Repositories.
- Copies the source code from the sample GitHub repository to the new repository in Cloud Source Repositories.
- Creates the apply and destroy build triggers.
Cloud Build pipelines
apply.cloudbuild.yaml
and destroy.cloudbuild.yaml
are the
Cloud Build config files that the setup script uses to set up the
resources for the GitOps flow. apply.cloudbuild.yaml
contains two build steps:
tf_apply build
build step that calls the functiontf_install_in_cloud_build_step
, which installs Terraform.tf_apply
that creates the resources used in the GitOps flow. The functionstf_install_in_cloud_build_step
andtf_apply
are defined inbash_utils.sh
and the build step uses thesource
command to call them.describe_deployment
build step that calls the functiondescribe_deployment
that prints out the IP addresses of the load balancers.
destroy.cloudbuild.yaml
calls tf_destroy
that deletes all the resources
created by tf_apply
.
The functions tf_install_in_cloud_build_step
, tf_apply
,
describe_deployment
, and tf_destroy
are defined in the file bash_utils.sh
.
The build config files use the source
command to call the functions.
The following code shows the function tf_install_in_cloud_build_step
that's
defined in bash_utils.sh
. The build config files call this function to
install Terraform on the fly. It creates a Cloud Storage bucket to
record the Terraform status.
The following code snippet shows the function tf_apply
that's defined in
bash_utils.sh
. It first calls terraform init
that loads all modules and
custom libraries and then runs terraform apply
to load the variables from
the main.tfvars
file.
The following code snippet shows the function describe_deployment
that's
defined in bash_utils.sh
. It uses gcloud compute addresses describe
to fetch
the IP addresses of the load balancers using the name and prints them out.
The following code snippet shows the function tf_destroy
that's defined in
bash_utils.sh
. It calls terraform init
that loads all modules and custom
libraries and then runs terraform destroy
that unloads the Terraform variables.
Terraform templates
You'll find all the Terraform configuration files and variables in the
copy-of-gcp-mig-simple/infra/
folder.
main.tf
: this is the Terraform configuration filemain.tfvars
: this file defines the Terraform variables.mig/
andsplitter/
: these folders contain the modules that define the load balancers. Themig/
folder contains the Terraform configuration file that defines the MIG for the Blue and the Green load balancers. The Blue and the Green MIGs are identical, therefore they are defined once and instantiated for the blue and the green objects. The Terraform configuration file for the splitter load balancer is in thesplitter/
folder .
The following code snippet shows the contents of infra/main.tfvars
. It
contains three variables: two that determine what application version to deploy
to the Blue and the Green pools and a variable for the active color: Blue or
Green. Changes to this file triggers the deployment.
The following is a code snippet from infra/main.tf
. In this snippet:
- A variable is defined for the Google Cloud project.
- Google is set as the Terraform provider.
- A variable is defined for namespace. All objects created by Terraform are prefixed with this variable so that multiple versions of the application can be deployed in the same project and the object names don't collide with each other.
- Variables
MIG_VER_BLUE
,MIG_VER_BLUE
, andMIG_ACTIVE_COLOR
are the bindings for the variables in theinfra/main.tfvars
file.
The following code snippet from infra/main.tf
shows the instantiation of the
splitter module. This module takes in the active color so that the splitter load
balancer knows which MIG to deploy the application.
The following code snippet from infra/main.tf
defines two identical modules
for Blue and Green MIGs. It takes in the color, the network, and the subnetwork
which are defined in the splitter module.
The file splitter/main.tf
defines the objects that are created for the
splitter MIG. The following is a code snippet from splitter/main.tf
that
contains the logic to switch between the Green and the Blue MIG. It's backed by
the service google_compute_region_backend_service
, which can route traffic to
two backend regions: var.instance_group_blue
or var.instance_group_green
.
capacity_scaler
defines how much of the traffic to route.
The following code routes 100% of the traffic to the specified color, but you can update this code for canary deployment to route the traffic to a subset of the users.
The file mig/main.tf
defines the objects pertaining to the Blue and the Green
MIGs. The following code snippet from this file defines the Compute Engine
instance template that's used to create the VM pools. Note that this instance
template has the Terraform lifecycle property set to create_before_destroy
.
This is because, when updating the version of the pool, you cannot use the
template to create the new version of the pools when it is still being used by
the previous version of the pool. But if the older version of the pool is
destroyed before creating the new template, there'll be a period of time when
the pools are down. To avoid this scenario, we set the Terraform lifecycle to
create_before_destroy
so that the newer version of a VM pool is created first
before the older version is destroyed.
Clean up
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
Delete individual resources
Delete the Compute Engine resources created by the apply trigger:
Open the Cloud Build Triggers page:
In the Triggers table, locate the row corresponding to the destroy trigger, and click Run. When the trigger completes execution, the resources created by the apply trigger are deleted.
Delete the resources created during bootstrapping by running the following command in your terminal window:
bash <(curl https://raw.githubusercontent.com/GoogleCloudPlatform/cloud-build-samples/main/mig-blue-green/teardown.sh)
Delete the project
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
What's next
- Learn more about build triggers.
- Learn how to view build provenance.