Delegate VirtualHost and RouteTable options
You can use the VirtualHostOption
resource and options setting of the RouteTable
resource to specify option settings for virtual hosts and route tables, such as traffic management configurations or policies. The main virtual host and route table resources can then delegate to these options to apply them.
This approach is useful if you have traffic management or policy settings that you want to apply to multiple virtual hosts or routes, such as a rate limiting configuration that you want to reuse across hosts. It can also help to keep the main virtual host and route table resources concise, which can simplify the troubleshooting process in case of an error.
Rules for delegating to VirtualHostOption and RouteTable resources
When delegating to VirtualHostOption
and RouteTable
resources from the main virtual service or route table resource, the following rules apply:
- Options that are specified on the main virtual service or route table resource take precedence over options that are specified on
VirtualHostOption
andRouteTable
resources. For example, if a header manipulation policy is specified on the main virtual service resource, header manipulation policies inVirtualHostOption
resources that the virtual service delegates to are ignored. - If delegating to multiple
VirtualHostOption
andRouteTable
resources, the resource configuration is applied in order. For example, if a virtual service delegates to twoVirtualHostOption
resources, and both of them specify retry policies, only the retry policy from theVirtualHostOption
resource that is delegated to first is applied. The retry policy in subsequentVirtualHostOption
resources is ignored.
Keep in mind that delegating to several VirtualHostOption
and RouteTable
resources can complicate the troubleshooting process, as you might need to analyze multiple option resources to find the root cause of an issue. In addition, updates to VirtualHostOption
and RouteTable
resources that introduce errors can have large impacts on your environment depending on how often these resources are delegated to.
Example
The following example uses the httpbin app to demonstrate how option settings inVirtualService
and VirtualHostOption
resources are applied. The same rules apply to the option settings of RouteTable
resources.
-
Create the httpbin namespace.
kubectl create ns httpbin
-
Deploy the httpbin app.
kubectl -n httpbin apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/httpbin.yaml
Example output:
serviceaccount/httpbin created service/httpbin created deployment.apps/httpbin created
-
Verify that the httpbin app is running.
kubectl -n httpbin get pods
Example output:
NAME READY STATUS RESTARTS AGE httpbin-d57c95548-nz98t 3/3 Running 0 18s
-
Create a virtual service to expose the httpbin app on the gateway. The following virtual service removes the
User-Agent
header from the request and delegates to twoVirtualHostOption
resources that you create in later steps. BothVirtualHostOption
resources apply additional configuration to the virtual host.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: VirtualService metadata: name: httpbin namespace: httpbin ownerReferences: [] spec: virtualHost: domains: - '*' options: headerManipulation: requestHeadersToRemove: ["User-Agent"] optionsConfigRefs: delegateOptions: - name: virtualhost-options-1 namespace: gloo-system - name: virtualhost-options-2 namespace: gloo-system routes: - matchers: - prefix: / routeAction: single: upstream: name: httpbin-httpbin-8000 namespace: gloo-system EOF
-
Create a
VirtualHostOption
resource that defines additional virtual host options. In the following example, you want to add themyheader
header to the request and apply a retry policy.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: VirtualHostOption metadata: name: virtualhost-options-1 namespace: gloo-system spec: options: headerManipulation: requestHeadersToAdd: - header: key: myheader value: "option-test" retries: retryOn: 'connect-failure' numRetries: 3 perTryTimeout: '5s' EOF
-
Create a second
VirtualHostOption
resource that defines more virtual host options. In this example, you want to remove thecontent-type
request header and limit requests to your app to 1 per minute.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: VirtualHostOption metadata: name: virtualhost-options-2 namespace: gloo-system spec: options: headerManipulation: requestHeadersToRemove: ["content-header"] ratelimitBasic: anonymousLimits: unit: MINUTE requestsPerUnit: 1 retries: retryOn: 'connect-failure' numRetries: 5 perTryTimeout: '10s' EOF
-
Verify your final settings by sending multiple requests to the httpbin app. Following the rules for applying virtual host and route table option resources, the following behavior is expected:
headerManipulation
: Because the main virtual service resource specifies header manipulation settings, these settings take precedence over header manipulation settings that are configured on delegatedVirtualHostOption
resources. Consequently, the header manipulation settings from bothVirtualHostOption
resources are ignored.retries
: Retry settings from thevirtualhost-options-1
resource take precedence over the retry settings invirtualhost-options-2
, because the main virtual service resource delegates tovirtualhost-options-1
first. Retry settings in subsequentVirtualHostOption
resources are ignored.ratelimitBasic
: Because the main virtual service and thevirtualhost-options-1
virtual host option resources do not specify any rate limiting settings, the rate limit settings fromvirtualhost-options-2
are applied to the virtual host.
curl -vik $(glooctl proxy url)/headers
Example output for the first request. Note that the
User-Agent
request header is removed and that neither themyheader
header fromvirtualhost-options-1
was added, nor theAccept
header fromvirtualhost-options-2
was removed.* Mark bundle as not supporting multiuse < HTTP/1.1 200 OK HTTP/1.1 200 OK < access-control-allow-credentials: true access-control-allow-credentials: true < access-control-allow-origin: * access-control-allow-origin: * < content-type: application/json; encoding=utf-8 content-type: application/json; encoding=utf-8 < date: Wed, 29 Nov 2023 19:40:11 GMT date: Wed, 29 Nov 2023 19:40:11 GMT < content-length: 339 content-length: 339 < x-envoy-upstream-service-time: 2 x-envoy-upstream-service-time: 2 < server: envoy server: envoy < { "headers": { "Accept": [ "*/*" ], "Host": [ "a852ba7eb4adf4042a8e392766a1eca4-1405206594.us-east-2.elb.amazonaws.com" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "5000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "d809363f-c8c7-45fc-a33b-e67246c874b3" ] } }
Example output after sending a few requests to httpbin. Verify that your rate limiting settings from
virtualhost-options-2
are applied and that you see a 429 HTTP response code.* Mark bundle as not supporting multiuse < HTTP/1.1 429 Too Many Requests HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true x-envoy-ratelimited: true < date: Wed, 29 Nov 2023 19:45:01 GMT date: Wed, 29 Nov 2023 19:45:01 GMT < server: envoy server: envoy < content-length: 0 content-length: 0
-
Find your settings in the currently applied Gloo Gateway configuration to verify the settings that were applied.
glooctl proxy served-config
Example output:
name: listener-::-8080-routes virtualHosts: - domains: - '*' name: gloo-system_httpbin # rate limit settings from virtualhost-options-2 rateLimits: - actions: - genericKey: descriptorValue: gloo-system_httpbin - headerValueMatch: descriptorValue: is-authenticated expectMatch: true headers: - name: x-user-id presentMatch: true - requestHeaders: descriptorKey: userid headerName: x-user-id stage: 0 - actions: - genericKey: descriptorValue: gloo-system_httpbin - headerValueMatch: descriptorValue: not-authenticated expectMatch: false headers: - name: x-user-id presentMatch: true - remoteAddress: {} stage: 0 # header manipulation settings from main virtual service requestHeadersToRemove: - User-Agent # retry policy settings from virtualhost-options-1 retryPolicy: numRetries: 3 perTryTimeout: 5s retryOn: connect-failure routes: - match: prefix: / name: gloo-system_httpbin-route-0-matcher-0 route: cluster: httpbin-httpbin-8000_gloo-system typedPerFilterConfig: envoy.filters.http.ext_authz: '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute disabled: true
Cleanup
You can optionally clean up the resources that you created as part of this guide.
kubectl delete virtualservice httpbin -n httpbin
kubectl delete virtualhostoption virtualhost-options-1 -n gloo-system
kubectl delete virtualhostoption virtualhost-options-2 -n gloo-system
kubectl delete -n httpbin -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/httpbin.yaml
kubectl delete namespace httpbin