Per-Instance Weighted Network Load Balancing

1. Introduction

You can configure a network load balancer to distribute traffic across the load balancer's backend instances based on the weights reported by an HTTP health check using weighted load balancing.

Weighted load balancing requires that you configure both of the following:

  • You must set the locality load balancer policy (localityLbPolicy) of the backend service to WEIGHTED_MAGLEV.
  • You must configure the backend service with an HTTP/HTTP2/HTTPS health check. The HTTP health check responses must contain a custom HTTP response header field X-Load-Balancing-Endpoint-Weight to specify the weights with integer values from 0 to 1000 in decimal representation for each backend instance.

If you use the same instance group as a backend for multiple backend service-based network load balancers using weighted load balancing, it's recommended to use a unique request-path for each health check of the backend service. For more information, see Success criteria for HTTP, HTTPS, and HTTP/2 health checks.

The HTTP health check should return an HTTP 200 (OK) response for the health-checks to pass and the backend instance regarded as healthy. In situations where all backend instances pass their health checks and return X-Load-Balancing-Endpoint-Weight with zero weight, the load balancer distributes new connections among the healthy backends, treating them with equal weight. The load balancer can also distribute new connections among unhealthy backends. For more information, see Traffic distribution.

For examples of weighted load balancing, see Backend selection and connection tracking.

Weighted load balancing can be used in the following scenarios:

  • If some connections process more data than others, or some connections live longer than others, the backend load distribution might get uneven. By signaling a lower per-instance weight, an instance with high load can reduce its share of new connections, while it keeps servicing existing connections.
  • If a backend is overloaded and assigning more connections might break existing connections, such backends assign zero weight to itself. By signaling zero weight, a backend instance stops servicing new connections, but continues to service existing ones.
  • If a backend is draining existing connections before maintenance, it assigns zero weight to itself. By signaling zero weight, the backend instance stops servicing new connections, but continues to service existing ones.

What you'll learn

  • How to configure a network load balancer to distribute traffic across the load balancer's backend instances based on the weights reported by an HTTP health check using weighted load balancing.

Self-paced environment setup

  1. Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • The Project name is the display name for this project's participants. It is a character string not used by Google APIs. You can update it at any time.
  • The Project ID is unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference the Project ID (it is typically identified as PROJECT_ID). If you don't like the generated ID, you may generate another random one. Alternatively, you can try your own and see if it's available. It cannot be changed after this step and will remain for the duration of the project.
  • For your information, there is a third value, a Project Number which some APIs use. Learn more about all three of these values in the documentation.
  1. Next, you'll need to enable billing in the Cloud Console to use Cloud resources/APIs. Running through this codelab shouldn't cost much, if anything at all. To shut down resources so you don't incur billing beyond this tutorial, you can delete the resources you created or delete the whole project. New users of Google Cloud are eligible for the $300 USD Free Trial program.

Start Cloud Shell

While Google Cloud can be operated remotely from your laptop, in this codelab you will be using Google Cloud Shell, a command line environment running in the Cloud.

From the Google Cloud Console, click the Cloud Shell icon on the top right toolbar:

55efc1aaa7a4d3ad.png

It should only take a few moments to provision and connect to the environment. When it is finished, you should see something like this:

7ffe5cbb04455448.png

This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory, and runs on Google Cloud, greatly enhancing network performance and authentication. All of your work in this codelab can be done within a browser. You do not need to install anything.

2. Start Configuration

Codelab requires a single project.

In this tutorial, you create an instance group with three VM instances and assign weights for each instance. You create an HTTP health check to report backend instance weights. Weighted network load balancer is enabled on the backend service with locality load balancer policy as WEIGHTED_MAGLEV.

Before you begin

gcloud services enable compute.googleapis.com

Note: You cannot use the Google Cloud console to configure the locality load balancer policy and assign weights to VM instances. Use the Google Cloud CLI instead.

Create VPC network, subnets, and firewall rules

Create a VPC network, subnet, and ingress allow firewall rules to allow connections to the backend VMs of your load balancer.

  1. Create a VPC network and subnet. a. To create the VPC network, run the gcloud compute networks create command:
gcloud compute networks create NETWORK_NAME --subnet-mode custom

b. In this example, the subnet's primary IPv4 address range is 10.10.0.0/24.

To create the subnet, run the gcloud compute networks subnets create command:

gcloud compute networks subnets create SUBNET_NAME \
  --network=NETWORK_NAME \
  --range=10.10.0.0/24 \
  --region=us-central1

Replace the following:

  • NETWORK_NAME: the name of the VPC network to create.
  • SUBNET_NAME: the name of the subnetwork to create.
  1. Create an ingress allow firewall rule to allow packets sent to destination TCP ports 80 and 443 to be delivered to the backend VMs. In this example, firewall rule allows connections from any source IP address. The firewall rule applies to VMs with the network tag network-lb-tag. To create the firewall rule, run the gcloud compute firewall-rules create command:
gcloud compute firewall-rules create FIREWALL_RULE_NAME \
   --direction=INGRESS \
   --priority=1000 \
   --network=NETWORK_NAME \
   --action=ALLOW \
   --rules=tcp:80,tcp:443 \
   --source-ranges=0.0.0.0/0 \
   --target-tags=network-lb-tag

Replace FIREWALL_RULE_NAME with the name of the firewall rule to create.

Create VM instances and assign weights

Create three VM instances and assign weights:

  1. Configure three backend VM instances to return the weights in the X-Load-Balancing-Endpoint-Weight header with HTTP responses. For this tutorial, you configure one backend instance to report a weight of zero, a second backend instance to report a weight of 100, and a third backend instance to report a weight of 900. To create the instances, run the gcloud compute instances createcommand:
gcloud compute instances create instance-0 \
  --zone=us-central1-a \
  --tags=network-lb-tag \
  --image-family=debian-10 \
  --image-project=debian-cloud \
  --subnet=
SUBNET_NAME
\
  --metadata=load-balancing-weight=0,startup-script='#! /bin/bash
  apt-get update
  apt-get install apache2 -y
  ln -sr /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load
  vm_hostname="$(curl -H "Metadata-Flavor:Google" \
  http://169.254.169.254/computeMetadata/v1/instance/name)"
  echo "Page served from: $vm_hostname" | \
  tee /var/www/html/index.html
  lb_weight="$(curl -H "Metadata-Flavor:Google" \
  http://169.254.169.254/computeMetadata/v1/instance/attributes/load-balancing-weight)"
  echo "Header set X-Load-Balancing-Endpoint-Weight \"$lb_weight\"" | \
  tee /etc/apache2/conf-enabled/headers.conf
  systemctl restart apache2'
gcloud compute instances create instance-100 \
  --zone=us-central1-a \
  --tags=network-lb-tag \
  --image-family=debian-10 \
  --image-project=debian-cloud \
  --subnet=SUBNET_NAME \
  --metadata=load-balancing-weight=100,startup-script='#! /bin/bash
  apt-get update
  apt-get install apache2 -y
  ln -sr /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load
  vm_hostname="$(curl -H "Metadata-Flavor:Google" \
  http://169.254.169.254/computeMetadata/v1/instance/name)"
  echo "Page served from: $vm_hostname" | \
  tee /var/www/html/index.html
  lb_weight="$(curl -H "Metadata-Flavor:Google" \
  http://169.254.169.254/computeMetadata/v1/instance/attributes/load-balancing-weight)"
  echo "Header set X-Load-Balancing-Endpoint-Weight \"$lb_weight\"" | \
  tee /etc/apache2/conf-enabled/headers.conf
  systemctl restart apache2'
gcloud compute instances create instance-900 \
  --zone=us-central1-a \
  --tags=network-lb-tag \
  --image-family=debian-10 \
  --image-project=debian-cloud \
  --subnet=
SUBNET_NAME
\
  --metadata=load-balancing-weight=900,startup-script='#! /bin/bash
    apt-get update
    apt-get install apache2 -y
    ln -sr /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load
    vm_hostname="$(curl -H "Metadata-Flavor:Google" \
    http://169.254.169.254/computeMetadata/v1/instance/name)"
    echo "Page served from: $vm_hostname" | \
    tee /var/www/html/index.html
    lb_weight="$(curl -H "Metadata-Flavor:Google" \
    http://169.254.169.254/computeMetadata/v1/instance/attributes/load-balancing-weight)"
    echo "Header set X-Load-Balancing-Endpoint-Weight \"$lb_weight\"" | \
    tee /etc/apache2/conf-enabled/headers.conf
    systemctl restart apache2'

Create an instance group

In this tutorial, you provide instructions to create an unmanaged instance group containing all three VM instances(instance-0, instance-100, and instance-900).

gcloud compute instance-groups unmanaged create
INSTANCE_GROUP --zone=us-central1-a
gcloud compute instance-groups unmanaged add-instances INSTANCE_GROUP \
  --zone=us-central1-a \
  --instances=instance-0,instance-100,instance-900

Replace INSTANCE_GROUP with the name of the instance group to create.

Create an HTTP health check

In this tutorial, you provide instructions to create an HTTP health check to read the HTTP response containing the backend VM's weight."

gcloud compute health-checks create http HTTP_HEALTH_CHECK_NAME \
  --region=us-central1

Replace HTTP_HEALTH_CHECK_NAME with the name of the HTTP health check to create.

Create a backend service

The following example provides instructions to create a regional external backend service configured to use weighted load balancing.

  1. Create a backend service with the HTTP health check and set the locality load balancer policy to WEIGHTED_MAGLEV.
gcloud compute backend-services create BACKEND_SERVICE_NAME \
  --load-balancing-scheme=external \
  --protocol=tcp \
  --region=us-central1 \
  --health-checks=HTTP_HEALTH_CHECK_NAME \
  --health-checks-region=us-central1 \
  --locality-lb-policy=WEIGHTED_MAGLEV
  • Replace BACKEND_SERVICE_NAME with the name of the backend service to create.
  1. Add the instance group to the backend service.
gcloud compute backend-services add-backend BACKEND_SERVICE_NAME \
  --instance-group=INSTANCE_GROUP \
  --instance-group-zone=us-central1-a \
  --region=us-central1
  1. Reserve a regional external IP address for the load balancer.
gcloud compute addresses create ADDRESS_NAME \
 --region us-central1

Replace ADDRESS_NAME with the name of the IP address to create. Use the compute addresses describe command to view the result. Note the reserved static external IP address (‘IP_ADDRESS').

gcloud compute addresses describe ADDRESS_NAME
  1. Create a forwarding rule using the reserved regional external IP address ‘IP_ADDRESS'. Connect the forwarding rule to the backend service.
gcloud compute forwarding-rules create FORWARDING_RULE \
  --region=us-central1 \
  --ports=80 \
  --address=IP_ADDRESS \
  --backend-service=BACKEND_SERVICE_NAME
  • Replace the following: FORWARDING_RULE: the name of the forwarding rule to create. IP_ADDRESS: the IP address to assign to the instance. Use the reserved static external IP address, not the address name.

Verify backend weights using backend service API

Verify that the backend weights are properly reported to the HTTP health check.

gcloud compute backend-services get-health HTTP_HEALTH_CHECK_NAME \
  --region=us-central1

The output should be like the following:

backend: https://www.googleapis.com/compute/projects/project-name/{project}/zones/us-central1-a/instanceGroups/{instance-group-name}
status:
  healthStatus:
  - forwardingRule: https://www.googleapis.com/compute/projects/{project}/regions/us-central1/forwardingRules/{firewall-rule-name}
    forwardingRuleIp: 34.135.46.66
    healthState: HEALTHY
    instance: https://www.googleapis.com/compute/projects/{project}/zones/us-central1-a/instances/instance-0
    ipAddress: 10.10.0.5
    port: 80
    weight: '0'
  - forwardingRule: https://www.googleapis.com/compute/projects/{project}/regions/us-central1/forwardingRules/{firewall-rule-name}
    forwardingRuleIp: 34.135.46.66
    healthState: HEALTHY
    instance: https://www.googleapis.com/compute/projects/{project}/zones/us-central1-a/instances/instance-100
    ipAddress: 10.10.0.6
    port: 80
    weight: '100'
  - forwardingRule: https://www.googleapis.com/compute/projects/{project}/regions/us-central1/forwardingRules/{firewall-rule-name}
    forwardingRuleIp: 34.135.46.66
    healthState: HEALTHY
    instance: https://www.googleapis.com/compute/projects/{project}/zones/us-central1-a/instances/instance-900
    ipAddress: 10.10.0.7
    port: 80
    weight: '900'
  kind: compute#backendServiceGroupHealth