Forked from mikesparr/gcp-global-lb-multi-region-cr-ce.sh
Created
August 26, 2024 11:02
-
-
Save mwiewior/ea95d5d4c97400c6abc1a1040311121a to your computer and use it in GitHub Desktop.
Demonstrating how you can deploy Cloud Run (serverless) or Compute Engine instance groups across regions and balance with global load balancer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
##################################################################### | |
# REFERENCES | |
# - https://cloud.google.com/run/docs/multiple-regions | |
# - https://cloud.google.com/compute/docs/instance-groups/distributing-instances-with-regional-instance-groups | |
# - https://cloud.google.com/load-balancing/docs/https/setup-global-ext-https-compute | |
# - https://cloud.google.com/load-balancing/docs/backend-service#named_ports | |
##################################################################### | |
export PROJECT_ID=$(gcloud config get-value project) | |
export PROJECT_USER=$(gcloud config get-value core/account) # set current user | |
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)") | |
export IDNS=${PROJECT_ID}.svc.id.goog # workflow identity domain | |
export GCP_REGION="us-central1" # CHANGEME (OPT) | |
export GCP_ZONE="us-central1-a" # CHANGEME (OPT) | |
export NETWORK_NAME="default" | |
# enable apis | |
gcloud services enable compute.googleapis.com \ | |
storage.googleapis.com \ | |
cloudbuild.googleapis.com \ | |
run.googleapis.com \ | |
artifactregistry.googleapis.com | |
# configure gcloud sdk | |
gcloud config set compute/region $GCP_REGION | |
gcloud config set compute/zone $GCP_ZONE | |
########################################################## | |
# Demo App Initialization | |
########################################################## | |
# declare demo app name | |
export APP_NAME="my-app" | |
export APP_REGION_1="us-central1" | |
export APP_REGION_2="australia-southeast1" | |
export APP_IMAGE_URL="gcr.io/google-samples/zone-printer:0.2" | |
########################################################## | |
# Load Balancing | |
########################################################## | |
export DOMAIN="my-app.msparr.com" # CHANGE ME TO DESIRED DOMAIN | |
export EXT_IP_NAME="global-ip" | |
export BACKEND_NAME="$APP_NAME-backend" | |
export SERVERLESS_NEG_NAME_1="$APP_NAME-neg-us-2" | |
export SERVERLESS_NEG_NAME_2="$APP_NAME-neg-aus-2" | |
export HTTP_KEEPALIVE_TIMEOUT_SEC="610" # default | |
# create global public IP | |
gcloud compute addresses create --global $EXT_IP_NAME | |
export EXT_IP=$(gcloud compute addresses describe $EXT_IP_NAME --global --format="value(address)") | |
echo "** remember to update DNS for $DOMAIN -> $EXT_IP **" | |
# create backend service | |
gcloud compute backend-services create $BACKEND_NAME \ | |
--global | |
# create URL map | |
gcloud compute url-maps create $APP_NAME-url-map \ | |
--default-service=$BACKEND_NAME | |
# create managed SSL cert | |
gcloud beta compute ssl-certificates create $APP_NAME-cert \ | |
--domains $DOMAIN | |
# create target HTTPS proxy | |
gcloud compute target-https-proxies create $APP_NAME-https-proxy \ | |
--ssl-certificates=$APP_NAME-cert \ | |
--url-map=$APP_NAME-url-map | |
# create forwarding rule using static IP (classic LB, use EXTERNAL_MANAGED for global ALB) | |
gcloud compute forwarding-rules create $APP_NAME-fwd-rule \ | |
--load-balancing-scheme=EXTERNAL \ | |
--target-https-proxy=$APP_NAME-https-proxy \ | |
--global \ | |
--ports=443 \ | |
--address=$EXT_IP_NAME | |
# create target HTTP proxy | |
gcloud compute target-http-proxies create $APP_NAME-http-proxy \ | |
--url-map=$APP_NAME-url-map | |
# create forwarding rule using static IP (classic LB, use EXTERNAL_MANAGED for global ALB) | |
gcloud compute forwarding-rules create $APP_NAME-fwd-rule-http \ | |
--load-balancing-scheme=EXTERNAL \ | |
--target-http-proxy=$APP_NAME-http-proxy \ | |
--global \ | |
--ports=80 \ | |
--address=$EXT_IP_NAME | |
########################################################## | |
# Cloud Run Serverless Runtime | |
########################################################## | |
export SERVERLESS_NEG_NAME="$APP_NAME-neg" | |
export SERVERLESS_BACKEND_NAME="$APP_NAME-run-backend" | |
# deploy app to 2 regions | |
gcloud run deploy $APP_NAME \ | |
--allow-unauthenticated \ | |
--ingress=internal-and-cloud-load-balancing \ | |
--image=$APP_IMAGE_URL \ | |
--region=$APP_REGION_1 | |
gcloud run deploy $APP_NAME \ | |
--allow-unauthenticated \ | |
--ingress=internal-and-cloud-load-balancing \ | |
--image=$APP_IMAGE_URL \ | |
--region=$APP_REGION_2 | |
# create serverless network endpoint groups for each region | |
gcloud compute network-endpoint-groups create $SERVERLESS_NEG_NAME \ | |
--network-endpoint-type=serverless \ | |
--cloud-run-service=$APP_NAME \ | |
--region=$APP_REGION_1 | |
gcloud compute network-endpoint-groups create $SERVERLESS_NEG_NAME \ | |
--network-endpoint-type=serverless \ | |
--cloud-run-service=$APP_NAME \ | |
--region=$APP_REGION_2 | |
# add custom backend for Cloud Run apps (assuming legacy) | |
gcloud compute backend-services create $SERVERLESS_BACKEND_NAME \ | |
--global | |
# add serverless negs to backend for each region | |
gcloud compute backend-services add-backend $SERVERLESS_BACKEND_NAME \ | |
--global \ | |
--network-endpoint-group=$SERVERLESS_NEG_NAME \ | |
--network-endpoint-group-region=$APP_REGION_1 | |
gcloud compute backend-services add-backend $SERVERLESS_BACKEND_NAME \ | |
--global \ | |
--network-endpoint-group=$SERVERLESS_NEG_NAME \ | |
--network-endpoint-group-region=$APP_REGION_2 | |
# update existing load balancer URL map to point to new backend | |
gcloud compute url-maps set-default-service $APP_NAME-url-map \ | |
--default-service=$SERVERLESS_BACKEND_NAME \ | |
--global | |
# test from different regions and confirm backend switches | |
########################################################## | |
# (OPTIONAL ALTERNATIVE) Compute Engine Runtime | |
########################################################## | |
export INSTANCE_TEMPLATE_NAME="$APP_NAME-template" | |
export INSTANCE_GROUP_NAME="$APP_NAME-rmig" | |
export MIG_BACKEND_NAME="$APP_NAME-rmig-backend" | |
export HEALTH_CHECK_NAME="http-basic-check" | |
# create instance template that runs container image | |
gcloud compute instance-templates create-with-container $INSTANCE_TEMPLATE_NAME \ | |
--container-image $APP_IMAGE_URL \ | |
--tags "$APP_NAME,allow-health-check,allow-ssh" | |
# create regional migs for each region | |
gcloud compute instance-groups managed create $INSTANCE_GROUP_NAME \ | |
--base-instance-name $INSTANCE_GROUP_NAME \ | |
--size 1 \ | |
--template $INSTANCE_TEMPLATE_NAME \ | |
--region $APP_REGION_1 | |
gcloud compute instance-groups managed create $INSTANCE_GROUP_NAME \ | |
--base-instance-name $INSTANCE_GROUP_NAME \ | |
--size 1 \ | |
--template $INSTANCE_TEMPLATE_NAME \ | |
--region $APP_REGION_2 | |
# add named port (internal) | |
gcloud compute instance-groups set-named-ports $INSTANCE_GROUP_NAME \ | |
--named-ports http:80,$APP_NAME:8080 \ | |
--region $APP_REGION_1 | |
gcloud compute instance-groups set-named-ports $INSTANCE_GROUP_NAME \ | |
--named-ports http:80,$APP_NAME:8080 \ | |
--region $APP_REGION_2 | |
# enable firewall rules | |
gcloud compute firewall-rules create fw-allow-health-check \ | |
--network=default \ | |
--action=allow \ | |
--direction=ingress \ | |
--source-ranges=130.211.0.0/22,35.191.0.0/16 \ | |
--target-tags=allow-health-check \ | |
--rules=tcp | |
gcloud compute firewall-rules create fw-allow-ssh \ | |
--network=default \ | |
--action=allow \ | |
--direction=ingress \ | |
--source-ranges=0.0.0.0/0 \ | |
--target-tags=allow-ssh \ | |
--rules=tcp:22 | |
# create health check | |
gcloud compute health-checks create http $HEALTH_CHECK_NAME \ | |
--use-serving-port \ | |
--global | |
# create custom backend for MIGs | |
gcloud compute backend-services create $MIG_BACKEND_NAME \ | |
--load-balancing-scheme=EXTERNAL \ | |
--protocol=HTTP \ | |
--port-name=$APP_NAME \ | |
--health-checks=$HEALTH_CHECK_NAME \ | |
--global | |
# add instance groups to MIG backend for each region | |
gcloud compute backend-services add-backend $MIG_BACKEND_NAME \ | |
--global \ | |
--instance-group=$INSTANCE_GROUP_NAME \ | |
--instance-group-region=$APP_REGION_1 | |
gcloud compute backend-services add-backend $MIG_BACKEND_NAME \ | |
--global \ | |
--instance-group=$INSTANCE_GROUP_NAME \ | |
--instance-group-region=$APP_REGION_2 | |
# update existing load balancer URL map to point to MIG backend | |
gcloud compute url-maps set-default-service $APP_NAME-url-map \ | |
--default-service=$MIG_BACKEND_NAME \ | |
--global | |
# test from different regions and confirm backend switches |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment