Last active
August 8, 2023 23:48
-
-
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
This file contains 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/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 | |
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
URL Rewrite with ALB
Testing whether you can capture url path template parameters and then reallocate them to a querystring. It appears you currently CANNOT append captured path parameters to the querystring based on these tests.
Experiment
Given input:
/echo/3/profile
where 3 representscustomer_id
Desired output:
/echo/profile/3/?customer_id=3
Results
It does not appear possible to accomplish this, even with the new Application Load Balancer. At first there were errors when trying to import the new url map config in the terminal using
gcloud compute url-maps import ...
command.Errors disappeared after removing the querystring from
line 131
withpathTemplateRewrite
field.After various tests, I was successful at importing a config using urlencoded parameters
%3F
for?
and%3D
for=
. That resulted, unfortunately, in the same output successfully swapping the{customer}
second path param with 3rd, but leaving the{query:
object blank.Screenshots