Gateway API Support
Kamaji provides built-in support for the Gateway API, allowing you to expose Tenant Control Planes using TLSRoute resources with SNI-based routing. This enables hostname-based routing to multiple Tenant Control Planes through a single Gateway resource, reducing the need for dedicated LoadBalancer services.
Overview
Gateway API support in Kamaji automatically creates and manages TLSRoute resources for your Tenant Control Planes. When you configure a Gateway for a Tenant Control Plane, Kamaji automatically creates TLSRoutes for the Control Plane API Server. If konnectivity is enabled, a separate TLSRoute is created for it. Both TLSRoutes use the same hostname and Gateway resource, but route to different ports(listeners) using port-based routing and semantic sectionName values.
Therefore, the target Gateway resource must have right listener configurations (see the Gateway example section below).
How It Works
When you configure spec.controlPlane.gateway in a TenantControlPlane resource, Kamaji automatically:
- Creates a TLSRoute for the control plane that routes for port 6443 (or
spec.networkProfile.port) with sectionName"kube-apiserver" - Creates a TLSRoute for Konnectivity (if konnectivity addon is enabled) that routes for port 8132 (or
spec.addons.konnectivity.server.port) with sectionName"konnectivity-server"
Both TLSRoutes:
- Use the same hostname from
spec.controlPlane.gateway.hostname - Reference the same parent Gateway resource via
parentRefs - The
portandsectionNamefields are set automatically by Kamaji - Route to the appropriate Tenant Control Plane service
The Gateway resource must have listeners configured for both ports (6443 and 8132) to support both routes.
Prerequisites
Before using Gateway API support, ensure:
-
Gateway API CRDs are installed in your cluster (Required CRDs:
GatewayClass,Gateway,TLSRoute) -
A Gateway resource exists with appropriate listeners configured:
- At minimum, listeners for ports 6443 (control plane) and 8132 (Konnectivity)
- TLS protocol with Passthrough mode
- Hostname pattern matching your Tenant Control Plane hostnames
-
DNS is configured to resolve your hostnames to the Gateway's external address
-
Gateway controller is running (e.g., Envoy Gateway, Istio Gateway, etc.)
Configuration
TenantControlPlane Gateway Configuration
Enable Gateway API mode by setting the spec.controlPlane.gateway field in your TenantControlPlane resource:
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tcp-1
spec:
controlPlane:
# ... gateway configuration:
gateway:
hostname: "tcp1.cluster.dev"
parentRefs:
- name: gateway
namespace: default
additionalMetadata:
labels:
environment: production
annotations:
example.com/custom: "value"
# ... rest of the spec
deployment:
replicas: 1
service:
serviceType: ClusterIP
dataStore: default
kubernetes:
version: v1.29.0
kubelet:
cgroupfs: systemd
networkProfile:
port: 6443
certSANs:
- "c11.cluster.dev" # make sure to set this.
addons:
coreDNS: {}
kubeProxy: {}
konnectivity: {}
Required fields:
hostname: The hostname that will be used for routing (must match Gateway listener hostname pattern)parentRefs: Array of Gateway references (name and namespace)
Optional fields:
additionalMetadata.labels: Custom labels to add to TLSRoute resourcesadditionalMetadata.annotations: Custom annotations to add to TLSRoute resources
Port and sectionName are set automatically
Do not specify port or sectionName in parentRefs. Kamaji automatically sets these fields in TLSRoutes.
Gateway Resource Setup
Your Gateway resource must have listeners configured for both the control plane and Konnectivity ports. Here's an example Gateway configuration:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy-gw-class
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
namespace: default
spec:
gatewayClassName: envoy-gw-class
listeners:
- name: kube-apiserver
port: 6443
protocol: TLS
hostname: 'tcp1.cluster.dev'
tls:
mode: Passthrough
allowedRoutes:
kinds:
- group: gateway.networking.k8s.io
kind: TLSRoute
namespaces:
from: All
# if konnectivity addon is enabled:
- name: konnectivity-server
port: 8132
protocol: TLS
hostname: 'tcp1.cluster.dev'
tls:
mode: Passthrough
allowedRoutes:
kinds:
- group: gateway.networking.k8s.io
kind: TLSRoute
namespaces:
from: All
Multiple Tenant Control Planes
You can use the same Gateway resource for multiple Tenant Control Planes by using different hostnames:
# Gateway with wildcard hostname
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
spec:
listeners:
- hostname: '*.cluster.dev'
name: kube-apiserver
port: 6443
# ...
---
# Tenant Control Plane 1
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tcp-1
spec:
controlPlane:
gateway:
hostname: "tcp1.cluster.dev"
parentRefs:
- name: gateway
namespace: default
# ...
---
# Tenant Control Plane 2
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tcp-2
spec:
controlPlane:
gateway:
hostname: "tcp2.cluster.dev"
parentRefs:
- name: gateway
namespace: default
# ...
Each Tenant Control Plane will get its own TLSRoutes with the respective hostnames, all routing through the same Gateway resource.
You can check the Gateway status in the TenantControlPlane:
kubectl get tenantcontrolplane tcp-1 -o yaml
Look for the status.kubernetesResources.gateway and status.addons.konnectivity.gateway fields.