You can now route your users to the nearest Google datacenter to them that has
your Cloud Run application deployed. In this article, I list the commands to
setup a load balancer and deploy an application as “multi-region” with Cloud Run
You can do this on Cloud Console web site as well, but in this blog post, I am providing the CLI version of the story, and share a bash script, as well as a working demo.
Step 0: Identify the Cloud Run regions you want to deploy
regions=(us-central1 asia-east1 europe-west4 australia-southeast1)
Learn how to get Cloud Run regions from the REST API in bash
project="$(gcloud config get-value core/project -q) access_token="$(gcloud auth print-access-token)" curl -sSLfH "Authorization: Bearer $access_token" \ "https://run.googleapis.com/v1/projects/$project/locations?alt=json" |\ jq -r '.locations.locationId'
Step 1: Deploy the app to multiple regions
I wrote an application that prints the flag of country the datacenter is running at. You can use this to try things out.
for region in $regions; do gcloud run deploy zoneprinter --platform=managed --allow-unauthenticated \ --image=gcr.io/ahmetb-public/zoneprinter --region=$region done
Step 2: Understand a load balancer is many components put together.
Take a look at the diagram in is article. You’ll learn that, under the covers, a “Cloud HTTP(S) Balancer” is not a single API object, but rather quite a few API objects associated to each other.
Step 3: Create regional serverless network endpoint groups (NEGs)
for region in $regions; do gcloud alpha compute network-endpoint-groups create \ --region=$region --network-endpoint-type=SERVERLESS \ --cloud-run-service=zoneprinter \ zoneprinter-neg-$region" done
Step 3: Create global backend service
gcloud compute backend-services create --global \ zoneprinter-backend
Step 3: Add regional NEGs to the backend
for region in $regions; do gcloud alpha compute backend-services add-backend zoneprinter-backend \ --network-endpoint-group-region=$region \ --network-endpoint-group=zoneprinter-neg-$region" done
Step 4: Create URL Map for the backend
gcloud compute url-maps create zoneprinter-urlmap \ --default-service=zoneprinter-backend
Step 5: Create a managed SSL certificate
Did you know Google can automatically provision TLS certificates for your domains for free? Decide on a domain name for your app.
gcloud beta compute ssl-certificates create zoneprinter-cert \ --domains=zoneprinter.ahmet.im
Step 6: Create a Target HTTP(S) Proxy
gcloud compute target-https-proxies create zoneprinter-https \ --ssl-certificates=zoneprinter-cert \ --url-map=zoneprinter-urlmap
Step 7: Create global forwarding rule
gcloud compute forwarding-rules create --global zoneprinter-lb \ --target-https-proxy=zoneprinter-https \ --ports=443
Step 8: Find the IP address of the load balancer
gcloud compute forwarding-rules describe --global zoneprinter-lb \ --format='value(IPAddress)')
This is an ephemeral IP (i.e. if you delete and recreate the forwarding rule,
you’ll get a different IP, however you can create a global static IP and associate
it in the previous step with
Step 9: Configure your domain’s DNS records
Take this IP address and update your domain’s (e.g.
zoneprinter.ahmet.im above) DNS records with this IP
Step 10: Now, patiently wait…
Now, (1) Google is reconfiguring its global network, (2) solving a TLS challenge
to get you a managed certificate (3) and your DNS provider is updating your DNS
records. All this can take up to 30 minutes. Wait patiently
until this command shows
gcloud beta compute ssl-certificates describe zoneprinter-cert
If all goes well, you’ll get a globally load-balanced endpoint with Cloud Run. If you’re lazy, check out a demo I deployed. 😉
I wrote a bash
does these steps for you. (You can configure it via
$DOMAIN environment variables.)
This feature enables a ton of new products to be used with Cloud Run, such as Cloud CDN, Cloud Armor (DDoS/WAF) and soon Cloud IAP. Similarly, you can use this to have static IP addresses for your Cloud Run applications.
P.S. If you want to prevent long-term charges to your account, you should
clean up the resources by using the
equivalent of each
create command and by following the steps backwards.