Usage

Define Gateways for HAProxy Unified Gateway

Gateways are Kubernetes resources that receive traffic from outside the cluster and, working in conjunction with Route resources, direct the traffic to the correct services running inside the cluster. A Gateway is backed by a proxy and when you set the gatewayClassName field to haproxy, it will be backed by the HAProxy Unified Gateway controller as the proxy technology.

Prerequisites checklist Jump to heading

Before continuing, ensure that you’ve met these prerequisites:

Add listeners Jump to heading

When you define a Gateway, you set the types of traffic it can receive. To do so, configure one or more listeners, each specifying the application protocol it accepts. For example, here’s a partial snippet where we define listeners for HTTP, HTTPS, and TLS-protected TCP traffic. Later, we’ll see how to define these sections fully.

gateway.yaml
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-haproxy-gateway
namespace: default
spec:
gatewayClassName: haproxy
listeners:
- name: http-listener
protocol: HTTP
...
- name: https-listener
protocol: HTTPS
...
- name: tls-listener
protocol: TLS
...
gateway.yaml
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-haproxy-gateway
namespace: default
spec:
gatewayClassName: haproxy
listeners:
- name: http-listener
protocol: HTTP
...
- name: https-listener
protocol: HTTPS
...
- name: tls-listener
protocol: TLS
...

Let’s briefly consider these fields:

Field Description
apiVersion The version of the Gateway API schema to use.
kind The kind of resource to instantiate. Here, it’s Gateway.
name The name of the Gateway, which Route resources will use to refer to this Gateway.
namespace The Kubernetes namespace to deploy this Gateway into.
gatewayClassName The Gateway’s class. The class maps to the HAProxy Unified Gateway controller.
listeners A list of endpoints that accept traffic. Each sets a protocol, address, port, and other attributes.
name A name for the listener, which will appear in logs.
protocol A protocol type for the listener.

The next sections describe how to define each type of listener.

Listen for HTTP traffic Jump to heading

When you add an HTTP listener, HAProxy Unified Gateway creates a proxy (in HAProxy terminology, a frontend) that accepts HTTP traffic. To define a listener that accepts HTTP traffic:

  1. Add a listener that has its protocol set to HTTP.

    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: http-listener
    protocol: HTTP
    port: 31080
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Same
    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: http-listener
    protocol: HTTP
    port: 31080
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Same

    In this example, the listener named http-listener sets these fields:

    Field Description
    protocol HTTP means that it will accept cleartext HTTP/1.1 traffic.
    port Sets the HTTP port to 31080. HAProxy Unified Gateway will dynamically publish this port on its Service resource. If you set the Service’s type to be NodePort, then a random NodePort value will be assigned.
    allowedRoutes Restricts the kinds of Route resources that can connect to this listener. Here, we’ve configured it to accept only HTTPRoute resources that are defined in the same namespace. You can also allow routes from other namespaces.
  2. Apply the changes with kubectl:

    nix
    kubectl apply -f gateway.yaml
    nix
    kubectl apply -f gateway.yaml
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway created
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway created
  3. You should now see that the HAProxy Unified Gateway service has published port 31080.

    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31080:31722/TCP 5m54s
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31080:31722/TCP 5m54s
  4. Define one or more HTTPRoute resources that utilize the listener.

Listen for HTTPS traffic Jump to heading

When you add an HTTPS listener, HAProxy Unified Gateway creates a proxy (in HAProxy terminology, a frontend) that accepts HTTPS traffic. Clients connect via HTTPS; HAProxy Unified Gateway will terminate the TLS connection and then relay the request to the backend service over plaintext HTTP.

To define a listener that accepts HTTPS traffic:

  1. On Linux, you can generate a self-signed TLS certificate for the domain example.com with this command:

    nix
    openssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=example.com" -days 365
    nix
    openssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=example.com" -days 365
  2. Use the kubectl create secret command to store your TLS certificate and key in the Kubernetes cluster:

    nix
    kubectl create secret tls example-tls --cert=tls.crt --key=tls.key
    nix
    kubectl create secret tls example-tls --cert=tls.crt --key=tls.key
  3. Add a listener that has its protocol set to HTTPS. Under the tls section, set mode to Terminate and specify the TLS secret to terminate the TLS connection on the frontend and relay the request to the backend service as decrypted HTTP.

    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: https-listener
    protocol: HTTPS
    port: 31443
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Same
    tls:
    mode: Terminate
    certificateRefs:
    - name: example-tls
    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: https-listener
    protocol: HTTPS
    port: 31443
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Same
    tls:
    mode: Terminate
    certificateRefs:
    - name: example-tls

    In this example, the listener named https-listener sets these fields:

    Field Description
    protocol HTTPS means that it will accept HTTP/2 traffic protected by TLS.
    port Sets the HTTPS port to 31443. HAProxy Unified Gateway will dynamically publish this port on its Service resource. If you set the Service’s type to be NodePort, then a random NodePort value will be assigned.
    allowedRoutes Restricts the kinds of Route resources that can connect to this listener. Here, we’ve configured it to accept only HTTPRoute resources that are defined in the same namespace. You can also allow routes from other namespaces.
    tls Sets mode to Terminate and references a TLS secret named example-tls. Note that you cannot use a mode of Passthrough when protocol is HTTPS.
  4. Apply the changes with kubectl:

    nix
    kubectl apply -f gateway.yaml
    nix
    kubectl apply -f gateway.yaml
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway configured
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway configured
  5. You should now see that the HAProxy Unified Gateway service has published port 31443.

    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31443:31038/TCP 12m
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31443:31038/TCP 12m
  6. Define one or more HTTPRoute resources that utilize the listener.

