Multi-level delegation
Create a 3-level route delegation hierarchy with a parent, child, and grandchild HTTPRoute resource.
Configuration overview
In this guide you walk through a route delegation example that demonstrates route delegation from a parent HTTPRoute resource to a child HTTPRoute resource, and from a child HTTPRoute resource to a grandchild HTTPRoute resource. The following image illustrates the route delegation hierarchy:
parent HTTPRoute:
- The parent HTTPRoute resource
parentdelegates traffic as follows:/anything/team1delegates traffic to the child HTTPRoute resourcechild-team1in namespaceteam1./anything/team2delegates traffic to the child HTTPRoute resourcechild-team2in namespaceteam2.
child-team1 HTTPRoute:
- The child HTTPRoute resource
child-team1matches incoming traffic for the/anything/team1/fooprefix path and routes that traffic to the httpbin app in theteam1namespace.
child-team2 HTTPRoute:
- The child HTTPRoute resource
child-team2delegates traffic on the/anything/team2/grandchildto a grandchild HTTPRoute resource in theteam2namespace.
grandchild HTTPRoute:
- The grandchild HTTPRoute resource
grandchild-team2matches incoming traffic for the/anything/team2/grandchild/.*regex path and routes that traffic to the httpbin app in theteam2namespace.
Before you begin
-
Follow the Get started guide to install kgateway.
-
Create a Gateway resource and configure an HTTP listener. The following Gateway can serve HTTPRoute resources from all namespaces.
kubectl apply -f- <<EOF kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: http namespace: kgateway-system spec: gatewayClassName: kgateway listeners: - protocol: HTTP port: 8080 name: http allowedRoutes: namespaces: from: All EOF -
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESSkubectl port-forward deployment/http -n kgateway-system 8080:8080 -
Create the namespaces for
team1andteam2.kubectl create namespace team1 kubectl create namespace team2 -
Deploy the httpbin app into both namespaces.
kubectl -n team1 apply -f https://raw.githubusercontent.com/kgateway-dev/kgateway.dev/main/assets/docs/examples/httpbin.yaml kubectl -n team2 apply -f https://raw.githubusercontent.com/kgateway-dev/kgateway.dev/main/assets/docs/examples/httpbin.yaml -
Verify that the httpbin apps are up and running.
kubectl get pods -n team1 kubectl get pods -n team2Example output:
NAME READY STATUS RESTARTS AGE httpbin-f46cc8b9b-bzl9z 3/3 Running 0 7s NAME READY STATUS RESTARTS AGE httpbin-f46cc8b9b-nhtmg 3/3 Running 0 6s
Setup
-
Create the parent HTTPRoute resource that matches incoming traffic on the
delegation.exampledomain. The HTTPRoute resource specifies two routes:/route1/team1: The routing decision is delegated to a child HTTPRoute resource in theteam1namespace./route2/team2: The routing decision is delegated to a child HTTPRoute resource in theteam2namespace.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: parent namespace: kgateway-system spec: hostnames: - delegation.example parentRefs: - name: http rules: - matches: - path: type: PathPrefix value: /anything/team1 backendRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: "*" namespace: team1 - matches: - path: type: PathPrefix value: /anything/team2 backendRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: "*" namespace: team2 EOF -
Create the
child-team1HTTPRoute resource in theteam1namespace that matches traffic on the/anything/team1/fooprefix and routes traffic to the httpbin app in theteam1namespace. The child HTTPRoute resource does not select a specific parent HTTPRoute resource. Because of that, the child HTTPRoute resource is automatically selected by all parent HTTPRoute resources that delegate traffic to this child.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team1 namespace: team1 spec: rules: - matches: - path: type: PathPrefix value: /anything/team1/foo backendRefs: - name: httpbin port: 8000 EOF -
Create the
child-team2HTTPRoute resource in theteam2namespace that matches traffic on the/anything/team2/grandchild/prefix and delegates traffic to an HTTPRoute resource in theteam2namespace. Note that because the child delegates traffic to a grandchild, aPathPrefixmatcher must be used.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team2 namespace: team2 spec: rules: - matches: - path: type: PathPrefix value: /anything/team2/grandchild/ backendRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: "*" namespace: team2 EOF -
Create a grandchild HTTPRoute resource that matches traffic on the
/anything/team2/grandchild/.*regex path and routes traffic to the httpbin app in theteam2namespace.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: grandchild namespace: team2 spec: rules: - matches: - path: type: RegularExpression value: /anything/team2/grandchild/.* backendRefs: - name: httpbin port: 8000 EOF -
Send a request to the
delegation.exampledomain along the/anything/team1/foopath. Verify that you get back a 200 HTTP response code.curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team1/foo \ -H "host: delegation.example"curl -i localhost:8080/anything/team1/foo \ -H "host: delegation.example"Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 date: Mon, 06 May 2024 15:59:32 GMT x-envoy-upstream-service-time: 0 server: envoy transfer-encoding: chunked -
Send another request to the
delegation.exampledomain along the/anything/team1/barpath. Verify that you get back a 404 HTTP response code, because this route is not specified in the child HTTPRoute resourcechild-team1.curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team1/bar \ -H "host: delegation.example"curl -i localhost:8080/anything/team1/bar \ -H "host: delegation.example"Example output:
HTTP/1.1 404 Not Found date: Mon, 06 May 2024 16:01:48 GMT server: envoy transfer-encoding: chunked -
Send another request to the
delegation.exampledomain. This time, you use the/anything/team2/grandchild/barpath that is configured on thegrandchildHTTPRoute resource. Verify that you get back a 200 HTTP response code.curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team2/grandchild/bar \ -H "host: delegation.example"curl -i localhost:8080/anything/team2/grandchild/bar \ -H "host: delegation.example"Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 date: Mon, 06 May 2024 15:59:32 GMT x-envoy-upstream-service-time: 0 server: envoy transfer-encoding: chunked -
Send another request to the
delegation.exampledomain along the/anything/team2/grandchild/foopath. Because the grandchild HTTPRoute resource uses a regular expression to match incoming traffic, you can use any valid endpoint in the httpbin app to route traffic to the httpbin app in theteam2namespace.
curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team2/grandchild/foo \ -H "host: delegation.example"curl -i localhost:8080/anything/team2/grandchild/foo \ -H "host: delegation.example"Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 date: Mon, 06 May 2024 15:59:32 GMT x-envoy-upstream-service-time: 0 server: envoy transfer-encoding: chunked
Cleanup
You can remove the resources that you created in this guide.kubectl delete gateway http -n kgateway-system
kubectl delete httproute parent -n kgateway-system
kubectl delete httproute child-team1 -n team1
kubectl delete httproute child-team2 -n team2
kubectl delete httproute grandchild -n team2
kubectl delete -n team1 -f https://raw.githubusercontent.com/kgateway-dev/kgateway.dev/main/assets/docs/examples/httpbin.yaml
kubectl delete -n team2 -f https://raw.githubusercontent.com/kgateway-dev/kgateway.dev/main/assets/docs/examples/httpbin.yaml
kubectl delete namespaces team1 team2