In this lab, you create a managed instance group and configure it for scaling based on its capacity to handle genome sequence alignment requests against a configurable reference genome using the bwa mem software. You associate your managed Compute Engine instance group with a backend service you define to handle traffic. You configure the necessary resources required to create a simple HTTP load balancer deployment. You test health checks associated with the HTTP load balancer and observe the way traffic is distributed amongst Google Compute Engine instances within the managed instance group.

An illustration of the fully configured system follows:

Sources are available in GitHub. Note that this codelab uses a component from a larger project for aligning and analyzing data from a DNA nanopore sequencer. For more information about how to do this, please read the blog post Nanopore DNA Sequencer Real-time Stream Processing on Google Cloud.

What you need

To complete this lab, you need access to a supported Internet browser:

What you learn

In this lab, you:

In this lab, you build on all the previous labs to create a highly available and scalable deployment of a HTTP-based interface to bwa mem. This is a relatively complex lab and yet still a relatively simple HTTP load balancing configuration that includes a single availability zone and instance templates that leverage Docker images.

This lab provides a basic foundation for working with load balancing but there is much more to learn in relation to this topic including HTTPS load balancing, as well as network load balancing to handle other protocols such as SMTP.

By completing this codelab you will:

  1. Prepare your working environment in with Cloud Shell
  2. Create a new Compute Engine instance template that references a Docker image
  3. Create a managed instance group that will be auto-scaled based on workload
  4. Create a HTTP health check that will be used to determine whether an instance is available to accept work requests
  5. Create a load balancer that routes work requests to workers in the managed instance group
  6. Test various aspects of your HTTP load balancer deployment, including the HTTP health check resources you create to monitor the health of your instances. You also observe how traffic is routed across the instances in the managed instance group in the backend service
  7. Clean up the environment by deleting all created services and configurations

Select Project and Open GCP Console

Open the Cloud Platform Console, and ensure you have selected the project in which you would like to do this codelab.

Set Environment Variables

Paste the following commands to load the values of all variables for this course into your shell session. Note that these contents are in the codelab's git repository in the file

export NAME="bwa-rice"
export REGION="us-east1"
export ZONE="${REGION}-d"
export MACHINE_TYPE="n1-standard-1"
export DOCKER_IMAGE="allenday/bwa-http-docker:http"
export BWA_FILES="gs://rice-3k/reference/Os-Nipponbare-Reference-IRGSP-1.0/*"

Note that we are using a rice reference genome and sample, and this is reflected in a base $NAME variable used throughout the remainder of the codelab.

Now you'll prepare a new Compute Engine instance template. Instantiations of this template allow bwa to be accessed over HTTP, uploading FastQ records and downloading SAM records.

Create Instance Template

Type the following command to create the instance template:"

# create instance template
gcloud compute instance-templates \
    create-with-container ${NAME}-template \
        --container-image="${DOCKER_IMAGE}" \
        --container-env "BWA_FILES=${BWA_FILES}" \
        --boot-disk-size=200GB \
        --tags http-server,http \
        --preemptible \

The output confirms that the instance is created.

Created [].
bwa-rice-template  n1-standard-1  true         YYYY-MM-DDT03:21:16.253-08:00

Two details to note here:

  1. We are using a custom Docker image, allenday/bwa-http-docker, in this instance template that will be providing access to the bwa software over HTTP.
  2. We are using a custom Cloud Storage path for the pre-built bwa index files for the rice reference genome IRGSP 1.0. Both the input FastA and the bwa index files are located in a Cloud Storage bucket: gs://aligner-deployment/reference/Os-Nipponbare-Reference-IRGSP-1.0/*.

HTTP health checks are used by two components in this codelab:

  1. HTTP load balancers rely on HTTP health checks to ensure traffic is only routed to instances where working copies of an application are running
  2. Auto-healing managed instance groups use HTTP health checks to verify the integrity of members of the instance group, replacing unhealthy instances as necessary.

Create HTTP Health Check

Type the following command to create an HTTP health check:

# create HTTP health check
gcloud compute http-health-checks \
    create ${NAME}-health-check \
        --request-path /cgi-bin/bwa.cgi

The output confirms that the resource has been created and prints the port and request path associated with this health check.

Created [].
NAME                   HOST  PORT  REQUEST_PATH
bwa-rice-health-check        80    /cgi-bin/bwa.cgi

This defines the endpoint that will be used to check the health of the application. Note that we are using a specific path served by the HTTP service, /cgi-bin/bwa.cgi. This corresponds to a CGI script present in the Docker image that provides an interface to bwa. We'll use this health check later for configuring both the Managed Instance Group for Auto-Healing, as well as for the HTTP load balancer.

Create Managed Instance Group

Create a managed instance group. Before you can configure your HTTP load balancer resources, you first create a managed instance group and configure it for scaling.

