Routes
Define HTTPRoutes for HAProxy Unified Gateway
The Gateway API defines specialized resources for routing different types of network traffic. You would use an HTTPRoute resource to route HTTP traffic.
Prerequisites checklist Jump to heading
Before continuing, ensure that you’ve met these prerequisites:
- Define a Gateway. When defining a Gateway, set its
allowedRoutesproperty to accept routes of kindHTTPRoute.
Implement hostname-based routing Jump to heading
Hostname-based routing is useful when you want to route traffic based on the domain. For example, you want to route traffic for api.example.com and web.example.com to different services.
To implement hostname-based routing:
-
Update your Gateway resource so that it omits or comments out the
hostnamefield. This ensures that the Gateway will relay traffic for all of your domains.gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080# hostname: "example.com"allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Samegateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080# hostname: "example.com"allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Same -
Define an HTTPRoute resource for your target domain. In this example, we route traffic for the hostname
web.example.com.- The
parentRefssection references one or more Gateways to which an HTTPRoute tries to attach. This HTTPRoute will attach toGatewayresources that have listeners withallowedRoutesmatching theHTTPRoutekind and a matching namespace. - Under
rules, each entry has abackendRefssection to route to the specified service. For example, requests forweb.example.comwill route toweb-svc. AbackendRefsentry refers to the name of a Service resource and its listening port.
hostname-based-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: web-hostname-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayhostnames:- web.example.comrules:- backendRefs:- name: web-svcnamespace: defaultport: 80hostname-based-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: web-hostname-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayhostnames:- web.example.comrules:- backendRefs:- name: web-svcnamespace: defaultport: 80 - The
-
Apply the changes with
kubectl:nixkubectl apply -f hostname-based-route.yamlnixkubectl apply -f hostname-based-route.yamloutputtexthttproute.gateway.networking.k8s.io/api-hostname-route createdoutputtexthttproute.gateway.networking.k8s.io/api-hostname-route created -
If your HTTPRoute resource lists a
backendRefsService that’s in a namespace that’s different from the namespace where the HTTPRoute is defined, you’ll need to add a ReferenceGrant for cross-namespace service references.
Implement path-based routing Jump to heading
Migrating from Ingress API
Path-based routing with Gateway API behaves similarly to traditional Ingress rules. This makes it easy to migrate from HAProxy Kubernetes Ingress Controller or other Ingress controller implementations.
Path-based routing is useful when you have multiple applications under the same domain and want to route traffic based on the URL path. For example, you want to route traffic for example.com/web.
To implement path-based routing:
-
Define an HTTPRoute for routing HTTP traffic for the target URL paths. In this example, we route traffic for the path
/web.- The
parentRefssection references one or more Gateways to which an HTTPRoute tries to attach. This HTTPRoute will attach toGatewayresources that have listeners withallowedRoutesmatching theHTTPRoutekind and a matching namespace. - Under
rules, each entry has amatchesandbackendRefssection. For a path-matching rule, set thetypetoPathPrefix. This means that URL paths that begin with the specifiedvaluewill be routed to the service specified by thebackendRefsentry. For example, requests beginning with/webwill route toweb-svc. AbackendRefsentry refers to the name of a Service resource and its listening port.
path-based-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: path-based-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayrules:- matches:- path:type: PathPrefixvalue: /webbackendRefs:- name: web-svcnamespace: defaultport: 80path-based-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: path-based-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayrules:- matches:- path:type: PathPrefixvalue: /webbackendRefs:- name: web-svcnamespace: defaultport: 80 - The
-
Apply the changes with
kubectl:nixkubectl apply -f path-based-route.yamlnixkubectl apply -f path-based-route.yamloutputtexthttproute.gateway.networking.k8s.io/path-based-route createdoutputtexthttproute.gateway.networking.k8s.io/path-based-route created -
Optional: If your HTTPRoute resource lists a
backendRefsService that’s in a namespace that’s different from the namespace where the HTTPRoute is defined, you’ll need to add a ReferenceGrant for cross-namespace service references. -
Optional: When using path-based routing, you may want to restrict which hostnames your Gateway will accept traffic for. See Add a Gateway for a hostname.
-
Optional: To test connectivity with the Gateway and HTTPRoute you just defined, deploy the example application using Deployment and Service resources. The application uses the
hashicorp/ettp-echoDocker container image. It’ll receive HTTP traffic on port 5678 and respond with text indicating the application’s name.Note that the Service is named
web-svc, which is the same Service name you specified when you defined your HTTPRoute in the previous steps, and it listens on port 80. This is how the HTTPRoute knows the Service to route to.app.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: web-svcnamespace: defaultspec:replicas: 1selector:matchLabels:app: web-svctemplate:metadata:labels:app: web-svcspec:containers:- name: webimage: hashicorp/http-echo:0.2.3args: ["-text=WEB RESPONSE"]ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: web-svcnamespace: defaultspec:selector:app: web-svcports:- port: 80targetPort: 5678app.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: web-svcnamespace: defaultspec:replicas: 1selector:matchLabels:app: web-svctemplate:metadata:labels:app: web-svcspec:containers:- name: webimage: hashicorp/http-echo:0.2.3args: ["-text=WEB RESPONSE"]ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: web-svcnamespace: defaultspec:selector:app: web-svcports:- port: 80targetPort: 5678Apply the changes with
kubectl:nixkubectl apply -f app.yamlnixkubectl apply -f app.yamloutputtextdeployment.apps/web-svc createdservice/web-svc createdoutputtextdeployment.apps/web-svc createdservice/web-svc created
Test the connection (click to expand)
To test the connection to the application:
-
Use the following command to find the NodePort configured for your HAProxy Unified Gateway Service. In this example the NodePort is 31080, the NodePort associated with the TCP port 8080.
nixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewaynixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewayoutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114moutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114m -
From a server that has connection to your cluster, such as the server from which you run
kubectl, usecurlto send a request to the NodePort at the hostname you configured in your Gateway. The HAProxy Unified Gateway service will forward the request to the port you defined in your Gateway.If your DNS is configured to resolve
example.com, use this command:nixcurl http://example.com/webnixcurl http://example.com/webOtherwise, use this command to set the
Hostheader toexample.com:nixcurl http://<NODEPORT_IP>:<NODEPORT>/web -H "Host: example.com"nixcurl http://<NODEPORT_IP>:<NODEPORT>/web -H "Host: example.com"outputtextWEB RESPONSEoutputtextWEB RESPONSE
Implement weighted traffic splitting Jump to heading
Use weighted traffic splitting when you want different percentages of traffic to route to different services. One use case is canary deployments. A canary deployment means routing a small percentage of traffic to the new version of your application, and then gradually ramping up, allowing you to release the new version in the safest possible way.
-
Define an HTTPRoute for routing HTTP traffic to your service.
- The
parentRefssection references the Gateways to which the HTTPRoute wants to attach, which in this case isexample-haproxy-gateway. - In this example, we’re using hostname-based routing, so we’re including the
hostnamessection. - The
backendRefssection lists two services,blueandgreen. Theblueservice will receive 90% of the traffic and thegreenservice will receive 10% of the traffic.
http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: canary-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayhostnames:- "example.com"rules:- backendRefs:- name: bluenamespace: defaultport: 80weight: 9- name: greennamespace: defaultport: 80weight: 1http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: canary-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayhostnames:- "example.com"rules:- backendRefs:- name: bluenamespace: defaultport: 80weight: 9- name: greennamespace: defaultport: 80weight: 1 - The
-
Apply the changes with
kubectl:nixkubectl apply -f http-route.yamlnixkubectl apply -f http-route.yamloutputtexthttproute.gateway.networking.k8s.io/canary-route createdoutputtexthttproute.gateway.networking.k8s.io/canary-route created -
Optional: To test connectivity with the Gateway and HTTPRoute, deploy two test applications using Deployments and Services. Here, we define two example applications using the
hashicorp/ettp-echoDocker container image. They will each receive HTTP traffic on port 5678 and respond with text indicating receipt of the request.Note that the Services are named
blueandgreen, the same Service names you specified when you defined your HTTPRoute in the previous steps, both listening on port 80, which you defined in the HTTPRoute as well. This is how the HTTPRoute knows what Service to route to.apps.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: bluenamespace: defaultspec:replicas: 1selector:matchLabels:app: bluetemplate:metadata:labels:app: bluespec:containers:- name: blueimage: hashicorp/http-echoargs:- "-text=Hello from blue"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: bluenamespace: defaultspec:selector:app: blueports:- port: 80targetPort: 5678---apiVersion: apps/v1kind: Deploymentmetadata:name: greennamespace: defaultspec:replicas: 1selector:matchLabels:app: greentemplate:metadata:labels:app: greenspec:containers:- name: greenimage: hashicorp/http-echoargs:- "-text=Hello from green"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: greennamespace: defaultspec:selector:app: greenports:- port: 80targetPort: 5678apps.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: bluenamespace: defaultspec:replicas: 1selector:matchLabels:app: bluetemplate:metadata:labels:app: bluespec:containers:- name: blueimage: hashicorp/http-echoargs:- "-text=Hello from blue"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: bluenamespace: defaultspec:selector:app: blueports:- port: 80targetPort: 5678---apiVersion: apps/v1kind: Deploymentmetadata:name: greennamespace: defaultspec:replicas: 1selector:matchLabels:app: greentemplate:metadata:labels:app: greenspec:containers:- name: greenimage: hashicorp/http-echoargs:- "-text=Hello from green"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: greennamespace: defaultspec:selector:app: greenports:- port: 80targetPort: 5678 -
Apply the changes with
kubectl:nixkubectl apply -f apps.yamlnixkubectl apply -f apps.yamloutputtextdeployment.apps/blue createdservice/blue createddeployment.apps/green createdservice/green createdoutputtextdeployment.apps/blue createdservice/blue createddeployment.apps/green createdservice/green created
Test the connection (click to expand)
To test the connection to the http-echo instances:
-
Use the following command to find the NodePort configured for your HAProxy Unified Gateway Service. In this example the NodePort is 31080, the NodePort associated with the TCP port 8080.
nixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewaynixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewayoutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114moutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114m -
From a server that has connection to your cluster, such as the server from which you run
kubectl, usecurlto send a request to the NodePort at the hostname you configured in your Gateway. The HAProxy Unified Gateway service will forward the request to the port you defined in your Gateway.If your DNS is configured to resolve
example.com, use this command:nixfor i in {1..20}; do curl http://example.com -H "Host: example.com"; donenixfor i in {1..20}; do curl http://example.com -H "Host: example.com"; doneOtherwise, use this command to set the
Hostheader toexample.com:nixfor i in {1..20}; do curl http://<NODEPORT_IP>:<NODEPORT> -H "Host: example.com"; donenixfor i in {1..20}; do curl http://<NODEPORT_IP>:<NODEPORT> -H "Host: example.com"; doneoutputtextHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from greenHello from greenHello from blueHello from blueHello from blueHello from blueHello from blueoutputtextHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from blueHello from greenHello from greenHello from blueHello from blueHello from blueHello from blueHello from blueMost responses should be from the blue application, with only a small percentage from the green application. The exact number of responses from each may vary from run to run.
Add a ReferenceGrant for cross-namespace service references Jump to heading
If your HTTPRoute lists a Service under backendRefs that’s in a different namespace than the HTTPRoute resource, you’ll need to define a ReferenceGrant resource to allow cross-namespace communication between the HTTPRoute and the Service.
Below, we allow an HTTPRoute in the default namespace to reference a Service in the foo namespace. Note that the to section doesn’t need a namespace because a ReferenceGrant can refer only to resources defined in its own namespace.
foo-referencegrant.yamlyamlapiVersion: gateway.networking.k8s.io/v1alpha2kind: ReferenceGrantmetadata:name: refgrantns1namespace: foospec:from:- group: "gateway.networking.k8s.io"kind: "HTTPRoute"namespace: defaultto:- group: ""kind: "Service"
foo-referencegrant.yamlyamlapiVersion: gateway.networking.k8s.io/v1alpha2kind: ReferenceGrantmetadata:name: refgrantns1namespace: foospec:from:- group: "gateway.networking.k8s.io"kind: "HTTPRoute"namespace: defaultto:- group: ""kind: "Service"
Apply the changes with kubectl:
nixkubectl apply -f foo-referencegrant.yaml
nixkubectl apply -f foo-referencegrant.yaml
Rewrite the requested URL path Jump to heading
You may want to rewrite the URL path before forwarding the request to the backend, because:
- Your backend expects a specific URL structure.
- You want to hide internal routing details.
- You’re consolidating multiple backend services under a shared URL prefix.
- You want to expose a simpler API.
- You’re migrating legacy Ingress rules to Gateway API.
To rewrite the requested URL path:
-
Define an HTTPRoute for routing HTTP traffic to your service.
- The path-matching rule specifies the
typeasPathPrefix. This means that for URL paths that begin with the specifiedvaluewill be routed to the corresponding service specified by thebackendRefsin the rule. There’s also afilteroftype: URLRewritethat instructs the HTTPRoute to replace/servicewith/.
http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: rewrite-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayrules:- matches:- path:type: PathPrefixvalue: /servicefilters:- type: URLRewriteurlRewrite:path:type: ReplacePrefixMatchreplacePrefixMatch: /backendRefs:- name: rewrite-backend-svcnamespace: defaultport: 80http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: rewrite-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewayrules:- matches:- path:type: PathPrefixvalue: /servicefilters:- type: URLRewriteurlRewrite:path:type: ReplacePrefixMatchreplacePrefixMatch: /backendRefs:- name: rewrite-backend-svcnamespace: defaultport: 80 - The path-matching rule specifies the
-
Apply the changes with
kubectl:nixkubectl apply -f http-route.yamlnixkubectl apply -f http-route.yamloutputtexthttproute.gateway.networking.k8s.io/rewrite-route createdoutputtexthttproute.gateway.networking.k8s.io/rewrite-route created -
Optional: To test connectivity with the Gateway and HTTPRoute, deploy a test application using a Deployment and a Service. Here, we define an example application using the
hashicorp/ettp-echoDocker container image. It will receive HTTP traffic on port 5678 (the Gateway terminates the TLS connection and then communicates with backend services over HTTP) and respond with text indicating receipt of the request.Note that the Service is named
rewrite-backend-svc, the same Service name you specified when you defined your HTTPRoute in the previous steps, listening on port 80, which you defined in the HTTPRoute as well. This is how the HTTPRoute knows what Service to route to.apps.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: rewrite-backendnamespace: defaultspec:replicas: 1selector:matchLabels:app: rewrite-backendtemplate:metadata:labels:app: rewrite-backendspec:containers:- name: echoimage: hashicorp/http-echoargs:- "-text=Rewrite backend reached"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: rewrite-backend-svcnamespace: defaultspec:selector:app: rewrite-backendports:- port: 80targetPort: 5678apps.yamlyamlapiVersion: apps/v1kind: Deploymentmetadata:name: rewrite-backendnamespace: defaultspec:replicas: 1selector:matchLabels:app: rewrite-backendtemplate:metadata:labels:app: rewrite-backendspec:containers:- name: echoimage: hashicorp/http-echoargs:- "-text=Rewrite backend reached"ports:- containerPort: 5678---apiVersion: v1kind: Servicemetadata:name: rewrite-backend-svcnamespace: defaultspec:selector:app: rewrite-backendports:- port: 80targetPort: 5678 -
Apply the changes with
kubectl:nixkubectl apply -f apps.yamlnixkubectl apply -f apps.yamloutputtextdeployment.apps/tls-test createdservice/tls-test-svc createdoutputtextdeployment.apps/tls-test createdservice/tls-test-svc created
Test the connection (click to expand)
To test the connection to the http-echo instances:
-
Use the following command to find the NodePort configured for your HAProxy Unified Gateway Service. In this example the NodePort is 31080, the NodePort associated with the TCP port 8080.
nixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewaynixkubectl get service haproxy-unified-gateway -n haproxy-unified-gatewayoutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114moutputtextNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhaproxy-unified-gateway NodePort 10.111.136.206 <none> 8080:31080/TCP,8443:31443/TCP,31024:31689/TCP 114m -
From a server that has connection to your cluster, such as the server from which you run
kubectl, usecurlto send a request to the NodePort at the hostname you configured in your Gateway. The HAProxy Unified Gateway service will forward the request to the port you defined in your Gateway.If your DNS is configured to resolve
example.com, use this command:nixcurl http://example.com/service/foonixcurl http://example.com/service/fooOtherwise, use this command to set the
Hostheader toexample.com:nixcurl http://<NODEPORT_IP>:<NODEPORT>/service/foo -H "Host: example.com"nixcurl http://<NODEPORT_IP>:<NODEPORT>/service/foo -H "Host: example.com"outputtextRewrite backend reachedoutputtextRewrite backend reachedThis indicates that the URL path was rewritten from
/service/footo/.
See also Jump to heading
- Refer to the Gateway API reference for HTTPRoute.