K8S Gateway API
I reproduce this conversation I had with Claude after switching our very nicely structured K8S cluster to Gateway API, in case it helps anyone else understand the topic better. Yes, I have read the official docs.
Question: so the only real top-level change with gateway API is an expressive complex format,
that we can query with kubectl describe gateway as opposed to k describe <a whole lot of ingresses - where a lot of the nitty gritty is hidden in the nginx confs>? The control plane shape is the same.
⏺ Mostly correct, with three substantive nuances worth naming:
-
VALIDATION - Typed schema vs string annotations. That's not just expressiveness — it's admission-time validation. ingress-nginx silently ignored a typo'd annotation; with Gateway API, an invalid CORS filter or BackendTLSPolicy is rejected at apply time and shows up in status.conditions. Less "wonder why this didn't work" debugging.
-
GATEWAY AS A FIRST CLASS OPS OBJECT - Role separation. With Ingress, the whole resource — TLS, host, backends, annotations — was one object usually owned by the app team. With Gateway API, the Gateway (listeners, certs, NLB
annotations) is naturally an ops object in gateway-system, and per-app teams only own HTTPRoutes in their namespace pointing at it. We exploited this: TLS Certificates centralised in
gateway-system/certificates.yaml, app charts stay focused on routing and per-route filters. That's why the cleanup was tractable — the boundary was clear. -
ROUTE TYPE VISIBILITY - More route kinds, cross-namespace as a first-class concept. We already use GRPCRoute and BackendTLSPolicy for end-to-end TLS — neither has a clean
ingress-nginx equivalent. And parentRef from any namespace into the central Gateway is built into the spec rather than implied by sharing an IngressClass.
So: data plane shape unchanged, controller pattern unchanged (watch → render nginx.conf → reload), and yes, you can kubectl describe gateway to see the listener-level state. But the API
gained validation, role separation, and a small genuine functional surface (gRPC, backend TLS) that we're using.