Here we're creating an instance group that will create Compute Engine instances with a base name of bwa-rice. The instance group will have at minimum one instance at all times.

# create managed instance group
gcloud compute instance-groups managed \
    create ${NAME}-managed-instance-group \
        --base-instance-name ${NAME} \
        --size $MIN_REPLICAS \
        --template ${NAME}-template \
        --zone $ZONE

The output displays the progress of the operation and confirms when the resource is created.

Created [].
bwa-rice-managed-instance-group  us-east1-d  zone   bwa-rice            0     1            bwa-rice-template  no

Create Named Ports

Create named ports. You need to specify labels for the managed instance group to define a service endpoint that will be used by the Load Balancing service. The label takes the form of a simple key:value pair that represents the name of the service and the port it is running on and indicates that the service is available on all instances in the group. Type the following command to specify the service endpoint for this group on port 80.

gcloud compute instance-groups managed \
    set-named-ports ${NAME}-managed-instance-group \
        --named-ports http:80 \
        --zone $ZONE

The output displays the progress of the operation and confirms when the resource is created.

Updated [].

Configure Managed Instance Group Auto-Scaling

You now create an autoscaler instance to attach to your instance group, bwa-rice-managed-instance-group. In this lab, you are using a policy to scale based on CPU utilization of the compute engine instances in the managed instance group.

gcloud compute instance-groups managed \
    set-autoscaling ${NAME}-managed-instance-group \
        --max-num-replicas $MAX_REPLICAS \
        --min-num-replicas $MIN_REPLICAS \
        --target-cpu-utilization $TARGET_CPU_UTILIZATION \
        --cool-down-period 120 \
        --zone $ZONE

The output describes the creation of the autoscaler and summarizes the details of the new resource.

Created [].
  coolDownPeriodSec: 120
    utilizationTarget: 0.5
  maxNumReplicas: 3
  minNumReplicas: 1
creationTimestamp: 'YYYY-MM-DDT03:33:12.156-08:00'
id: '159473396323672600'
kind: compute#autoscaler
name: bwa-rice-managed-instance-group-bc0p
status: ACTIVE

Configure Managed Instance Group Auto-Healing

Configure auto-healing for the managed instance group. We're using the HTTP health check defined previously to verify that the HTTP server is able to provide BWA alignment services. We're also delaying the first incidence of the health check by 180 seconds to give a newly created instance time to initialize. The purpose of the initial delay is needed in this case to allow the Compute Engine instance to download the Docker image and also synchronize bwa index files to local storage (see Step 3).

# configure managed instance group auto-healing
gcloud beta compute instance-groups managed \
    set-autohealing ${NAME}-managed-instance-group \
        --http-health-check ${NAME}-health-check \
        --initial-delay 180 \
        --zone $ZONE

The output displays the progress of the operation and confirms when the resource is created.

Updated [].
- healthCheck:
  initialDelaySec: 180
baseInstanceName: bwa-rice
creationTimestamp: 'YYYY-MM-DDT03:23:06.595-08:00'
  abandoning: 0
  creating: 0
  creatingWithoutRetries: 0
  deleting: 0
  none: 1
  recreating: 0
  refreshing: 0
  restarting: 0
  verifying: 0
fingerprint: bZki35_OWBA=
id: '6832257938850014325'
kind: compute#instanceGroupManager
name: bwa-rice-managed-instance-group
- name: http
  port: 80
  creating: 0
  deleting: 0
  recreating: 0
  restarting: 0
  isStable: true
targetSize: 1
    calculated: 1
    fixed: 1
    calculated: 1
    fixed: 1
  minReadySec: 0
  minimalAction: REPLACE
- instanceTemplate:
    calculated: 1

A load balancer is composed of a backend service, a frontend service, and a health check

Create Load Balancer Backend Service

HTTP health checks operate against instances that are members of a backend service. Instances are added to backend services through their association with managed or regular instance groups. Instances cannot be added directly to a backend service. Backend services can include multiple managed instance groups located in different zones.

Type the following command to create a backend service and associate the HTTP health check from the previous step with the new resource.

# create load balancer backend service
gcloud compute backend-services \
    create ${NAME}-backend-service \
        --http-health-checks ${NAME}-health-check \

The output confirms that the new resource has been created and prints the details including the name and associated protocol. In this case, it is set to the default value, HTTP.

Created [].
NAME                      BACKENDS  PROTOCOL
bwa-rice-backend-service            HTTP

Configure Load Balancer Backend Service

Create a backend service for the load balancer. It's configured to send traffic to different backends to make the average utilization the same across all workers in the instance group.

# configure load balancer backend service
gcloud compute backend-services \
    add-backend ${NAME}-backend-service \
    --instance-group ${NAME}-managed-instance-group \
        --balancing-mode UTILIZATION \
        --max-utilization $TARGET_CPU_UTILIZATION \
        --instance-group-zone $ZONE \

The output displays the progress of the operation and confirms that the resource is created.

