How it works
The explanation, with examples you can run.
Ingress: simple and frozen
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: webspec: ingressClassName: example # which controller handles it tls: - hosts: [shop.example.com] secretName: shop-tls rules: - host: shop.example.com http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80Ingress covers hosts, paths and TLS. Everything else (timeouts, header rewrites, traffic splitting, rate limits) was added through controller-specific annotations, so Ingress manifests are rarely portable. The API is now frozen: generally available and staying, but not getting new features.
Two recent changes matter here. The Kubernetes docs now recommend Gateway over Ingress. And in November 2025 SIG Network and the Security Response Committee announced the retirement of the community ingress-nginx controller, long the default choice: best-effort maintenance continued until March 2026, after which there are no new releases or security fixes. Existing installs keep working, but they should be migrated to a maintained controller, ideally a Gateway API implementation.
Gateway API: roles and routes
Gateway API v1.0 went GA in October 2023 and is developed outside the core release as CRDs (gateway.networking.k8s.io) that you install, often bundled with the implementation. It splits one Ingress into objects owned by different people:
apiVersion: gateway.networking.k8s.io/v1kind: Gateway # platform team: the entry pointmetadata: name: public namespace: infraspec: gatewayClassName: example # which implementation listeners: - name: https protocol: HTTPS port: 443 hostname: "*.example.com" tls: mode: Terminate certificateRefs: - name: wildcard-tls allowedRoutes: namespaces: from: All---apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoute # app team: their hostname and backendsmetadata: name: web namespace: shopspec: parentRefs: - name: public namespace: infra hostnames: ["shop.example.com"] rules: - matches: - path: { type: PathPrefix, value: / } backendRefs: - name: web port: 80 weight: 90 - name: web-canary port: 80 weight: 10- GatewayClass names an implementation, like
ingressClassName. - Gateway declares listeners: ports, protocols, hostnames, certificates, and which namespaces may attach routes.
- HTTPRoute (and GRPCRoute, plus TLS, TCP and UDP routes in various channels) attaches to a Gateway and maps matches (paths, headers, methods) to backends, with weights, redirects, rewrites and header changes as portable fields instead of annotations.
The split lets a platform team control TLS and exposure while app teams change their own routes in their own namespaces, and the same route can usually move between implementations unchanged.
Choosing
- New clusters: pick a conformant Gateway API implementation (check the project's implementations page) and use HTTPRoute.
- Existing Ingress: inventory annotations, which are the hard part to translate; the
ingress2gatewaytool converts the common cases. - Either way, the controller is critical production software: run several replicas, give it resource requests, and watch its error and latency metrics.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.