Usage
Define Gateways for HAProxy Unified Gateway
Gateways are Kubernetes objects that relay traffic from outside the cluster to inside, directing the request to the correct service as defined by HTTPRoute or other kinds of route rules. Each Gateway that you define instantiates a proxy. When you define a Gateway that has a gatewayClassName field of haproxy, it will be backed by the HAProxy Unified Gateway controller that you installed.
Prerequisites checklist Jump to heading
Before continuing, ensure that you’ve met these prerequisites:
Add a Gateway for a hostname Jump to heading
You can limit a Gateway so that it will route traffic for specific hostnames only. For instance, you could define a Gateway that handles traffic for the hostname example.com. It will ignore other traffic.
When to use this:
- You want to limit which services can connect through this Gateway. For instance, this may be a production Gateway for which you want to control usage.
To define a Gateway for a single hostname:
-
Create a file named
gateway.yamlto define your Gateway. In this example, we set these fields:Field Description nameSets the name of the Gateway, which HTTPRoute resources will use to refer to this Gateway. namespaceSets the Kubernetes namespace to deploy this Gateway into. gatewayClassNameSets the Gateway’s class. The class maps to the HAProxy Unified Gateway controller. listenersLists TCP ports at which to receive traffic. nameSets a name for the listener, which will appear in logs. protocolSets a protocol type for the listener. portMatches a targetPortdefined on the controller’s Service resource. In this example, we’re using theHTTPport. You’ll use the same port for all HTTP Gateways.hostnameSets the hostname to match. This Gateway will route traffic for that hostname only. allowedRoutesRestricts the kinds of route resources that can connect to this Gateway. Here, we’ve configured it to accept only HTTPRoute resources that are defined in the same namespace. For more information about these fields, see the Gateway API specification for Gateway.
gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080hostname: "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: 31080hostname: "example.com"allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Same -
Apply the changes with
kubectl:nixkubectl apply -f gateway.yamlnixkubectl apply -f gateway.yamloutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway createdoutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway createdNext, define one or more routes.
Add a Gateway for all hostnames Jump to heading
To have the Gateway match traffic for all hostnames, omit the hostname field under listeners. When doing this, you’ll typically configure your HTTPRoute or other kinds of route resources to filter on hostname and route to the correct service.
When to use this:
- You have a Gateway that it’s permissible to connect any service to. Development teams can manage which hostnames to assign to services and route the traffic through this Gateway. For instance, they could define a service that receives traffic at
api.example.com, and another atweb.example.com. The Gateway will allow traffic from both to flow through the same proxy.
In the example below, we omit hostname to accept all traffic.
-
Create a file named
gateway.yaml.gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080allowedRoutes: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: 31080allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Same -
Apply the changes with
kubectl:nixkubectl apply -f gateway.yamlnixkubectl apply -f gateway.yamloutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway createdoutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway createdNext, define one or more routes.
Allow routes from other namespaces Jump to heading
When you set allowedRoutes.namespaces.from to Same, then the Gateway will accept only route resources defined in the same namespace as the Gateway. It will ignore others. Use this when you want to deploy a Gateway to a namespace and have it handle traffic for services in that namespace only. You can also deploy Gateways that set from to any of these values:
| From | Description |
|---|---|
All |
Matches routes from any namespace. |
Same |
Matches routes from the same namespace where the Gateway is deployed. |
Selector |
Matches routes from namespaces matching the selector attribute. In this case, add a selector attribute to define the match criteria. |
To match route resources from other namespaces via a selector:
-
When defining your namespace, add a label. In this example, we set a label named
shared-gateway-access.namespace.yamlyamlapiVersion: v1kind: Namespacemetadata:name: example-namespacelabels:shared-gateway-access: "true"namespace.yamlyamlapiVersion: v1kind: Namespacemetadata:name: example-namespacelabels:shared-gateway-access: "true" -
On the Gateway, set
namespaces.fromtoSelector. Also, define theselector. In the example below, the selector usesmatchLabelsto indicate that only HTTPRoute resources defined in namespaces with the labelshared-gateway-accessset totruewill be used.gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080hostname: "example.com"allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Selectorselector:matchLabels:shared-gateway-access: "true"gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080hostname: "example.com"allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Selectorselector:matchLabels:shared-gateway-access: "true"
Add an HTTPS listener Jump to heading
HAProxy Unified Gateway can terminate TLS at the Gateway level. Using this mechanism, clients connect via HTTPS, HAProxy Unified Gateway terminates TLS with the specified TLS certificate, and then it forwards the requests to the backends over HTTP. This reduces TLS workload on backend services if they don’t require HTTPS.
To terminate TLS using HAProxy Unified Gateway:
-
For testing, generate a self-signed TLS certificate for the domain
example.comwith theopenssl reqcommand.nixopenssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=example.com" -days 365nixopenssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=example.com" -days 365 -
Create the
example-tlssecret with thekubectl create secretcommand.nixkubectl create secret tls example-tls --cert=tls.crt --key=tls.keynixkubectl create secret tls example-tls --cert=tls.crt --key=tls.key -
Update your Gateway to have an HTTPS listener.
- The
tlssection setsmodetoTermianteand references a TLS secret namedexample-tls.
gateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Same- name: httpsprotocol: HTTPSport: 31443allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Sametls:mode: TerminatecertificateRefs:- name: example-tlsgateway.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata:name: example-haproxy-gatewaynamespace: defaultspec:gatewayClassName: haproxylisteners:- name: httpprotocol: HTTPport: 31080allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Same- name: httpsprotocol: HTTPSport: 31443allowedRoutes:kinds:- group: gateway.networking.k8s.iokind: HTTPRoutenamespaces:from: Sametls:mode: TerminatecertificateRefs:- name: example-tlsApply the changes with
kubectl:nixkubectl apply -f gateway.yamlnixkubectl apply -f gateway.yamloutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway configuredoutputtextgateway.gateway.networking.k8s.io/example-haproxy-gateway configured - The
-
Optional: When defining an HTTPRoute, you can force only HTTPS for your application by setting
sectionNameto thehttpsGateway listener. Otherwise, all listeners with a matchingallowedRoutesentry can be used.http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: http-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewaysectionName: httpshostnames:- "example.com"rules:- backendRefs:- name: web-svcnamespace: defaultport: 80http-route.yamlyamlapiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:name: http-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewaysectionName: httpshostnames:- "example.com"rules:- backendRefs:- name: web-svcnamespace: defaultport: 80Apply the changes with
kubectl:nixkubectl apply -f http-route.yamlnixkubectl apply -f http-route.yamloutputtexthttproute.gateway.networking.k8s.io/http-route createdoutputtexthttproute.gateway.networking.k8s.io/http-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
web-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.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 http-echo instance:
-
Use the following command to find the HTTPS NodePort configured for your HAProxy Unified Gateway Service. In this example the NodePort is 31443, the NodePort associated with the TCP port 8443.
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 https://example.com/ -knixcurl https://example.com/ -kOtherwise, use this command to set the
Hostheader toexample.com:nixcurl https://<NODEPORT_IP>:<NODEPORT> -H "Host: example.com" -knixcurl https://<NODEPORT_IP>:<NODEPORT> -H "Host: example.com" -koutputtextWEB RESPONSEoutputtextWEB RESPONSEThis indicates that the Gateway terminated the TLS connection and then made connection to the HTTP backend.
See also Jump to heading
- Refer to the Gateway API reference for Gateway.
- Learn more about cross-namespace routing in the Gateway API guide, Cross-namespace Route Attachment.