Updated [].

Configure Load Balancer URL Maps

Load Balancing allows you to direct traffic to different instances based on the incoming URL. For this application, we can send all traffic to a default backend service.

# configure load balancer URL-maps
gcloud compute url-maps \
    create ${NAME}-url-map \
        --default-service ${NAME}-backend-service

The output displays the progress of the operation and confirms when the resource is created.

Created [].
bwa-rice-url-map  backendServices/bwa-rice-backend-service

Create Load Balancer Frontend

Now register the service to a Google Front End, effectively a reverse proxy. In this application we map an input IP address, port, and HTTP path to the backend we previously created.

First connect the proxy and the URL map:

# create load balancer frontend
gcloud compute target-http-proxies \
    create ${NAME}-target-proxy \
        --url-map ${NAME}-url-map

The output displays the progress of the operation and confirms when the resource is created.

Created [].
NAME                   URL_MAP
bwa-rice-target-proxy  bwa-rice-url-map

Then connect the proxy to the balancer IP and port:

# configure load balancer frontend
gcloud compute forwarding-rules \
    create ${NAME}-forward \
        --global \
        --ports 80 \
        --target-http-proxy ${NAME}-target-proxy

The output displays the progress of the operation and confirms when the resource is created.

Created [].

Port 80 is not allowed by default. Open it.

# create firewall rule
gcloud compute firewall-rules \
    create allow-http \
        --allow tcp:80 \
        --target-tags http-server

The output displays the progress of the operation and confirms when the resource is created.

Creating firewall...⠏Created [].
Creating firewall...done.
allow-http  default  INGRESS    1000      tcp:80        False

Now do the following to test your configured cluster and load balancer:

# get load balancer frontend IP address
FRONTEND=`gcloud compute forwarding-rules describe ${NAME}-forward --global | grep IPAddress | cut -d' ' -f2`

#get example data
curl -O

curl -X POST -F 'database=Os-Nipponbare-Reference-IRGSP-1.0.fa' -F 'fastq=@example-rice-fastq.fq' http://$FRONTEND/cgi-bin/bwa.cgi

If all goes well, you'll see a response like this:

@SQ     SN:Chr1 LN:43270923
@SQ     SN:Chr2 LN:35937250
@SQ     SN:Chr3 LN:36413819
@SQ     SN:Chr4 LN:35502694
@SQ     SN:Chr5 LN:29958434
@SQ     SN:Chr6 LN:31248787
@SQ     SN:Chr7 LN:29697621
@SQ     SN:Chr8 LN:28443022
@SQ     SN:Chr9 LN:23012720
@SQ     SN:Chr10        LN:23207287
@SQ     SN:Chr11        LN:29021106
@SQ     SN:Chr12        LN:27531856
@SQ     SN:ChrUn        LN:633585
@SQ     SN:ChrSy        LN:592136
@PG     ID:bwa  PN:bwa  VN:0.7.15-r1140 CL:bwa mem /data/Os-Nipponbare-Reference-IRGSP-1.0.fa /tmp/uPibPOdzRB.fq
example-fastq-data      0       Chr1    1001    60      150M    *       0       0       CTAAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAACCCTAAACCCTAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAAACCCTAAACAGCTGACAGTACGATAGATCCACGCGAGAGGAAC    "##"""""#1'##.&&'#&(&'($&'+)""#"##"""$#&*&+),&$##$*-(,-1850*(&###&(*'&&),//($'*(%'#%##(('"$"&#"$')&$"$&+($#"$(%%"""""#$$"%##"%#%""'$#+*,$,*%%$%"&$++$"  NM:i:0  MD:Z:150        AS:i:150  XS:i:109

Congratulations! It worked and you've completed the codelab!

Once you are finished with test resources, we recommend deleting them as you incur costs as long as they are allocated. There are a large number of resources that need to be deleted as a result of this lab. The quickest and simplest method is using the following command, although you must ensure that there are no errors.

# delete forwarding rule
yes | gcloud compute forwarding-rules delete ${NAME}-forward --global
# delete target proxy
yes | gcloud compute target-http-proxies delete ${NAME}-target-proxy
# delete url-map
yes | gcloud compute url-maps delete ${NAME}-url-map
# delete backend service
yes | gcloud compute backend-services delete ${NAME}-backend-service --global
# delete managed instance group
yes | gcloud compute instance-groups managed delete ${NAME}-managed-instance-group --zone $ZONE
# delete instance template
yes | gcloud compute instance-templates delete ${NAME}-template
# delete HTTP health check
yes | gcloud compute http-health-checks delete ${NAME}-health-check
# delete firewall rule
yes | gcloud compute firewall-rules delete allow-http

After completing this lab, your instructor will lead you through the following review activity. You can find a reference solution with suggestions at the end of the lab.


What you learned

In this lab, you:

The answers to the lab challenge questions are as follows: