In this example we assume we are working on a suite of backend servives as part of a larger travel booking app. More precisely we assume we have 2 apps (REST APIs) deployed on Cloud Run:

  • Pricing deployed in both europe-west1 and us-east1 regions
  • Booking deployed in europe-west1 region

The reason we are deploying the pricing api in 2 regions is for the web-site to respond quicker when users are inquiring/comparing different options by having the queries running closer to where they are. The final booking stage is less sensitive to speed so we only deploy it in one place.

The rest of this post assumes our apps are already deployed as Cloud Run instances in the relevant regions and discusses the creation of the different components of the following Load Balancer architectute.

In the following graph the arrows are not oriented according to the traffic but according to the depedencies when building each node of the graph. For example the arrows from the NEGs to the Backend Services mean that a NEG is used as an input to a Backend Service.

graph TD %% SSL Certificate first SSLCert[SSL Certificate] --> CertMap[Certificate Map] %% Cloud Run Services BookingApp_EU[Booking App eu-east1] --> BookingNEG_EU[Booking NEG eu-east1] BookingApp_US[Booking App us-west1] --> BookingNEG_US[Booking NEG us-west1] PricingApp_EU[Pricing App eu-west1] --> PricingNEG_EU[Pricing NEG eu-west1] %% NEGs to Backend Services BookingNEG_EU --> BookingBackend[Booking Backend Service] BookingNEG_US --> BookingBackend PricingNEG_EU --> PricingBackend[Pricing Backend Service] %% Backend Services to URL Map BookingBackend --> URLMap[URL Map] PricingBackend --> URLMap %% URL Map to Target Proxies URLMap --> TargetHTTPProxy[Target HTTP Proxy] URLMap --> TargetHTTPSProxy[Target HTTPS Proxy] %% Certificate Map only to HTTPS Proxy CertMap --> TargetHTTPSProxy %% Target Proxies to Forwarding Rules TargetHTTPProxy --> HTTPForwardingRule[HTTP Forwarding Rule] TargetHTTPSProxy --> HTTPSForwardingRule[HTTPS Forwarding Rule] %% Forwarding Rules to Load Balancer HTTPForwardingRule --> LB[Global Load Balancer] HTTPSForwardingRule --> LB %% Custom styling with matching border colors (effectively no visible borders) classDef cloudRun fill:#4285F4,stroke:#4285F4,stroke-width:1px,color:white classDef networkEndpoint fill:#F4B400,stroke:#F4B400,stroke-width:1px,color:white classDef backendService fill:#0F9D58,stroke:#0F9D58,stroke-width:1px,color:white classDef urlMap fill:#DB4437,stroke:#DB4437,stroke-width:1px,color:white classDef securityHTTPS fill:#AB47BC,stroke:#AB47BC,stroke-width:1px,color:white classDef securityHTTP fill:#CE93D8,stroke:#CE93D8,stroke-width:1px,color:white classDef loadBalancer fill:#5C6BC0,stroke:#5C6BC0,stroke-width:1px,color:white class BookingApp_US,BookingApp_EU,PricingApp_US,PricingApp_EU cloudRun class BookingNEG_US,BookingNEG_EU,PricingNEG_US,PricingNEG_EU networkEndpoint class BookingBackend,PricingBackend backendService class URLMap urlMap class SSLCert,CertMap,TargetHTTPSProxy securityHTTPS class TargetHTTPProxy securityHTTP class HTTPForwardingRule,HTTPSForwardingRule,LB loadBalancer

From Cloud Run to URL Map

Setting up the NEGs (regional level)

Booking service

gcloud compute network-endpoint-groups create booking-neg-eu \
    --region=europe-west1 \
    --network-endpoint-type=serverless  \
    --cloud-run-service=booking
gcloud compute network-endpoint-groups create booking-neg-us \
    --region=us-east1 \
    --network-endpoint-type=serverless  \
    --cloud-run-service=booking

Pricing service

gcloud compute network-endpoint-groups create pricing-neg-eu \
    --region=europe-west1 \
    --network-endpoint-type=serverless  \
    --cloud-run-service=pricing

Setting up the Backend Services (global)

Here we only cover the case of the Booking service as the operation is very similar for the Pricing service.

The Backend Services being defined at global level (see --global option) our naming pattern only refers to the service.

First create the Backend Service:

gcloud compute backend-services create booking-be \
    --load-balancing-scheme=EXTERNAL_MANAGED \
    --global

Then add the two 2 regional booking NEGs we created above to the same Backend Service:

gcloud compute backend-services add-backend booking-be \
    --global \
    --network-endpoint-group=booking-neg-eu \
    --network-endpoint-group-region=europe-west1

gcloud compute backend-services add-backend booking-be \
    --global \
    --network-endpoint-group=booking-neg-us \
    --network-endpoint-group-region=us-east1

Setting up the URL Map

(to do)

Creating the Certificate Map

To setup our certificate map we assume here we already purchased a domain name and we already created a ssl certificate.

Create the dns-authorizations

We create dns-authorizations refering to our reserved domain name cf YOUR_DOMAINE.com.

gcloud certificate-manager dns-authorizations create trvl-dns-auth \
    --domain="YOUR_DOMAIN.com"
gcloud certificate-manager dns-authorizations describe trvl-dns-auth
dnsResourceRecord:
  data: SOME_LONG_DATA_CHAIN.authorize.certificatemanager.goog.
  name: _acme-challenge.YOUR_DOMAIN.com.
  type: CNAME
domain: YOUR_DOMAIN.com

We print out a mock output above as we need these values next.

Add dns record-set

We first start a transation on the dns record sets to make it editable:

gcloud dns record-sets transaction start --zone="test-zone10"
Transaction started [transaction.yaml].

The next command requires to use the “data” and “name” outputs from the dns-authorization “describe” command:

gcloud dns record-sets transaction add SOME_LONG_DATA_CHAIN.authorize.certificatemanager.goog. \
    --name="_acme-challenge.YOUR_DOMAIN.com." \
    --ttl="60" \
    --type="CNAME" \
    --zone="test-zone10"

We then execute and close the transation we opened above:

gcloud dns record-sets transaction execute --zone="test-zone10"
Executed transaction [transaction.yaml] for managed-zone [test-zone10].

To create the certificate (allowing for subdomains wildcard)

gcloud certificate-manager certificates create trvl-certificate \
    --domains="*.YOUR_DOMAIN.com,YOUR_DOMAIN.com" \
    --dns-authorizations=trvl-dns-auth
Create request issued for: [trvl-certificate]
Created certificate [trvl-certificate].

To create the certificate map (map from url to ssl)

gcloud certificate-manager maps create trvl-cert-map

Add two entries to the certificate map, one fo the main domain and one for the wildcard subdomain.

gcloud certificate-manager maps entries create trvl-cert-map-entry-a \
    --map="trvl-cert-map" \
    --certificates="trvl-certificate" \
    --hostname="YOUR_DOMAIN.com"

gcloud certificate-manager maps entries create trvl-cert-map-entry-b \
    --map="trvl-cert-map" \
    --certificates="trvl-certificate" \
    --hostname="*.YOUR_DOMAIN.com"

Setting up the HTTP and HTTPS Proxies

The HTTP Proxies are built on top of the url-maps but the HTTPs one also depends on the certificate map.

Note that both the HTTP and HTTPs proxies can be assigned the same name because there are not the same type of resources.

HTTP

gcloud compute target-http-proxies create trvl-proxy \
    --http-keep-alive-timeout-sec=30 \
    --url-map=trvl-url-map

HTTPS

gcloud compute target-https-proxies create trvl-proxy \
    --http-keep-alive-timeout-sec=30 \
    --url-map=trvl-url-map \
    --certificate-map="trvl-cert-map"

Setting up the Forwarding Rules

This depends on the HTTP/HTTPs Proxies and on a fixed IP address.

Note the use scheme=EXTERNAL_MANAGED

HTTP

gcloud compute forwarding-rules create trvl-http-rules \
    --load-balancing-scheme=EXTERNAL_MANAGED \
    --network-tier=PREMIUM \
    --address=trvl-ip-addr \
    --target-http-proxy=trvl-proxy \
    --global \
    --ports=80

HTTPS

gcloud compute forwarding-rules create trvl-https-rules \
    --load-balancing-scheme=EXTERNAL_MANAGED \
    --network-tier=PREMIUM \
    --address=trvl-ip-addr \
    --target-https-proxy=trvl-proxy \
    --global \
    --ports=443