Migrating from GCP subnets from INTERNAL_HTTPS_LOAD_BALANCER to REGIONAL_MANAGED_PROXY

First, add the new subnet with purpose = “REGIONAL_MANAGED_PROXY” and role = “BACKUP”. A typical Terraform input might look like this:

{
    name        = "old-proxy-only-subnet"
    description = null
    ip_range    = "100.64.1.0/24"
    region      = "us-central1"
    purpose     = "INTERNAL_HTTPS_LOAD_BALANCER"
    role        = "ACTIVE"
},
{
    name        = "new-proxy-only-subnet"
    description = null
    region      = "us-central1"
    ip_range    = "100.64.2.0/24"
    purpose     = "REGIONAL_MANAGED_PROXY"
    role        = "BACKUP"
},

After the subnet has been created, switch the role to “ACTIVE”

{
    name        = "new-proxy-only-subnet"
    purpose     = "REGIONAL_MANAGED_PROXY"
    role        = "ACTIVE"
},

Google will automatically change the old subnet’s to role = “BACKUP”. It will also change state from “READY” to “DRAINING”. To match the role change, update input:

{
    name      = "old-proxy-only-subnet"
    purpose   = "INTERNAL_HTTPS_LOAD_BALANCER"
    role      = "BACKUP"
},

After 5 minutes, the draining should finish. You may either leave the old subnet as-is, or simply delete it.


To replace a REGIONAL_MANGED_PROXY subnet, follow this process:

  1. Add the new subnet with a unique name and ip range with role = “BACKUP”
  2. Change the new subnet’s role from “BACKUP” to “ACTIVE”. Google will change the old subnet’s role to “BACKUP”
  3. The old subnet can be be deleted after waiting at least 5 minutes for existing sessions to drain

Remember of course to update firewall rules if the IP address has changed! Google does not automatically create firewall rules for you.

Google Cloud Internal HTTP(S) Load Balancers now have global access support

Previously, the envoy-based Internal HTTP(S) load balancers could only be accessed within the same region. For orgs that leverage multiple regions and perform cross-region traffic, this limitation was a real pain point, and not a problem for AWS ALBs. So, I’m glad to see it’s now offered:

Oddly, the radio button only shows up during the ILB creation. To modify an existing one, use this gcloud command:

gcloud compute forwarding-rules update NAME --allow-global-access

Or, in Terraform:

resource "google_compute_forwarding_rule" "default" {
  allow_global_access   = true
}

It’s also important to be aware that Global access on the HTTP(S) ILB must be enabled if accessing from another load balancer via PSC. If not, you’ll get this error message:

 Error 400: Invalid value for field 'resource.backends[0]': '{  "resourceGroup": "projects/myproject/regions/us-west1/networkEndpointGroups/psc-backend", ...'. Global L7 Private Service Connect consumers require the Private Service Connect producer load b
alancer to have AllowGlobalAccess enabled., invalid

Using the Built-in GeoIP Functionality of GCP HTTP/HTTPS Load Balancers

GCP HTTP/HTTPS Load Balancers offer great performance, and today I learned of a cool almost hidden feature: the ability to stamp custom headers with client GeoIP info. Here’s a Terraform config snippet:

resource "google_compute_backend_service" "MY_BACKEND_SERVICE" {
  provider                 = google-beta
  name                     = "my-backend-service"
  health_checks            = [ google_compute_health_check.MY_HEALTHCHECK.id ]
  backed {
    group                  = google_compute_instance_group.MY_INSTANCE_GROUP.self_link
    balancing_mode         = "UTILIZATION"
    max_utilization        = 1.0
  }
  custom_request_headers   = [ "X-Client-Geo-Location: {client_region},{client_city}" ]
  custom_response_headers  = [ "X-Cache-Hit: {cdn_cache_status}" ]
}

This will cause the Backend Service to stamp all HTTP requests with a custom header called “X-Client-Geo-Location” with the country abbreviation and city. It can then be parsed on the server to get this information for the client without having to rely on messy X-Forwarded-For parsing and GeoIP lookups.

Here’s a Python example that redirects the user to UK or Australia localized websites:

#!/usr/bin/env python3

import os

try:
   client_location = os.environ.get('HTTP_X_CLIENT_GEO_LOCATION', None)
   if client_location:
       [country,city] = client_location.split(',')
   websites = { 'UK': "www.foo.co.uk", 'AU': "www.foo.au" }
   if country in websites:
       local_website = websites[country]
   else:
       local_website = "www.foo.com"
   print("Status: 301\nLocation: https://{}\n".format(local_website))

except Exception as e:
   print("Status: 500\nContent-Type: text/plain\n\n{}".format(e))

GCP Load Balancers – Two Gotchas

Healthchecks are failing, even though the service is running and open via fw rules

Healthchecks actually originate from GCP directly, rather than the load balancer instance itself.  So these networks must be whitelisted in the firewall rules:

  • 35.191.0.0/16
  • 130.211.0.0/22

The LB works in the same region, but does not respond from different regions

By default, load balancers operate in regional-only mode.  To switch to global, edit the frontend properties and look for this radio button:

ilb_global_access