Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Last active August 8, 2023 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikesparr/0a2b53a6d972825158b331bdff7ce83d to your computer and use it in GitHub Desktop.
Save mikesparr/0a2b53a6d972825158b331bdff7ce83d to your computer and use it in GitHub Desktop.
Experiment with GCP application load balancer in front of Cloud Run service testing URL rewrite capabilities
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/run/docs/deploying#command-line
# - https://hub.docker.com/r/ealen/echo-server
# - https://cloud.google.com/load-balancing/docs/https/setup-global-ext-https-serverless
# - https://cloud.google.com/load-balancing/docs/url-map-concepts#wildcards-regx-dynamic-route
# - https://cloud.google.com/load-balancing/docs/url-map-concepts#example_url_map_workflow_with_an
#####################################################################
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 \
containerregistry.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
#################################################################
# Cloud Run Service (sample echoserver app)
#################################################################
export APP_NAME="echo"
export IMAGE_NAME="ealen/echo-server:0.7.1"
gcloud run deploy $APP_NAME \
--image $IMAGE_NAME \
--allow-unauthenticated \
--ingress=internal-and-cloud-load-balancing \
--region=$GCP_REGION
##########################################################
# Load Balancer
##########################################################
export DOMAIN="demo.msparr.com" # CHANGE ME TO DESIRED DOMAIN
export EXT_IP_NAME="external-address"
export BACKEND_SERVICE_NAME="$APP_NAME-service"
export SERVERLESS_NEG_NAME="$APP_NAME-neg"
export HTTP_KEEPALIVE_TIMEOUT_SEC="610" # default
# create static IP
gcloud compute addresses create $EXT_IP_NAME \
--network-tier=PREMIUM \
--ip-version=IPV4 \
--global
export EXT_IP=$(gcloud compute addresses describe $EXT_IP_NAME --global --format="value(address)")
# create serverless NEG
gcloud compute network-endpoint-groups create $SERVERLESS_NEG_NAME \
--region=$GCP_REGION \
--network-endpoint-type=serverless \
--cloud-run-service=$APP_NAME
# create backend service
gcloud compute backend-services create $BACKEND_SERVICE_NAME \
--load-balancing-scheme=EXTERNAL_MANAGED \
--global
# add serverless NEG to backend service
gcloud compute backend-services add-backend $BACKEND_SERVICE_NAME \
--network-endpoint-group=$SERVERLESS_NEG_NAME \
--network-endpoint-group-region=$GCP_REGION \
--global
# create URL map
gcloud compute url-maps create $APP_NAME-url-map \
--default-service $BACKEND_SERVICE_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 \
--http-keep-alive-timeout-sec=$HTTP_KEEPALIVE_TIMEOUT_SEC \
--ssl-certificates=$APP_NAME-cert \
--url-map=$APP_NAME-url-map
gcloud compute forwarding-rules create $APP_NAME-fwd-rule \
--load-balancing-scheme=EXTERNAL_MANAGED \
--target-https-proxy=$APP_NAME-https-proxy \
--global \
--ports=443 \
--address=$EXT_IP_NAME
# verify app is running (wait 10-15 minutes until cert provisions)
curl "https://$DOMAIN" # Unauthorized request
##########################################################
# URL rewrite experimentation
# - TODO (test if can add ?customer_id={customer}) to rewrite URL somehow
##########################################################
export URL_MAP_CONFIG_FILE="url-map.conf"
export DEFAULT_SVC_URL="https://www.googleapis.com/compute/v1/projects/$PROJECT_ID/global/backendServices/$BACKEND_SERVICE_NAME"
cat > $URL_MAP_CONFIG_FILE << EOF
kind: compute#urlMap
name: $APP_NAME-url-map
defaultService: $DEFAULT_SVC_URL
hostRules:
- hosts:
- '*'
pathMatcher: pathmap
pathMatchers:
- defaultService: $DEFAULT_SVC_URL
name: pathmap
routeRules:
- description: EchoService
matchRules:
- pathTemplateMatch: '/echo/{customer=*}/profile'
service: $DEFAULT_SVC_URL
priority: 1
routeAction:
urlRewrite:
pathTemplateRewrite: '/echo/profile/{customer}'
EOF
# validate new config
gcloud beta compute url-maps validate --source=$(pwd)/$URL_MAP_CONFIG_FILE
# import updated config
gcloud beta compute url-maps import $APP_NAME-url-map \
--source=$(pwd)/$URL_MAP_CONFIG_FILE \
--global
@mikesparr
Copy link
Author

Failed tests

##########################################################
# URL rewrite experimentation
# - TODO (test if can add ?customer_id={customer}) to rewrite URL somehow
# - Tests (failed):
#   - /echo/profile/{customer}/?foo=bar
#   - /echo/profile/{customer}/?customer_id={customer}
#   - /echo/profile/{customer}?customer_id={customer}
#   - /echo/profile/{customer}/%3Fcustomer_id={customer}
##########################################################

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment