Skip to main content

Ingress-NGINX Is Dead. Gateway API v1.5 Is What You Migrate To — and It Finally Covers the Gaps

9 min readDora NodaDora Noda
Share
On this page

Six months ago, in March 2026, the most widely deployed Kubernetes ingress controller stopped receiving patches. Not deprecated, not maintenance mode — done. Kubernetes SIG Network and the Security Response Committee announced in November 2025 that Ingress NGINX would get best-effort maintenance until March 2026 and then nothing: no releases, no bugfixes, no security updates. Every cluster still routing edge traffic through it today is running an unmaintained proxy at the exact layer where the last big lesson — IngressNightmare, an unauthenticated remote-code-execution chain disclosed in March 2025 — cost a CVSS 9.8.

The good news is that the replacement stopped being a stopgap in the same window. Gateway API v1.5, released February 27, 2026, promoted six long-awaited features to the Standard channel — including stable TLSRoute, ListenerSet, and a native HTTPRoute CORS filter — and v1.6 followed on June 30 by graduating TCPRoute and UDPRoute. The gaps that used to force NGINX-specific annotations or a custom sidecar are now stable, conformance-tested APIs. This post maps each common annotation workaround to its stable replacement, lays out the now-mostly-mechanical migration path, and picks a default Gateway API implementation for a self-hosted fleet running on owned hardware.

The deadline already passed

The retirement notice, published November 11, 2025 during KubeCon North America in Atlanta, is unusually blunt for the Kubernetes project. Best-effort maintenance until March 2026; afterward, "no further releases, no bugfixes, and no updates to resolve any security vulnerabilities." Existing deployments keep functioning and installation artifacts remain available — your Ingress objects will not stop routing tomorrow — but the next vulnerability disclosure gets no fix, ever.

The cause was not a technical verdict on NGINX. It was maintainership collapse: for years the project ran on one or two people doing development in their spare time, and even the 2024 announcement of a planned successor (InGate, to be built with the Gateway API community) failed to attract new maintainers. InGate never matured and is being retired alongside its parent. SIG Network and the SRC recommend that all users "begin migration to Gateway API or another Ingress controller immediately."

The cost of ignoring that recommendation has a name and a number. On March 24, 2025, Wiz researchers disclosed IngressNightmare: CVE-2025-1974 (CVSS 9.8, unauthenticated RCE through the admission webhook) chained with three config-injection flaws (CVE-2025-1097, CVE-2025-1098, CVE-2025-24514, each 8.8), letting an attacker with pod-network access inject arbitrary NGINX configuration, read every secret in every namespace, and take over the cluster. The root cause was architectural — an unauthenticated admission controller that renders attacker-influenced input into NGINX config — not a typo. The next flaw of that shape, in a controller nobody patches, is a permanent zero-day on your edge.

The v1.5 payoff table: every annotation workaround, now a stable API

For years the honest objection to migrating was the feature gap: production Ingress NGINX setups lean on dozens of nginx.ingress.kubernetes.io/* annotations, and early Gateway API had no stable equivalent for several of them. Gateway API v1.5 (released February 27, 2026, announced April 21) closed that gap by promoting six features to the Standard (GA) channel. Here is what each one replaces:

What you hacked with NGINX annotationsNow stable in Gateway API v1.5Why stable matters
ssl-passthrough plus stream-snippet SNI tricks to pass TLS through to backendsTLSRoute v1 (GEP-2643)SNI-based L4 routing is a versioned API with conformance coverage instead of a boolean annotation whose semantics differ per controller version
One copy-pasted Gateway object per team, or shared-Gateway merge fightsListenerSet (GEP-1713)Teams attach their own listeners to a shared Gateway; listener ownership is declarative instead of a merge convention the platform team polices by hand
enable-cors plus a dozen cors-* annotations (origins, methods, headers, max-age)HTTPRoute CORS filter (GEP-1767)Cross-origin policy is route config the data plane enforces, portable across implementations instead of NGINX-only annotation strings
auth-tls-* annotation soup for client-certificate / mTLS verificationGateway client certificate validation (GEP-91, GEP-3567)mTLS verification moves from annotation folklore to a specified API with defined validation behavior
Cross-namespace backend references with no trust model (or out-of-band convention)ReferenceGrant v1The cross-namespace trust grant — "namespace B may route to my Service" — is GA, cementing the security story the whole route model depends on
Hand-picked certs for Gateway-originated upstream TLSCertificate selection for TLS origination (GEP-3155)Which certificate the Gateway presents upstream is explicit config, not implementation default behavior

And the window kept moving: Gateway API v1.6 (shipped June 30, 2026) graduated TCPRoute and UDPRoute to v1 on the Standard channel and deprecated their v1alpha2 shapes, so L4 routing for non-HTTP workloads no longer sits on an alpha API either. If your migration plan stalled in 2024 on "TLSRoute is alpha," that excuse has expired twice over.

Why Gateway API, not just another Ingress controller

Switching from Ingress NGINX to a maintained Ingress controller fixes the patching problem but re-buys the structural one: the Ingress API is HTTP-only and effectively frozen, so every feature beyond basic host/path routing arrives as a vendor-specific annotation with no portability and no conformance suite.

Gateway API inverts that. Infrastructure owners manage GatewayClass and Gateway (listeners, TLS mode, addresses) while developers own HTTPRoute/TLSRoute/TCPRoute attachments; traffic splitting, header matching, and filters are first-class fields; and implementations prove behavior against shared conformance profiles (the v1.6 suite now requires the GATEWAY-TCP and GATEWAY-UDP profiles, not just e2e spot checks). A route written against the Standard channel survives swapping the data plane underneath it — which is exactly the migration you are doing now, and exactly the one you never want to redo by hand again.

The migration is mechanical now

The tooling caught up with the API. Ingress2Gateway 1.0 (March 2026) expanded Ingress-NGINX annotation support from three annotations to more than thirty — CORS, backend TLS, regex matching, path rewrites — translating existing Ingress manifests plus annotations into Gateway + HTTPRoute YAML while warning about anything it cannot translate:

bash
go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers=ingress-nginx --input-file my-ingress.yaml

The recommended cutover avoids a flag day: install the chosen Gateway API implementation alongside Ingress NGINX, generate and review the translated routes, shift traffic gradually (DNS weight or a parallel front IP), and keep NGINX serving until the new data path is verified under real load. TLS automation ports cleanly — cert-manager ships a GA Gateway shim alongside its Ingress shim, so certificate issuance follows the same ClusterIssuer setup.

Be honest about the non-mechanical remainder, because it is where migrations stall. Anything living in configuration-snippet, server-snippet, or embedded Lua does not translate — ingress2gateway will flag it, but reimplementing custom auth logic, exotic regex rewrites, or bespoke buffering behavior as Gateway API filters (or an implementation extension) is real engineering. The correct first step is an annotation inventory: most fleets discover that 80% of their annotations are CORS, rewrites, and TLS settings that now map one-to-one onto stable fields, and the remaining 20% is a short, named list of snippets to rewrite deliberately. That list is the actual migration scope — everything else is codegen.

Which implementation for owned hardware

For a self-hosted fleet on bare metal or rented dedicated servers — no cloud load-balancer controller to lean on — the choice comes down to four serious options:

ImplementationData planeWhy pick itWhy not
Envoy Gateway (default)EnvoyCNCF project, maximum portability, strongest conformance story; ~325k qps in gateway-api-bench per Gardener's published comparisonSlightly slower config-update propagation than the eBPF options; another control plane to operate
Cilium GatewayeBPF / EnvoyFastest update times alongside Istio/Kong; zero extra proxy hop if Cilium is already your CNIRequires adopting Cilium as your CNI — a non-starter if you are on Calico/flannel and staying there
NGINX Gateway FabricNGINXSmallest mental-model jump for an NGINX shop; F5-backedYoungest implementation, weakest throughput in the field (~91k qps, second-slowest measured)
Traefik / kgatewayTraefik / EnvoyTraefik's Gateway provider is production-ready since v3.1 — the easy path if Traefik already terminates your edgeSmaller Gateway API conformance surface than the purpose-built options; evaluate against the profiles you need

The default recommendation is Envoy Gateway: it is the portable, vendor-neutral pick whose routes you can later move to any other conformant implementation — the entire point of migrating to a standard API. Deviate to Cilium when the fleet already runs Cilium networking, to NGINX Gateway Fabric when operator familiarity outweighs throughput headroom, and stay on Traefik's Gateway provider when Traefik is already your edge and its supported profile set covers your routes. Whichever you choose, verify against the published conformance reports for the profiles you need rather than the marketing matrix.

Migrate on your timeline, not the CVE's

The retirement deal is unusually forgiving as these things go: nothing breaks on its own, artifacts stay published, and the migration tooling is the best it has ever been. What you no longer get is the one thing an edge proxy exists to provide — a patched data path the next time someone finds an admission-controller-shaped hole in it. With TLSRoute, ListenerSet, CORS, client-cert validation, and ReferenceGrant all Standard, plus TCP/UDP routes graduated in v1.6 and thirty-plus annotations machine-translatable, "the successor isn't ready" stopped being true around February. The remaining work is an annotation inventory and a side-by-side cutover — weekend-sized for a small fleet, and strictly smaller than incident response on an unpatchable edge.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex