Set up an external passthrough Network Load Balancer with a target pool

Note: This guide provides instructions for creating a target pool-basedexternal passthrough Network Load Balancer. We recommend using a backend service-based external passthrough Network Load Balancerinstead. For more information, seeBackend service-based external passthrough Network Load Balanceroverview.

The example assumes that you have multiple web servers running onCompute Engine instances, and balances new TCP connections among them. Thisexample uses a legacy HTTP health check so that new connections are only sent tohealthy backend VMs.

Before you start, readExternal passthrough Network Load Balanceroverview for conceptual information aboutexternal passthrough Network Load Balancers.

Before you begin

Install the Google Cloud CLI. For a complete overview of the tool,see thegcloud Tool Guide. You can find commands related toload balancing in thegcloud computecommand group.

You can also get detailed help for anygcloud command by using the--helpflag:

gcloud compute http-health-checks create --help

If you haven't run the Google Cloud CLI previously, first rungcloud init to authenticate.

In addition, you must create a static external IP address for the load balancer.If you are using an image provided by Compute Engine, your virtual machine (VM)instances are automatically configured to handle this IP address. If you are usingany other image, you will have to configure this address as an alias on eth0 oras a loopback on each instance.

This guide assumes that you are familiar withbash.

Configuring Compute Engine VM instances

For this load balancing scenario, you will create three Compute EngineVM instances and install Apache on them. You will add a firewall rule that allowsHTTP traffic to reach the instances.

Instances that participate as backend VMs for external passthrough Network Load Balancersmust be running the appropriateLinux Guest Environment,Windows Guest Environment,or other processes that provide equivalent functionality.

Setting up the backend instances

Console

  1. In the Google Cloud console, go to theVM instances page.

    Go to VM instances

  2. ClickCreate instance.

  3. SetName towww1.

  4. Set theRegion tous-central1.

  5. Set theZone tous-central1-b.

  6. UnderBoot disk, the default OS image ofDebian GNU/Linux 12(bookworm) is already selected.

  7. ClickAdvanced options.

  8. ClickNetworking and configure the following field:

    1. ForNetwork tags, enternetwork-lb-tag.
  9. ClickManagement. Enter the following script into theStartup script field.

     #! /bin/bash sudo apt-get update sudo apt-get install apache2 -y sudo service apache2 restart echo '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html

    1. ClickCreate.
  10. Create an instance namedwww2 with the same settings, except withthe following script inserted into theAutomation,Startup scriptfield.

      #! /bin/bash  sudo apt-get update  sudo apt-get install apache2 -y  sudo service apache2 restart  echo '<!doctype html><html><body><h1>www2</h1></body></html>' | tee /var/www/html/index.html

  11. Create an instance namedwww3 with the same settings, except withthe following script inserted into theAutomation,Startup scriptfield.

        #! /bin/bash    sudo apt-get update    sudo apt-get install apache2 -y    sudo service apache2 restart    echo '<!doctype html><html><body><h1>www3</h1></body></html>' | tee /var/www/html/index.html

gcloud

The commands below are all run on your local system and assume abash commandprompt.

To see OS image names, attributes, and status use thegcloud compute images listcommand.

  1. Create three new virtual machines in a given zone and give themall the same tag. This example sets the zone to us-central1-b. Setting thetags field lets you reference these instances all at once, such aswith a firewall rule. These commands also install Apache on each instanceand give each instance a unique home page.

    gcloud compute instances create www1 \  --image-family debian-12 \  --image-project debian-cloud \  --zone us-central1-b \  --tags network-lb-tag \  --metadata startup-script="#! /bin/bash    sudo apt-get update    sudo apt-get install apache2 -y    sudo service apache2 restart    echo '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html"
    gcloud compute instances create www2 \  --image-family debian-12 \  --image-project debian-cloud \  --zone us-central1-b \  --tags network-lb-tag \  --metadata startup-script="#! /bin/bash    sudo apt-get update    sudo apt-get install apache2 -y    sudo service apache2 restart    echo '<!doctype html><html><body><h1>www2</h1></body></html>' | tee /var/www/html/index.html"
    gcloud compute instances create www3 \  --image-family debian-12 \  --image-project debian-cloud \  --zone us-central1-b \  --tags network-lb-tag \  --metadata startup-script="#! /bin/bash    sudo apt-get update    sudo apt-get install apache2 -y    sudo service apache2 restart    echo '<!doctype html><html><body><h1>www3</h1></body></html>' | tee /var/www/html/index.html"

api

Create instancewww1 in zoneus-central1-b with theinstances.insertmethod

POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances{  "canIpForward": false,  "deletionProtection": false,  "disks": [    {      "type": "PERSISTENT",      "boot": true,      "mode": "READ_WRITE",      "autoDelete": true,      "deviceName": "www1",      "initializeParams": {        "sourceImage": "projects/debian-cloud/global/images/debian-12-buster-v20220719",        "diskType": "projects/[PROJECT_ID]/zones/us-central1-b/diskTypes/pd-standard",        "diskSizeGb": "10"      }    }  ],  "machineType": "projects/[PROJECT_ID]/zones/us-central1-b/machineTypes/e2-standard-2",  "metadata": {    "items": [      {        "key": "startup-script",        "value": "sudo apt-get update\nsudo apt-get install apache2 -y\nsudo a2ensite default-ssl\nsudo a2enmod ssl\nsudo service apache2 restart\necho '<!doctype html><html><body><h1>www1</h1></body></html>' | tee /var/www/html/index.html"      }    ]  },  "name": "www1",  "networkInterfaces": [    {      "network": "projects/[PROJECT_ID]/global/networks/default",      "subnetwork": "projects/[PROJECT_ID]/regions/us-central1/subnetworks/default"    }  ],  "tags": {    "items": [      "network-lb-tag"    ]  }}

Create instances namedwww2 andwww3 with the same settings, exceptreplacewww1 in thedeviceName,value, andname fields.

Creating a firewall rule to allow external traffic to these VM instances

Console

  1. In the Google Cloud console, go to theFirewall policies page.

    Go to Firewall policies

  2. ClickCreate firewall rule.

  3. Enter aName ofwww-firewall-network-lb.

  4. Select theNetwork that the firewall rule applies to (Default).

  5. UnderTargets, selectSpecified target tags.

  6. In theTarget tags field, enternetwork-lb-tag.

  7. SetSource filter toIPv4 ranges.

  8. Set theSource IPv4 ranges to0.0.0.0/0, which allows traffic from anysource.

  9. UnderSpecified protocols and ports, select theTCP checkboxand enter80.

  10. ClickCreate. It might take a moment for the Console to display thenew firewall rule, or you might have to clickRefresh to seethe rule.

gcloud

gcloud compute firewall-rules create www-firewall-network-lb \    --target-tags network-lb-tag --allow tcp:80

api

Create a firewall rule that allows all traffic within the subnet with thefirewalls.insert ** method**

POST https://compute.googleapis.com/compute/projects/[PROJECT_ID]/global/firewalls{  "name": "www-firewall-network-lb",  "direction": "INGRESS",  "priority": 1000,  "targetTags": [    "network-lb-tag"  ],  "allowed": [    {      "IPProtocol": "tcp",      "ports": [        "80"      ]    }  ],  "sourceRanges": [    "0.0.0.0/0"  ]}

Getting the external IP addresses of your instances and verifying that they are running

Console

  1. In the Google Cloud console, go to theVM instances page.

    Go to VM instances

  2. View the addresses for your instances in theExternal IP column.

  3. Verify that your instances are running by looking for a green checkmarkto the left of the instance name. If you don't see a green checkmark,refer to theGeneral Troubleshooting page for instances.

gcloud

  1. List your instances to get their IP addresses from theEXTERNAL_IPcolumn.

    gcloud compute instances list
  2. Verify that each instance is running.

    At the command line, runcurl using the external IP address of each instanceto confirm that all of the instances respond.

    curl http://[IP_ADDRESS]

api

Get information about instancewww1 with theinstances.getmethod

Make sure thestatus field saysRUNNING, and look for the external IPaddress in thenatIP field.

GET https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances/www1{ "kind": "compute#instance", "id": "6734015273571474749", "creationTimestamp": "2018-11-09T11:45:23.487-08:00", "name": "www1", "description": "", "tags": {  "items": [   "network-lb-tag"  ],  "fingerprint": "9GVlO4gPawg=" }, "machineType": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/machineTypes/e2-standard-2", "status": "RUNNING", "zone": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b", "canIpForward": false, "networkInterfaces": [  {   "kind": "compute#networkInterface",   "network": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/networks/default",   "subnetwork": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/subnetworks/default",   "networkIP": "10.128.0.2",   "name": "nic0",   "accessConfigs": [    {     "kind": "compute#accessConfig",     "type": "ONE_TO_ONE_NAT",     "name": "External NAT",     "natIP": "35.192.37.233",     "networkTier": "PREMIUM"    }   ],   "fingerprint": "lxD5f5ua_sw="  } ], "disks": [  {   "kind": "compute#attachedDisk",   "type": "PERSISTENT",   "mode": "READ_WRITE",   "source": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/disks/www1",   "deviceName": "www1",   "index": 0,   "boot": true,   "autoDelete": true,   "licenses": [    "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-12-buster"   ],   "interface": "SCSI",   "guestOsFeatures": [    {     "type": "VIRTIO_SCSI_MULTIQUEUE"    }   ]  } ], "metadata": {  "kind": "compute#metadata",  "fingerprint": "IyHRmHoJx6E=",  "items": [   {    "key": "startup-script",    "value": "#! /bin/bash\n sudo apt-get update\n sudo apt-get install apache2 -y\n sudo service apache2 restart\n echo '\u003c!doctype html\u003e\u003chtml\u003e\u003cbody\u003e\u003ch1\u003ewww1\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e' | tee /var/www/html/index.html"   }  ] }, "serviceAccounts": [  {   "email": "674259759219-compute@developer.gserviceaccount.com",   "scopes": [    "https://www.googleapis.com/auth/devstorage.read_only",    "https://www.googleapis.com/auth/logging.write",    "https://www.googleapis.com/auth/monitoring.write",    "https://www.googleapis.com/auth/servicecontrol",    "https://www.googleapis.com/auth/service.management.readonly",    "https://www.googleapis.com/auth/trace.append"   ]  } ], "selfLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/instances/www1", "scheduling": {  "onHostMaintenance": "MIGRATE",  "automaticRestart": true,  "preemptible": false }, "cpuPlatform": "Intel Haswell", "labelFingerprint": "42WmSpB8rSM=", "startRestricted": false, "deletionProtection": false}

Repeat this API call forwww2 andwww3.

Configuring the load balancing service

Next, set up the load balancing service.

When you configure the load balancing service, your virtual machine instanceswill receive packets that are destined for the static external IP address youconfigure. If you are using animage provided by Compute Engine,your instances are automatically configured to handle this IP address. Ifyou are using any other image, you will have to configure this address asan alias on eth0 or as a loopback on each instance.

Console

You can't use the Google Cloud console to create target pool-basedexternal passthrough Network Load Balancers. Instead, use either gcloud or the REST API.

gcloud

  1. Create astatic external IP address for your load balancer

    gcloud compute addresses create network-lb-ip-1 \    --region us-central1
  2. Add a legacy HTTP health check resourceTarget pool-based external passthrough Network Load Balancers can only uselegacy healthchecks.

    This example uses the default settings for the health check mechanism,but you can also customize the health check on your own.

    gcloud compute http-health-checks create basic-check
  3. Add a target pool

    Add a target pool in the same region as your virtual machineinstances. Use the health check created in the prior stepfor this target pool.

    gcloud compute target-pools create www-pool \    --region us-central1 --http-health-check basic-check
  4. Add your instances to the target pool

    gcloud compute target-pools add-instances www-pool \    --instances www1,www2,www3 \    --instances-zone us-central1-b

    Instances within a target pool must belong to the same region but can bespread out across different zones in the same region. For example, you canhave instances in zoneus-central1-f and instances in zoneus-central1-bin one target pool because they are in the same region,us-central1.

  5. Add a forwarding rule

    Add a forwarding rule serving on behalf of an external IP address and portrange that points to your target pool. For the--address field,use either the numeric IP address or its fully qualified name.

    gcloud compute forwarding-rules create www-rule \    --region us-central1 \    --ports 80 \    --address network-lb-ip-1 \    --target-pool www-pool

api

  1. Create astatic external IP address for your load balancer

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID/regions/us-central1/addresses{  "name": "network-lb-ip-1"}
  2. Add alegacy HTTP health checkTarget pool-based external passthrough Network Load Balancers can only uselegacy healthchecks.

    This example uses the default settings for the health check mechanism, butyou can also customize this on your own.

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/httpHealthChecks{  "name": "basic-check"}
  3. Add atarget pool

    Add a target pool in the same region as your virtual machine instances.Use the health check created in the prior step for this target pool.

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools{  "name": "www-pool",  "healthChecks": [    "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/httpHealthChecks/basic-check"  ]}
  4. Add yourinstances to the target pool

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-pool/addInstance{  "instances": [    {      "instance": "projects/[PROJECT_ID]/zones/us-central1-b/instances/www1"    }  ]}

    Repeat this API call for instanceswww2 andwww3.

    Instances within a target pool must belong to the same region but can bespread out across different zones in the same region. For example, you canhave instances in zoneus-central1-f and instances in zoneus-central1-bin one target pool because they are in the same region,us-central1.

  5. Add aforwarding rule

    POST https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules{  "name": "www-rule",  "portRange": "80",  "loadBalancingScheme": "EXTERNAL",  "target": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-network-lb"}

Sending traffic to your instances

Now that the load balancing service is configured, you can start sendingtraffic to the forwarding rule and watch the traffic be dispersed to differentinstances.

Looking up the forwarding rule's external IP address

Console

  1. Go to theForwarding Rules tab on theAdvanced load balancing pagein the Google Cloud console.
    Go to the Forwarding Rules tab
  2. Locatewww-rule, the forwarding rule used by the load balancer.
  3. In theIP Address column forwww-rule, note the external IP addresslisted.

gcloud

Enter the following command to view the external IP address of thewww-ruleforwarding rule used by the load balancer.

gcloud compute forwarding-rules describe www-rule --region us-central1

api

View the external IP address of thewww-rule forwarding rule with theforwardingRules.getmethod

In the output, look for theIPAddress field.

GET https://compute.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules/www-rule{  "kind": "compute#forwardingRule",  "id": "5133886346582800002",  "creationTimestamp": "2018-11-09T14:21:33.574-08:00",  "name": "www-rule",  "description": "",  "region": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1",  "IPAddress": "35.232.228.9",  "IPProtocol": "TCP",  "portRange": "80-80",  "target": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/targetPools/www-network-lb",  "selfLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/regions/us-central1/forwardingRules/www-rule",  "loadBalancingScheme": "EXTERNAL",  "networkTier": "PREMIUM"}

ICMP not supported for backend instances

External passthrough Network Load Balancers don't deliver ICMP packets to backend instances. Ifyou send an ICMP packet, for example withping ortraceroute, the replydoesn't come from the load balancer's backend instances.

Google Cloud infrastructure might send an ICMP reply, even if you havefirewall rules that prohibit ICMP traffic on the load balancer's backendinstances. This behavior can't be changed.

Using thecurl command to access the external IP address

The response from thecurl command alternates randomly among the three instances.If your response is initially unsuccessful, you might need to wait approximately30 seconds for the configuration to be fully loaded and for your instances to bemarked healthy before trying again:

$while true; do curl -m1IP_ADDRESS; done

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.