Gateway API statt Ingress
HTTPRoute, GatewayClass und schrittweise Migration.
von PlatPrep
Es fängt meistens mit einer kleinen Anforderung an. “Wir brauchen Header-basiertes Routing für unseren A/B-Test.” Du schaust in die Docs deines Ingress-Controllers und findest eine proprietäre Annotation. Funktioniert — bis die nächste Version des Controllers die Syntax ändert. Oder die Annotation existiert bei einem anderen Controller gar nicht.
Das ist das strukturelle Problem mit Ingress: ein minimalistisches API, das fast vollständig über Annotations erweitert wird. Jeder Controller hat seine eigene Annotations-Sprache. Portabilität ist eine Illusion.
Gateway API löst das durch ein durchdachteres Ressourcenmodell mit drei Ebenen: GatewayClass definiert, welche Controller-Implementierung zuständig ist. Gateway ist die konkrete Instanz — Listener, Ports, TLS-Konfiguration, und Regeln, welche Namespaces Routes anbinden dürfen. HTTPRoute beschreibt das eigentliche Routing und gehört den Anwendungsteams:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: checkout
namespace: team-checkout
spec:
parentRefs:
- name: shared-gateway
namespace: infra
hostnames:
- "shop.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /checkout
backendRefs:
- name: checkout
port: 8080
weight: 90
- name: checkout-canary
port: 8080
weight: 10
Hier stecken gleich zwei Dinge drin, die mit Ingress mühsam waren. Erstens das Ownership-Modell: Das Infra-Team betreibt den shared-gateway im infra-Namespace, das Checkout-Team pflegt seine Route im eigenen Namespace und hängt sie per parentRefs an. Kein zentrales Ingress-YAML mehr, an dem zehn Teams gleichzeitig herumeditieren. Der Gateway kontrolliert über allowedRoutes in der Listener-Konfiguration, wer andocken darf — etwa nur Namespaces mit einem bestimmten Label. Zweitens gewichtetes Traffic-Splitting als First-Class-Feature: 90/10 für ein Canary-Deployment, deklarativ, portabel über Implementierungen hinweg, ohne Controller-spezifische Annotations.
Header- und Query-Matching, URL-Rewrites, Request-Mirroring — was bei Ingress Annotation-Folklore war, ist in der HTTPRoute-Spec typisiert und validierbar. Falsch geschriebene Annotations scheitern leise; ein falsches Feld in einer HTTPRoute lehnt der API-Server ab. Das klingt nach einer Kleinigkeit, ist aber genau der Unterschied zwischen einem Tippfehler, der im Review auffällt, und einem, der erst im Produktions-Traffic auffällt.
Sicherheit über Namespace-Grenzen
Cross-Namespace-Referenzen sind in Gateway API bewusst nicht implizit erlaubt. Will eine Route auf einen Service in einem fremden Namespace zeigen, muss der Ziel-Namespace das per ReferenceGrant ausdrücklich gestatten — eine Ressource, die im Ziel-Namespace liegt und sagt: “HTTPRoutes aus Namespace X dürfen Services bei mir referenzieren.” Die Richtung ist entscheidend: Der Besitzer der Ressource erteilt die Erlaubnis, nicht der, der zugreifen will. Ohne Grant schlägt die Referenz fehl. Das klingt nach Bürokratie, verhindert aber eine reale Angriffsklasse: dass ein Team Traffic auf Services umbiegt, die ihm nicht gehören.
Beim Debugging hilft, dass Gateway API konsequent mit Status-Conditions arbeitet. Eine Route, die nicht greift, hat eine Accepted- oder ResolvedRefs-Condition mit Begründung — fehlende Permission, nicht auflösbarer Backend-Service, Hostname-Konflikt mit dem Listener. kubectl describe httproute beantwortet damit Fragen, für die man bei Ingress die Controller-Logs durchsuchen musste.
Auch TLS profitiert vom Schichtenmodell: Zertifikate hängen am Gateway-Listener und damit beim Infra-Team — Anwendungsteams müssen nie wieder Zertifikats-Secrets in ihre Namespaces kopieren. In Kombination mit cert-manager, der die Listener-Zertifikate automatisch ausstellt und rotiert, ist der gesamte TLS-Lebenszyklus aus den Team-Workflows verschwunden.
Migration: parallel statt Big Bang
Gateway API ist seit Version 1.0 GA; GatewayClass, Gateway und HTTPRoute sind stabile v1-Ressourcen. Wichtig zu verstehen: Die API wird als CRDs ausgeliefert und unabhängig vom Kubernetes-Release versioniert — die Implementierung liefert der Controller deiner Wahl, und nginx, Istio, Contour, Envoy Gateway und Cilium unterstützen Gateway API parallel zum klassischen Ingress. Genau das ermöglicht eine unaufgeregte Migration: beides gleichzeitig betreiben, unkritische Services zuerst umziehen, Erfahrungen sammeln, dann die kritischen. Für die mechanische Übersetzung bestehender Ingress-Ressourcen gibt es mit ingress2gateway ein offizielles Werkzeug — die Annotations-Spezialfälle muss man trotzdem von Hand prüfen, denn genau die waren ja nie portabel.
Zwei ehrliche Einschränkungen. Erstens unterscheiden sich Implementierungen darin, welche optionalen Features sie unterstützen — die Spec kennt Support-Level (Core, Extended, Implementation-specific), und ein weight-Split funktioniert überall, exotischere Filter nicht zwingend. Vor der Festlegung lohnt der Blick in die Conformance-Reports der Implementierung. Zweitens sind Nicht-HTTP-Routen (TCPRoute, UDPRoute, TLSRoute) noch nicht auf demselben Reifegrad — wer heute hauptsächlich rohe TCP-Passthroughs braucht, gewinnt durch die Migration wenig.
Für neue Cluster ist die Empfehlung trotzdem eindeutig: direkt mit Gateway API anfangen. Kein Annotation-Lock-in, klares Ownership-Modell, und Features wie Traffic-Splitting, die man früher dem Service Mesh überlassen musste — wobei für mTLS und feingranulare Traffic-Steuerung zwischen Services weiterhin ein Mesh wie Istio seinen Platz hat. Die Kubernetes-Networking-Grundlagen dazu vertieft der Kubernetes-Lernpfad.