Routes
Define TLSRoutes for HAProxy Unified Gateway
The Gateway API defines specialized resources for routing different types of network traffic. You would use a TLSRoute resource to route TCP traffic that’s encrypted by TLS, where the backend application is responsible for terminating the TLS connection. For this use case, you’d configure a listener on the Gateway that uses the TLS protocol and sets TLS passthrough.
Prerequisites checklist Jump to heading
Before continuing, ensure that you’ve met these prerequisites:
- Define a Gateway. When defining a Gateway, add a TLS listener that set its
allowedRoutesproperty to accept routes of kindTLSRoute.
Implement TLS passthrough Jump to heading
TLS passthrough is useful when the backend application terminates the TLS connection, giving you end-to-end encryption. The Gateway doesn’t decrypt the traffic. You can use this with HTTP applications where the web server handles the TLS or with non-HTTP applications that transfer data over TLS-encrypted TCP.
To implement TLS passthrough:
-
Define a TLSRoute resource for your target domain(s). In this example, we route traffic for the hostname
payments.example.com.Section Description parentRefs References one or more Gateways to which a TLSRoute tries to attach. This TLSRoute will attach to Gatewayresources that have listeners withallowedRoutesmatching theTLSRoutekind and a matching namespace. ThesectionNamefield specifies the name of the listener on the Gateway to attach to. In this example, we attach to the TLS listener.hostnames Lists hostnames to accept traffic for. This also sets the TLS SNI value to match when determining whether to route traffic to the backend application. rules Each entry has a backendRefssection to route to the specified service. For example, requests forpayments.example.comwill route topayments-svc. AbackendRefsentry refers to the name of a Service resource and its listening port.tlsroute.yamlyamlapiVersion: gateway.networking.k8s.io/v1alpha2kind: TLSRoutemetadata:name: payments-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewaysectionName: tls-listenerhostnames:- "payments.example.com"rules:- backendRefs:- name: payments-svcnamespace: defaultport: 443tlsroute.yamlyamlapiVersion: gateway.networking.k8s.io/v1alpha2kind: TLSRoutemetadata:name: payments-routenamespace: defaultspec:parentRefs:- name: example-haproxy-gatewaysectionName: tls-listenerhostnames:- "payments.example.com"rules:- backendRefs:- name: payments-svcnamespace: defaultport: 443 -
Apply the changes with
kubectl:nixkubectl apply -f tlsroute.yamlnixkubectl apply -f tlsroute.yamloutputtexttlsroute.gateway.networking.k8s.io/payments-route createdoutputtexttlsroute.gateway.networking.k8s.io/payments-route created -
If your TLSRoute resource lists a
backendRefsService that’s in a namespace that’s different from the namespace where the TLSRoute is defined, you’ll need to add a ReferenceGrant for cross-namespace service references.
Try a test application
To try out TLS passthrough, deploy this application. It uses HAProxy as the backend application. HAProxy terminates TLS and returns a Hello! message.
-
On Linux, you can generate a self-signed TLS certificate for the domain
payments.example.comwith this command:nixopenssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=payments.example.com" -days 365nixopenssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=payments.example.com" -days 365 -
Use the
kubectl create secretcommand to store your TLS certificate and key in the Kubernetes cluster:nixkubectl create secret tls example-tls --cert=tls.crt --key=tls.keynixkubectl create secret tls example-tls --cert=tls.crt --key=tls.key -
Define a ConfigMap, Deployment, and Service for the application.
payments-svc.yamlyamlapiVersion: v1kind: ConfigMapmetadata:name: haproxy-confdata:haproxy.cfg: |globallog stdout format raw local0pidfile /var/run/haproxy.pidssl-load-extra-del-extssl-load-extra-files keydefaultslog globalmode httpoption httplogtimeout connect 5000timeout client 50000timeout server 50000frontend mysitebind :80bind :443 ssl crt /usr/local/etc/haproxy/ssl/tls.crthttp-request return status 200 content-type text/plain lf-string "Hello!"---apiVersion: apps/v1kind: Deploymentmetadata:name: payments-appnamespace: defaultspec:replicas: 1selector:matchLabels:app: payments-apptemplate:metadata:labels:app: payments-appspec:containers:- name: haproxyimage: haproxytech/haproxy-ubuntu:latestports:- containerPort: 443- containerPort: 80volumeMounts:- name: haproxy-confmountPath: /usr/local/etc/haproxy/haproxy.cfgsubPath: haproxy.cfg- name: example-tlsmountPath: /usr/local/etc/haproxy/sslvolumes:- name: haproxy-confconfigMap:name: haproxy-conf- name: example-tlssecret:secretName: example-tls---apiVersion: v1kind: Servicemetadata:name: payments-svcnamespace: defaultspec:selector:app: payments-apptype: NodePortports:- name: httpport: 80targetPort: 80- name: httpsport: 443targetPort: 443payments-svc.yamlyamlapiVersion: v1kind: ConfigMapmetadata:name: haproxy-confdata:haproxy.cfg: |globallog stdout format raw local0pidfile /var/run/haproxy.pidssl-load-extra-del-extssl-load-extra-files keydefaultslog globalmode httpoption httplogtimeout connect 5000timeout client 50000timeout server 50000frontend mysitebind :80bind :443 ssl crt /usr/local/etc/haproxy/ssl/tls.crthttp-request return status 200 content-type text/plain lf-string "Hello!"---apiVersion: apps/v1kind: Deploymentmetadata:name: payments-appnamespace: defaultspec:replicas: 1selector:matchLabels:app: payments-apptemplate:metadata:labels:app: payments-appspec:containers:- name: haproxyimage: haproxytech/haproxy-ubuntu:latestports:- containerPort: 443- containerPort: 80volumeMounts:- name: haproxy-confmountPath: /usr/local/etc/haproxy/haproxy.cfgsubPath: haproxy.cfg- name: example-tlsmountPath: /usr/local/etc/haproxy/sslvolumes:- name: haproxy-confconfigMap:name: haproxy-conf- name: example-tlssecret:secretName: example-tls---apiVersion: v1kind: Servicemetadata:name: payments-svcnamespace: defaultspec:selector:app: payments-apptype: NodePortports:- name: httpport: 80targetPort: 80- name: httpsport: 443targetPort: 443 -
Apply the changes with
kubectl:nixkubectl apply -f payments-svc.yamlnixkubectl apply -f payments-svc.yamloutputtextconfigmap/haproxy-conf createddeployment.apps/payments-app createdservice/payments-svc createdoutputtextconfigmap/haproxy-conf createddeployment.apps/payments-app createdservice/payments-svc created -
If you set the HAProxy Unified Gateway service to have a type of NodePort, then you can edit the service definition to set a different NodePort value. Otherwise, a random port is assigned.
nixkubectl edit service -n haproxy-unified-gateway haproxy-unified-gatewaynixkubectl edit service -n haproxy-unified-gateway haproxy-unified-gatewayThen change the
nodePortto the port you want to use. Here, we use31444:yaml- name: tls-31444nodePort: 31444port: 31444protocol: TCPtargetPort: 31444yaml- name: tls-31444nodePort: 31444port: 31444protocol: TCPtargetPort: 31444 -
Make a request on the worker node:
nixcurl -k -H "Host: payments.example.com" --resolve "payments.example.com:31444:127.0.0.1" https://payments.example.com:31444/nixcurl -k -H "Host: payments.example.com" --resolve "payments.example.com:31444:127.0.0.1" https://payments.example.com:31444/outputtextHello!outputtextHello!
Add a ReferenceGrant for cross-namespace service references Jump to heading
If your TLSRoute lists a Service under backendRefs that’s in a different namespace than the TLSRoute resource, you’ll need to define a ReferenceGrant resource to allow cross-namespace communication between the TLSRoute and the Service.
Below, we allow a TLSRoute 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: "TLSRoute"namespace: defaultto:- group: ""kind: "Service"
foo-referencegrant.yamlyamlapiVersion: gateway.networking.k8s.io/v1alpha2kind: ReferenceGrantmetadata:name: refgrantns1namespace: foospec:from:- group: "gateway.networking.k8s.io"kind: "TLSRoute"namespace: defaultto:- group: ""kind: "Service"
Apply the changes with kubectl:
nixkubectl apply -f foo-referencegrant.yaml
nixkubectl apply -f foo-referencegrant.yaml
See also Jump to heading
- Refer to the Gateway API’s TLSRoute documentation.