Ingress-NGINX retired in March 2026: the Gateway API migration plan for 30 annotations
Summary. The deadline is not coming. It passed. Kubernetes SIG Network and the Security Response Committee retired Ingress-NGINX in March 2026, and since then there have been no releases, no bugfixes, and no patches for any security vulnerability discovered. The GitHub repositories are read-only. Your cluster did not break, which is exactly the problem: existing deployments keep working, so nothing tells you that you are now running an unmaintained edge proxy. Kat Cosgrove of the Kubernetes Steering Committee put the scale of it plainly in the January 2026 joint statement: "In March 2026, Kubernetes will retire Ingress NGINX, a piece of critical infrastructure for about half of cloud native environments." That 50% figure is attributed in the statement to internal Datadog research, against a project maintained "solely by one or two people working in their free time." Precedent for what unpatched means here: CVE-2025-1974, disclosed on 24 March 2025, let attackers take over a cluster, and at the time Kubernetes said over 40% of administrators ran the affected component. A fix existed then, in v1.12.1 and v1.11.5. The next one will not. The good news is that the tooling caught up: ingress2gateway 1.0 shipped on 20 March 2026 and now converts over 30 Ingress-NGINX annotations, up from three, and Gateway API v1.5 promoted six features to Standard on 27 February 2026. Here is the migration, including the annotations that will not convert.
First, find out whether you are affected
Run this with cluster administrator permissions. It is the check the Kubernetes Steering Committee published:
kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx
Empty output means you are probably clear. Any pods means you are running retired software at the edge of your cluster, terminating your TLS.
The committee's warning about detection is the part worth internalising: "Existing deployments will continue to work, so unless you proactively check, you may not know you are affected until you are compromised." There is no crash, no failed rollout, no alert. The failure mode is silence followed by an incident.
What retirement actually means
| Thing | Status after March 2026 |
|---|---|
| Existing deployments | Continue to function, unchanged |
| Helm charts and container images | Remain available |
| GitHub repositories | Read-only, kept for reference |
| New releases | None |
| Bugfixes | None |
| Security patches | None, for any vulnerability discovered |
| InGate, the intended successor | Also retired, never reached maturity |
That last row surprises people. The maintainers had announced a plan to wind down Ingress-NGINX and build a replacement controller with the Gateway API community. The retirement post is direct about how that went: InGate "development never progressed far enough to create a mature replacement; it will also be retired." There is no successor controller waiting for you. There is a different API.
Why it happened
Two reasons, and the second one is the one to learn from.
The staffing reason is stark. Despite Ingress-NGINX running roughly half of cloud native environments, "for the last several years, it has been maintained solely by one or two people working in their free time." SIG Network says it exhausted its efforts to find additional support.
The design reason is more interesting to anyone building infrastructure. From the retirement announcement: "What were once considered helpful options have sometimes come to be considered serious security flaws, such as the ability to add arbitrary NGINX configuration directives via the 'snippets' annotations. Yesterday's flexibility has become today's insurmountable technical debt."
That is the sentence to sit with. The feature that made Ingress-NGINX universally adoptable, letting anyone inject arbitrary config through an annotation, is the feature that made it unfixable. The January statement is blunter still: "With the technical debt that has piled up, and fundamental design decisions that exacerbate security flaws, it is no longer reasonable or even possible to continue maintaining the tool even if resources did materialize."
Set your expectations for the migration accordingly. Cosgrove's warning is the one that governs your planning estimate: "None of the available alternatives are direct drop-in replacements. This will require planning and engineering time."
Step 1: inventory your annotations
Before you run any tool, find out what you are actually using. Annotations are where the work is, not the routing rules.
kubectl get ingress --all-namespaces -o json \
| jq -r '.items[].metadata.annotations // {} | keys[]' \
| grep '^nginx.ingress.kubernetes.io/' \
| sort | uniq -c | sort -rn
You now have a ranked list of every Ingress-NGINX annotation in your estate and how often each appears. Two things to look for immediately. Any configuration-snippet or server-snippet is a red flag, because those are the arbitrary-config escape hatch that will not convert and that caused this whole situation. Anything appearing once or twice is probably a workaround somebody added during an incident that nobody has revisited.
Step 2: run ingress2gateway 1.0
ingress2gateway is the official SIG Network migration assistant, written by Beka Modebadze of Google and Steven Jin of Microsoft. Version 1.0, released 20 March 2026, is the release that makes this practical: before it, the tool supported three Ingress-NGINX annotations. It now supports over 30 common annotations, including CORS, backend TLS, regex matching and path rewriting.
Install it:
go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0
# or
brew install ingress2gateway
Run it against manifests, a namespace, or the whole cluster:
# From files
ingress2gateway print --input-file my-manifest.yaml,my-other-manifest.yaml --providers=ingress-nginx > gwapi.yaml
# From one namespace
ingress2gateway print --namespace my-api --providers=ingress-nginx > gwapi.yaml
# From the entire cluster
ingress2gateway print --providers=ingress-nginx --all-namespaces > gwapi.yaml
You can add --emitter <agentgateway|envoy-gateway|kgateway> to emit implementation-specific extensions, which matters for a few annotations that standard Gateway API has no equivalent for.
What you get back is a Gateway plus HTTPRoutes. What you should actually read is the warnings.
Step 3: read the warnings, not the YAML
The tool's authors are explicit that this is not a conversion button. "Ingress2Gateway is a migration assistant, not a one-shot replacement," and "Migration is not a 'one-click' affair." On reviewing the output they are firmer: "This is the most critical step."
Here is what the tool does with a realistic annotation set, taken from the release announcement's own worked example.
| Ingress-NGINX annotation | What ingress2gateway 1.0 does | What you must do |
|---|---|---|
enable-cors |
Converts cleanly to a Gateway API CORS filter | Nothing |
use-regex with a regex path |
Converts, but emits (?i)/users/(\d+).*
|
Decide whether you want case-insensitive prefix matching |
proxy-read-timeout / proxy-send-timeout
|
Best-effort translation to timeouts.request
|
Verify the value; Ingress-NGINX timeouts are TCP-level |
proxy-body-size |
Not translated, no Gateway API equivalent | Check your implementation's defaults, or use an emitter |
configuration-snippet |
Refuses; emits an unsupported-annotation warning | Rebuild the behaviour, or drop it |
The regex one is the trap. Ingress-NGINX regex matches are case-insensitive prefix matches, so the tool faithfully reproduces that as (?i)/users/(\d+).*. That is correct, and it is almost certainly not what you want. The release notes say so: most organisations will want an exact case-sensitive match, removing the leading (?i) and the trailing .*. If you apply the generated YAML without reading it, you have just carried a decade of accidental matching semantics into your new stack and made it permanent.
Two more warnings worth knowing about before you see them:
URL normalization. Gateway API has no standard way to configure it. Agentgateway, Envoy Gateway, kgateway and Istio each normalize differently and none of it is configurable through the standard API. If any of your routing or authorisation depends on path normalization, test it explicitly. This is a real behavioural difference between implementations, not a footnote.
The HTTP listener. To match Ingress-NGINX's default behaviour, the tool adds a port 80 listener and an HTTPRoute with a 308 redirect to HTTPS. If you never wanted to serve plain HTTP, delete both.
Step 4: handle what will not convert
Three categories, in descending order of how much time they will cost you.
Snippets. configuration-snippet and server-snippet inject raw NGINX config. Gateway API deliberately has no equivalent, because that escape hatch is precisely what got Ingress-NGINX retired. For each snippet, ask what it actually does. Header manipulation usually maps to an HTTPRoute filter. Rate limiting, auth and WAF rules map to your chosen implementation's policy CRDs. Some of it will turn out to be dead config from 2021 that you can delete, and you should check for that first, because it is the cheapest possible outcome.
Body size. proxy-body-size has no standard equivalent. The tool's own warning notes that most Gateway API implementations have reasonable body size and buffering defaults, so this may be a non-issue. If you genuinely need 1 GB uploads, use --emitter to generate implementation-specific config and verify it under load.
TCP-level timeouts. Ingress-NGINX only supports TCP-level timeouts, so the translation to a Gateway API request timeout is approximate by nature. The tool defaults conservatively. Set the value you actually want.
Step 5: shift traffic without an outage
The official guidance is a parallel run, and it is right. Do not cut over.
Deploy your Gateway API configuration alongside the existing Ingress. Both can serve simultaneously. Then shift traffic gradually using weighted DNS, your cloud load balancer, or your platform's traffic-splitting features, so that a misconfiguration that survived testing is recoverable in minutes rather than being your Monday. Only when all traffic has moved should you delete the Ingress resources and uninstall the controller.
Test in a development cluster first, and test the specific things the warnings flagged: your body size defaults, your timeout values, your regex semantics, your normalization behaviour. The generated YAML being valid tells you nothing about whether it behaves like your old stack.
One cost note that catches teams late. A single Ingress-NGINX controller typically sits behind one load balancer. Gateway API's model encourages a Gateway per team or per environment, and each Gateway usually provisions its own cloud load balancer. On AWS, Elastic Load Balancing charges for every hour each load balancer runs plus $0.008 per Load Balancer Capacity Unit-hour, so ten Gateways is ten load balancers on the bill, not one. Gateway API v1.5's ListenerSet is the answer if this bites: it lets separate teams attach listeners to one shared Gateway from their own namespaces, and it raises the ceiling above the 64-listener limit that a single Gateway otherwise imposes.
What Gateway API v1.5 gives you
Gateway API v1.5 was released on 27 February 2026, described by SIG Network as "our biggest release yet," and it concentrated on promoting existing Experimental features to Standard. Six features moved to the Standard channel.
| Feature | GEP | What it solves |
|---|---|---|
| ListenerSet | GEP-1713 | Teams attach listeners to a shared Gateway from their own namespaces; breaks the 64-listener ceiling |
| TLSRoute | GEP-2643 | SNI-based routing, in Passthrough or Terminate mode |
| HTTPRoute CORS filter | GEP-1767 | CORS as a first-class filter, including wildcard origins like https://*.bar.com
|
| Client certificate validation | GEP-91 | Frontend mTLS via frontendValidation
|
| Certificate selection for TLS origination | GEP-3155 | Gateway presents a client cert to backends via tls.backend.clientCertificateRef
|
| ReferenceGrant | promoted to v1 | Now under the GA contract: no breaking changes |
There is one upgrade hazard in that list, and it is easy to trip. If you install Gateway API v1.5 Standard over v1.4 or earlier Experimental, your existing Experimental TLSRoutes stop being usable, because they are stored as v1alpha2 or v1alpha3, which the v1.5 Standard YAMLs do not include. Either stay on Experimental for v1.5.1 onward, or migrate your TLSRoutes to v1 before you upgrade. Check this before you touch a cluster that has Experimental TLSRoutes in it.
You do not need a new Kubernetes version. Gateway API v1.5 runs on Kubernetes 1.30 or later.
Picking an implementation
As of the v1.5 announcement, seven implementations were fully conformant with Gateway API v1.5, listed alphabetically by SIG Network: Agentgateway, Airlock Microgateway, GKE Gateway, HAProxy Ingress, kgateway, NGINX Gateway Fabric, and Traefik Proxy.
Conformance is the floor, not the decision. The things that will actually decide it for you are the ones standard Gateway API does not cover: how the implementation handles URL normalization, whether it has a policy CRD for the snippet behaviour you need to rebuild, and whether --emitter supports it in ingress2gateway. Pick the implementation before you finalise the manifests, because the emitter flag changes the output.
If you are running on GKE, GKE Gateway is the low-friction path. If your team knows Envoy, kgateway and Agentgateway both have emitter support. NGINX Gateway Fabric is the closest thing to a philosophical continuation of what you had, though it is not a drop-in and nobody claims it is.
FAQ
Is Ingress-NGINX actually dead, or just deprecated?
Retired. Kubernetes SIG Network and the Security Response Committee halted maintenance in March 2026. There are no further releases, no bugfixes, and no updates for any security vulnerability discovered. The GitHub repositories are read-only. Existing deployments keep functioning and Helm charts and container images remain available, which is what makes it dangerous.
How do I check if my cluster uses Ingress-NGINX?
Run kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx with cluster administrator permissions. This is the check the Kubernetes Steering Committee published in its January 2026 statement. Any returned pods mean you are running retired software. Nothing will alert you otherwise, because existing deployments continue working normally.
What happened to InGate, the planned replacement?
It was abandoned. Maintainers announced plans to wind down Ingress-NGINX and build a replacement controller with the Gateway API community, but that announcement failed to attract contributors. Per the retirement post, InGate development never progressed far enough to create a mature replacement, and it will also be retired. Gateway API is the recommended path.
Can ingress2gateway convert everything automatically?
No, and its authors say so directly: it is a migration assistant, not a one-shot replacement. Version 1.0 converts over 30 common annotations, up from three. It refuses configuration-snippet entirely, cannot translate proxy-body-size, and makes only a best-effort translation of TCP-level timeouts. Reviewing its warnings is the critical step.
Why will configuration-snippet not convert?
Because that annotation is why Ingress-NGINX was retired. It allows arbitrary NGINX configuration directives to be injected, which the maintainers described as having come to be considered serious security flaws. Gateway API has no equivalent by design. Rebuild the behaviour using HTTPRoute filters or your implementation's policy CRDs instead.
What does Gateway API v1.5 add?
Released 27 February 2026, it promoted six features to the Standard channel: ListenerSet, TLSRoute, HTTPRoute CORS filter, client certificate validation, certificate selection for Gateway TLS origination, and ReferenceGrant at v1. It runs on Kubernetes 1.30 or later, so no cluster upgrade is required to adopt it.
How should I cut over safely?
Do not cut over. Deploy Gateway API configuration alongside the existing Ingress, then shift traffic gradually using weighted DNS, your cloud load balancer, or platform traffic-splitting. Delete Ingress resources and uninstall the controller only once all traffic has moved. Test the flagged warnings in a development cluster first.
Will migrating to Gateway API increase my cloud bill?
It can. One Ingress controller usually sits behind one load balancer, whereas a Gateway per team means a load balancer per Gateway. AWS Elastic Load Balancing bills each running load balancer hourly plus $0.008 per Load Balancer Capacity Unit-hour. ListenerSet, promoted to Standard in v1.5, lets teams share one Gateway instead.
How eCorpIT can help
We migrate Kubernetes ingress estates to Gateway API, and we start where the risk actually is: an inventory of every annotation you are running, the snippets that will not convert, and the routing semantics you are carrying by accident. Our senior engineering teams run the parallel deployment, shift traffic in weighted increments, and hand back manifests your team can reason about, rather than generated YAML nobody has read. eCorpIT has been building and running production systems from Gurugram since 2021, is assessed at CMMI Level 5, and partners with AWS, Microsoft and Google. If you ran the kubectl check above and it returned pods, contact us.
References
- Ingress NGINX Retirement: What You Need to Know, Tabitha Sable, Kubernetes SIG Network and Security Response Committee
- Ingress NGINX retirement, Kubernetes Contributors (canonical copy)
- Ingress NGINX: Statement from the Kubernetes Steering and Security Response Committees, Kat Cosgrove, 29 January 2026
- Announcing Ingress2Gateway 1.0: Your Path to Gateway API, Beka Modebadze and Steven Jin, 20 March 2026
- Gateway API v1.5: Moving features to Stable, Kubernetes SIG Network
- Ingress-nginx CVE-2025-1974: What You Need to Know, Tabitha Sable, Kubernetes Security Response Committee, 24 March 2025
- kubernetes-sigs/ingress2gateway on GitHub
- Gateway API guides, Kubernetes SIG Network
- Gateway API HTTP timeouts guide
- Ingress controllers, Kubernetes documentation
- Elastic Load Balancing pricing, AWS
- Experimenting with Gateway API using kind, Kubernetes
Last updated: 16 July 2026.
Top comments (0)