Gateway API: HTTPRoute + Gateway on eu-dev-rancher#
What This Covers#
Why Kubernetes Gateway API supersedes Ingress, how to set it up with Traefik, and how
to deploy a service (svc3) using HTTPRoute instead of Ingress. Also covers the
repo restructure that introduced platform/ as the home for shared cross-cutting config.
Why Gateway API?#
Ingress was designed for one simple use case - route HTTP(S) traffic to a backend by hostname or path. Any feature beyond that required controller-specific annotations, making configurations non-portable and hard to read.
Gateway API introduces a layered model:
| |
| Resource | Who owns it | What it does |
|---|---|---|
GatewayClass | Cluster admin | Binds a controller (e.g. Traefik) to this class |
Gateway | Infra team | Declares a listener (port, protocol, TLS) |
HTTPRoute | App team | Defines routing rules: host, path, headers → backend |
Key improvements over Ingress:
- No annotations - features like redirects, header matching, and URL rewrites are first-class fields, not controller-specific annotations
- Native traffic splitting -
backendRefswithweightper backend; no CRD hacks - Cross-namespace routing -
HTTPRouteinalpha-devcan attach to aGatewayiningressnamespace; controlled viaallowedRoutes - Role separation -
GatewayandHTTPRouteare separate RBAC targets; platform team owns the Gateway, app team owns the route
Ingress vs HTTPRoute side by side#
svc1 - Ingress (existing)
| |
svc3 - HTTPRoute (Gateway API)
| |
sectionName: web replaces the traefik.ingress.kubernetes.io/router.entrypoints: web
annotation. Portable, readable, no controller knowledge required.
Repo Structure#
New platform/ directory#
This session also formalised the distinction between shared config and per-cluster config,
replacing the old config/ folder with platform/:
| |
Rule: platform/ holds resources that are identical across all clusters. Per-cluster
resources (a Gateway with a specific namespace and listener config) go under
environments/<cluster>/.
Gateway API layout in eu-dev-rancher#
| |
gateway-api-config is a multi-source Application - it combines the shared
GatewayClass from platform/gateway-api with the env-specific Gateway from
environments/eu-dev-rancher/gateway-api in a single sync:
| |
Wave Ordering (updated)#
| |
Gateway API CRDs land at wave 1 - before Traefik starts - so the
kubernetesGateway provider can register on startup without needing a restart.
Key Config Changes#
Traefik - enable Gateway API provider#
| |
Without this, Traefik silently ignores all Gateway and HTTPRoute resources.
Gateway - allow cross-namespace routes#
| |
from: All lets HTTPRoute resources in alpha-dev attach to this Gateway in
ingress. Without it, only routes in the same namespace can attach.
Verification#
| |
Gotchas#
GatewayClass must use the correct controllerName
For Traefik v3 the value is traefik.io/gateway-controller. In Traefik v2 it was
different. If the GatewayClass stays in status Waiting, this is the first thing to
check - Traefik is not claiming the class.
Gateway API CRDs must be installed before Traefik starts
If Traefik starts before the CRDs exist, the Gateway API provider fails to initialise and routes are silently ignored. Sync wave 1 for CRDs and wave 2 for Traefik ensures correct ordering.
sectionName must match the listener name exactly
The sectionName: web in an HTTPRoute’s parentRef must match the listener name
field in the Gateway spec. Traefik maps listener names to its internal entrypoint
names (also called web). Mismatch = route is not attached, no traffic flows, no error
visible from the service side.
allowedRoutes.namespaces.from: All is required for cross-namespace routing
Without this, the Gateway only accepts routes from its own namespace (ingress).
Services in alpha-dev will show as not attached. No error is surfaced on the HTTPRoute
itself - the route just silently fails to attach.
ingress.enabled must be set to false
If both ingress.enabled: true and httpRoute.enabled: true are set, both resources
are created. Having duplicate routes for the same hostname is legal but confusing. Set
ingress.enabled: false explicitly when switching to HTTPRoute.