Skip to content

GatewayClass

HAPTIC creates a GatewayClass resource automatically when the gateway library is enabled, gatewayClass.enabled is true, and the cluster serves the gatewayclasses CRD. The controller emits it at runtime through the gateway library's k8sResources, not the Helm chart — so it appears (or disappears) as the CRDs come and go, without a helm upgrade.

Prerequisites

For the GatewayClass to appear, install the Gateway API CRDs (standard channel):

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.0/standard-install.yaml

Check Gateway API releases for newer versions.

The v1.6.0 standard channel ships every route kind HAPTIC supports — HTTPRoute, GRPCRoute, TLSRoute, and TCPRoute. On older Gateway API releases some kinds live only in the experimental channel (experimental-install.yaml): TLSRoute before v1.5 and TCPRoute before v1.6. See Supported Gateway API versions and channels for the full split.

If the CRDs are absent, nothing is emitted and the rest of the install proceeds normally. Install the CRDs later and the controller creates the GatewayClass by itself — no helm upgrade required.

Expose a Service through a Gateway

This quickstart routes a test hostname to a sample app through a Gateway and an HTTPRoute — the Gateway API counterpart to the Ingress walkthrough. It assumes HAPTIC is installed (see Getting started — Install with Helm) and the Gateway API CRDs are installed (see Prerequisites above), which together create the haptic GatewayClass.

Step 1: Deploy a sample application

Create an echo Deployment and Service in the default namespace:

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
        - name: echo
          image: ealen/echo-server:latest
          ports:
            - containerPort: 80
          env:
            - name: PORT
              value: "80"
---
apiVersion: v1
kind: Service
metadata:
  name: echo
  namespace: default
spec:
  selector:
    app: echo
  ports:
    - port: 80
      targetPort: 80
EOF

Step 2: Create a Gateway

Create a Gateway that references the haptic GatewayClass and opens an HTTP listener on port 80:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: edge
  namespace: default
spec:
  gatewayClassName: haptic
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same
EOF

The listener's allowedRoutes.namespaces.from: Same lets routes in the Gateway's own namespace (default) attach. HAPTIC serves Gateway listeners on the chart-static HTTP port (haproxy.ports.http, default 80) through the shared HAProxy pods, so no per-Gateway address is needed to test locally.

Step 3: Create an HTTPRoute

Attach an HTTPRoute to the Gateway that forwards echo.example.local to the echo Service:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: echo
  namespace: default
spec:
  parentRefs:
    - name: edge
  hostnames:
    - echo.example.local
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: echo
          port: 80
EOF

The controller detects the Gateway and HTTPRoute, renders the HAProxy configuration, and deploys it to the HAProxy pods.

Step 4: Test the routing

Port-forward to the shared HAProxy Service and send a request with the route's hostname:

kubectl port-forward -n haptic svc/haptic-haproxy 8080:80

In another terminal:

curl -H "Host: echo.example.local" http://localhost:8080/

You receive a response from the echo server. Confirm the controller wrote Accepted and Programmed conditions back to the Gateway:

kubectl get gateway edge -n default -o yaml

For every route type (HTTP, gRPC, TLS, TCP), listener option, and status condition, see the Gateway API library.

Configuration

controller:
  templateLibraries:
    gateway:
      enabled: true

gatewayClass:
  enabled: true
  name: haptic
  default: false
  controllerName: haproxy-haptic.org/controller
  parametersRef:
    group: haproxy-haptic.org
    kind: HAProxyTemplateConfig
    name: ""        # Defaults to controller.configName
    namespace: ""   # Defaults to Release.Namespace

Creation conditions

The GatewayClass exists only when all the following are true. Conditions 1 and 2 are chart-time; condition 3 is re-evaluated by the controller at runtime:

  1. gatewayClass.enabled: true (default)
  2. controller.templateLibraries.gateway.enabled: true (default)
  3. The cluster serves the gateway.networking.k8s.io gatewayclasses CRD

If the API is absent, nothing is emitted and the rest of the install proceeds normally. Because condition 3 is a runtime check, installing the CRDs later is enough — the controller notices and creates the GatewayClass.

The GatewayClass automatically references the HAProxyTemplateConfig created by this chart via parametersRef. The reference records which HAProxyTemplateConfig drives Gateways of this class — useful when you run several classes with different configs.

How it works:

  1. GatewayClass points to HAProxyTemplateConfig via spec.parametersRef
  2. Controller reads HAProxyTemplateConfig for template snippets, maps, watched resources, and HAProxy configuration
  3. Gateway API consumers get the same routing capabilities as Ingress consumers

Default behavior:

  • parametersRef.name defaults to controller.configName (typically haptic-config)
  • parametersRef.namespace defaults to chart's release namespace

Inspect the reference:

kubectl get gatewayclass haptic -o yaml

Multi-controller environments

When running multiple Gateway API controllers:

Ensure unique identification:

# Controller 1 (haptic)
gatewayClass:
  name: haptic
  controllerName: haproxy-haptic.org/controller

# Controller 2 (nginx-gateway-fabric)
gatewayClass:
  name: nginx
  controllerName: gateway.nginx.org/nginx-gateway-controller

Only one should be default:

# Set default on one controller only
gatewayClass:
  default: true  # Only on ONE controller

Advanced: Multiple GatewayClasses

You can create multiple GatewayClasses pointing to different HAProxyTemplateConfig resources for different routing scenarios (for example internet-facing vs internal):

# Install chart with default config
helm install haproxy-internet oci://registry.gitlab.com/haproxy-haptic/haptic/charts/haptic --version 0.2.0-alpha.1

# Create separate HAProxyTemplateConfig for internal traffic with different templates
kubectl apply -f - <<EOF
apiVersion: haproxy-haptic.org/v1alpha1
kind: HAProxyTemplateConfig
metadata:
  name: haproxy-internal-config
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: haproxy-internal
  # ... different template configuration ...
EOF

# Create additional GatewayClass pointing to the internal config
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: haproxy-internal
spec:
  controllerName: haproxy-haptic.org/controller
  parametersRef:
    group: haproxy-haptic.org
    kind: HAProxyTemplateConfig
    name: haproxy-internal-config
    namespace: default
EOF

Using GatewayClass

Gateway resources opt in to HAPTIC by referencing the class via spec.gatewayClassName; routes then attach to the Gateway via spec.parentRefs:

spec:
  gatewayClassName: haptic  # References GatewayClass.metadata.name

For the supported route types (HTTP, gRPC, TLS, TCP) and worked examples, see the Gateway API library.

Disabling GatewayClass creation

If you manage GatewayClass resources separately:

gatewayClass:
  enabled: false

See also

Found a problem on this page? Report it or edit the page with the pencil icon above the title.