GCP traffic splitting across external services in url map error: "One of backend_service or url_redirect must be set"

Viewed 609

First of all, I have an internet network endpoint group (NEG):

gcloud compute network-endpoint-groups update [neg-name] \
    --add-endpoint="fqdn=[service.example.com],port=443" \
    --global

This is what's called "Global external HTTP(S) load balancer (classic)" in the Backend Service documentation.

I have two services, created like this:

gcloud beta compute backend-services create [service-name] \
        --load-balancing-scheme=EXTERNAL \
        --protocol=HTTPS \
        --port-name=https \
        --enable-logging \
        --logging-sample-rate=1 \
        --global

gcloud beta compute backend-services add-backend [service-name] \
       --network-endpoint-group=[neg-name] \
       --global-network-endpoint-group \
       --global \
       --custom-request-header="Host: service.example.com" # Fix SSL issue

I also have a url map, created like this:

gcloud beta compute url-maps create [url-map-name] \
        --default-service [service 1 name]

I want to create a traffic splitting rule that routes traffic between service 1 and service 2. Following the load balancing docs, I came up with this:

creationTimestamp: '2021-11-26T12:41:59.779-08:00'
defaultService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
fingerprint: [fingerprint]
hostRules:
- hosts:
  - '*'
  pathMatcher: default-matcher
id: [id]
kind: compute#urlMap
name: [url-map-name]
pathMatchers:
- defaultService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
  name: default-matcher
  routeRules:
  - priority: 1
    matchRules:
      - prefixMatch: '/'
    routeAction:
      weightedBackendServices:
        - weight: 50
          backendService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 2 name]
        - weight: 50
          backendService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
selfLink: https://www.googleapis.com/compute/beta/projects/[project-name]/global/urlMaps/[url-map-name]

When I try to edit the url map with the above configuration, the following error is returned (debugger breakpoints included in output):

$ gcloud beta compute url-maps edit [url-map-name] --global --verbosity=debug
DEBUG: Running [gcloud.beta.compute.url-maps.edit] with arguments: [--global: "True", --verbosity: "debug", URL_MAP: "[url-map-name]"]
INFO: Display format: "default"
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "POST /batch/compute/beta HTTP/1.1" 200 None
> /opt/google-cloud-sdk/lib/surface/compute/url_maps/edit.py(100)_ProcessEditedResource()
-> return holder.client.MakeRequests(
(Pdb) c
DEBUG: https://compute.googleapis.com:443 "POST /batch/compute/beta HTTP/1.1" 200 None
> /opt/google-cloud-sdk/lib/googlecloudsdk/api_lib/compute/batch_helper.py(117)MakeRequests()
-> error_message = None
(Pdb) c
> /opt/google-cloud-sdk/lib/googlecloudsdk/api_lib/compute/client_adapter.py(116)MakeRequests()
-> utils.RaiseToolException(errors, error_message="Could not fetch resource:")
(Pdb) errors
[(400, 'Invalid value for field \'resource\': \'{  "name": "[url-map-name]",  "hostRule": [{    "host": ["*"],    "pathMatcher": "default-matcher...\'. One of backend_service or url_redirect must be set')]
(Pdb) c
There was a problem applying your changes: Could not fetch resource:
 - Invalid value for field 'resource': '{  "name": "[url-map-name]",  "hostRule": [{    "host": ["*"],    "pathMatcher": "default-matcher...'. One of backend_service or url_redirect must be
 set

Would you like to edit the resource again? (Y/n)?  n

Validating (Thank you Alex G):

$ gcloud beta compute url-maps validate --source=url-map-traffic-splitting.yml --global --verbosity=debug
DEBUG: Running [gcloud.beta.compute.url-maps.validate] with arguments: [--global: "True", --source: "url-map-traffic-splitting.yml", --verbosity: "debug"]
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "POST /compute/beta/projects/[project-name]/global/urlMaps/[url-map-name]/validate?alt=json HTTP/1.1" 200 None
INFO: Display format: "default"
result:
  loadErrors:
  - One of backend_service or url_redirect must be set
  loadSucceeded: false
  testPassed: false
DEBUG: SDK update checks are disabled.

What I've tried:

  • Tried with pathRules instead of routeRules, it works and the url map is updated.
  • I tried hacking the gcloud libraries to give better errors - but the error is returned by the API, not the client:
    HttpError accessing <https://compute.googleapis.com/batch/compute/beta>: response: <{'Content-Type': 'application/json; charset=UTF-8', 'Vary': 'Origin', 'status': '400'}>, content <{
      "error": {
        "code": 400,
        "message": "Invalid value for field 'resource': '{  \"name\": \"[url-map-name]\",  \"hostRule\": [{    \"host\": [\"*\"],    \"pathMatcher\": \"default-matcher...'. One of backend_service or url_redirect must be set",
        "errors": [
          {
            "message": "Invalid value for field 'resource': '{  \"name\": \"[url-map-name]\",  \"hostRule\": [{    \"host\": [\"*\"],    \"pathMatcher\": \"default-matcher...'. One of backend_service or url_redirect must be set",
            "domain": "global",
            "reason": "invalid"
          }
        ]
      }
    }
    
  • I've searched the GCP documentation for any mentions of this error, or mentions of limits to what url maps can do, but found nothing.
0 Answers
Related