Delegation via labels
In this example, you learn how to use labels to delegate traffic. The parent HTTPRoute defines the labels that must be present on the child HTTPRoute to allow traffic to be forwarded.
You typically configure the parent to find an HTTPRoute with a specific label in a specific namespace. However, you can also use a wildcard for the namespace when you have multiple HTTPRoutes in different namespaces that can all receive delegated traffic. This configuration can significantly simplify your route delegation setup, as it allows you to quickly add new child HTTPRoutes to the delegation chain without changing the parent HTTPRoute configuration.
Explore an example for delegating traffic to an HTTPRoute with a specific label in a specific namespace. To try out this example, see the Before you begin section and then continue with HTTPRoutes in specific namespaces.
parent
HTTPRoute:
- The parent HTTPRoute resource delegates traffic as follows:
- Requests to
/anything/team1
are delegated to the child HTTPRoute resourcechild-team1
in namespaceteam1
with thedelegation.kgateway.dev/label: team1
label. - Requests to
/anything/team2
are delegated to the child HTTPRoute resourcechild-team2
in namespaceteam2
with thedelegation.kgateway.dev/label: team2
label.
- Requests to
child-team1
HTTPRoute:
- The child HTTPRoute resource
child-team1
matches incoming traffic for the/anything/team1/foo
prefix path and routes that traffic to the httpbin app in theteam1
namespace.
child-team2
HTTPRoute:
- The child HTTPRoute resource
child-team2
matches incoming traffic for the/anything/team1/bar
prefix path and routes that traffic to the httpbin app in theteam2
namespace.
Learn how to use a wildcard for the namespace to streamline your route delegation setup. To try out this example, see the Before you begin section and then continue with Use wildcard namespaces.
parent
HTTPRoute:
- The parent HTTPRoute resource delegates traffic as follows:
- Requests to
/
are delegated to all child HTTPRoute resources with thedelegation.kgateway.dev/label: wildcard
label. The/
matcher is used so that the child HTTPRoutes can define any path prefix that they want to match traffic on.
- Requests to
child-team1
HTTPRoute:
- The child HTTPRoute resource
child-team1
matches incoming traffic for the/anything/team1/foo
prefix path and routes that traffic to the httpbin app in theteam1
namespace. The HTTPRoute is configured with thedelegation.kgateway.dev/label: wildcard
label so that it can receive delegated traffic from theparent
.
child-team2
HTTPRoute:
- The child HTTPRoute resource
child-team2
matches incoming traffic for the/anything/team1/bar
prefix path and routes that traffic to the httpbin app in theteam2
namespace. The HTTPRoute is configured with thedelegation.kgateway.dev/label: wildcard
label so that it can receive delegated traffic from theparent
.
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_ADDRESS
kubectl port-forward deployment/http -n kgateway-system 8080:8080
-
Create the namespaces for
team1
andteam2
.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 team2
Example 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
HTTPRoutes in specific namespaces
-
Create the parent HTTPRoute resource that matches incoming traffic on the
delegation.example
domain. The HTTPRoute resource specifies two routes:- Route 1 matches traffic on the path prefix
/anything/team1
and delegates traffic to the HTTPRoute with thedelegation.kgateway.dev/label: team1
label. - Route 2 matches traffic on the path prefix
/anything/team2
and delegates traffic to the HTTPRoute with thedelegation.kgateway.dev/label: team2
label.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: parent namespace: kgateway-system spec: parentRefs: - name: http hostnames: - delegation.example rules: - matches: - path: type: PathPrefix value: /anything/team1 backendRefs: # Delegate to routes with the label delegation.gateway.solo.io/label:team1 # in the team1 namespace - group: delegation.kgateway.dev kind: label name: team1 namespace: team1 - matches: - path: type: PathPrefix value: /anything/team2 backendRefs: # Delegate to routes with the label delegation.gateway.solo.io/label:team2 # in the team2 namespace - group: delegation.kgateway.dev kind: label name: team2 namespace: team2 EOF
- Route 1 matches traffic on the path prefix
-
Create the
child-team1
HTTPRoute resource in theteam1
namespace that matches traffic on the/anything/team1/foo
path prefix. To delegate traffic to this HTTPRoute, you must label the route with thedelegation.kgateway.dev/label: team1
label that you defined on theparent
HTTPRoute.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team1 namespace: team1 labels: delegation.kgateway.dev/label: team1 spec: rules: - matches: - path: type: PathPrefix value: /anything/team1/foo backendRefs: - name: httpbin port: 8000 EOF
-
Create the
child-team2
HTTPRoute resource in theteam2
namespace that matches traffic on the/anything/team2/bar
exact prefix. To delegate traffic to this HTTPRoute, you must label the route with thedelegation.kgateway.dev/label: team2
label that you defined on theparent
HTTPRoute.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team2 namespace: team2 labels: delegation.kgateway.dev/label: team2 spec: rules: - matches: - path: type: Exact value: /anything/team2/bar backendRefs: - name: httpbin port: 8000 EOF
-
Send a request to the
delegation.example
domain along the/anything/team1/foo
path. Verify that you get back a 200 HTTP response code.curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team1/foo \ -H "host: delegation.example:8080"
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 content-length: 509 x-envoy-upstream-service-time: 0 server: envoy { "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "delegation.example:8080" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "65927858-2c6b-42ae-9278-8ff9d8bba3f8" ] }, "origin": "10.0.64.27:49526", "url": "http://delegation.example:8080/anything/team1/foo", "data": "", "files": null, "form": null, "json": null }
-
Send a request to the
delegation.example
domain along the/anything/team2/bar
path. Verify that you also get back a 200 HTTP response code.
curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team2/bar \ -H "host: delegation.example:8080"
curl -i localhost:8080/anything/team2/bar \ -H "host: delegation.example:8080"
Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 content-length: 509 x-envoy-upstream-service-time: 1 server: envoy { "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "delegation.example:8080" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "d645dc37-5326-4b69-8c2c-4060e12ca4ff" ] }, "origin": "10.0.64.27:53026", "url": "http://delegation.example:8080/anything/team2/bar", "data": "", "files": null, "form": null, "json": null }
Use wildcard namespaces
Instead of routing to an HTTPRoute with a specific label in a specific namespace, you can use a wildcard for the namespace. This configuration can streamline your route delegation setup, as it allows you to easily add new child HTTPRoutes to the delegation chain.
-
Update the
parent
HTTPRoute to delegate traffic to all child HTTPRoutes with thewildcard
label.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: parent namespace: kgateway-system spec: parentRefs: - name: http hostnames: - delegation.example rules: - matches: - path: type: PathPrefix value: / backendRefs: - group: delegation.kgateway.dev kind: label name: wildcard namespace: all EOF
-
Update the
child-team1
HTTPRoute to add thedelegation.kgateway.dev/label: wildcard
label so that theparent
HTTPRoute can delegate traffic to this route.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team1 namespace: team1 labels: delegation.kgateway.dev/label: wildcard spec: rules: - matches: - path: type: PathPrefix value: /anything/team1/foo backendRefs: - name: httpbin port: 8000 EOF
-
Update the
child-team2
HTTPRoute to also add thedelegation.kgateway.dev/label: wildcard
label.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: child-team2 namespace: team2 labels: delegation.kgateway.dev/label: wildcard spec: rules: - matches: - path: type: Exact value: /anything/team2/bar backendRefs: - name: httpbin port: 8000 EOF
-
Send a request to the
delegation.example
domain along the/anything/team1/foo
path. Verify that you get back a 200 HTTP response code.curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team1/foo \ -H "host: delegation.example:8080"
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 content-length: 509 x-envoy-upstream-service-time: 0 server: envoy { "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "delegation.example:8080" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "65927858-2c6b-42ae-9278-8ff9d8bba3f8" ] }, "origin": "10.0.64.27:49526", "url": "http://delegation.example:8080/anything/team1/foo", "data": "", "files": null, "form": null, "json": null }
-
Send a request to the
delegation.example
domain along the/anything/team2/bar
path. Verify that you also get back a 200 HTTP response code.
curl -i http://$INGRESS_GW_ADDRESS:8080/anything/team2/bar \ -H "host: delegation.example:8080"
curl -i localhost:8080/anything/team2/bar \ -H "host: delegation.example:8080"
Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 content-length: 509 x-envoy-upstream-service-time: 1 server: envoy { "args": {}, "headers": { "Accept": [ "*/*" ], "Host": [ "delegation.example:8080" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "d645dc37-5326-4b69-8c2c-4060e12ca4ff" ] }, "origin": "10.0.64.27:53026", "url": "http://delegation.example:8080/anything/team2/bar", "data": "", "files": null, "form": null, "json": null }
Cleanup
You can remove the resources that you created in this guide.kubectl delete httproute parent -n kgateway-system
kubectl delete httproute child-team1 -n team1
kubectl delete httproute child-team2 -n team2
kubectl delete -n team1 -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/httpbin.yaml
kubectl delete -n team2 -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/httpbin.yaml
kubectl delete namespaces team1 team2