Listen for TLS traffic Jump to heading

When you add a TLS listener, HAProxy Unified Gateway creates a proxy (in HAProxy terminology, a frontend) that accepts TCP traffic encrypted by TLS. HAProxy Unified Gateway will relay the encrypted TCP stream to the backend service without decrypting it, preserving end-to-end encryption to the backend service.

To define a listener that accepts TLS-encrypted TCP traffic:

  1. Add a listener that has its protocol set to TLS. Under the tls section, set mode to Passthrough.

    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: tls-listener
    protocol: TLS
    port: 31444
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: TLSRoute
    namespaces:
    from: Same
    tls:
    mode: Passthrough
    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: tls-listener
    protocol: TLS
    port: 31444
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: TLSRoute
    namespaces:
    from: Same
    tls:
    mode: Passthrough

    In this example, the listener named tls-listener sets these fields:

    Field Description
    protocol TLS means that it will accept TLS sessions over TCP.
    port Sets the TLS port to 31444. HAProxy Unified Gateway will dynamically publish this port on its Service resource. If you set the Service’s type to be NodePort, then a random NodePort value will be assigned.
    allowedRoutes Restricts the kinds of Route resources that can connect to this listener. Here, we’ve configured it to accept only TLSRoute resources that are defined in the same namespace. You can also allow routes from other namespaces.
    tls Sets mode to Passthrough to indicate that the TLS session isn’t terminated by the Gateway.
  2. Apply the changes with kubectl:

    nix
    kubectl apply -f gateway.yaml
    nix
    kubectl apply -f gateway.yaml
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway configured
    output
    text
    gateway.gateway.networking.k8s.io/example-haproxy-gateway configured
  3. You should now see that the HAProxy Unified Gateway service has published port 31444.

    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    nix
    kubectl get svc -n haproxy-unified-gateway haproxy-unified-gateway
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31444:32190/TCP 15m
    output
    text
    NAME PORT(S) AGE
    haproxy-unified-gateway ... 31024:31103/TCP,31060:32387/TCP,31444:32190/TCP 15m
  4. Define one or more TLSRoute resources that utilize the listener.

Allow routes from other namespaces Jump to heading

When you set allowedRoutes.namespaces.from to Same, as we’ve done in previous examples, then the Gateway will accept only Route resources defined in the same namespace as the Gateway. It will ignore others. This is best when you want to deploy a Gateway to a namespace and have it handle traffic for services in that namespace only. However, 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, use a selector:

  1. When defining your namespace, add a label. In this example, we set a label named shared-gateway-access.

    namespace.yaml
    yaml
    apiVersion: v1
    kind: Namespace
    metadata:
    name: example-namespace
    labels:
    shared-gateway-access: "true"
    namespace.yaml
    yaml
    apiVersion: v1
    kind: Namespace
    metadata:
    name: example-namespace
    labels:
    shared-gateway-access: "true"
  2. On the Gateway, set namespaces.from to Selector. Also, define the selector. In the example below, the selector uses matchLabels to indicate that only HTTPRoute resources defined in namespaces with the label shared-gateway-access set to true will be used.

    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: http
    protocol: HTTP
    port: 31080
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Selector
    selector:
    matchLabels:
    shared-gateway-access: "true"
    gateway.yaml
    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: example-haproxy-gateway
    namespace: default
    spec:
    gatewayClassName: haproxy
    listeners:
    - name: http
    protocol: HTTP
    port: 31080
    allowedRoutes:
    kinds:
    - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespaces:
    from: Selector
    selector:
    matchLabels:
    shared-gateway-access: "true"

See also Jump to heading

Do you have any suggestions on how we can improve the content of this page?