Ingress NGINX is retired. Your ingress still works. For now.
In November 2025, Kubernetes SIG Network announced the retirement of the community ingress-nginx controller. Best-effort maintenance continued until March 2026. After that: no new releases, no bug fixes, and no security patches.
Nothing went down in March. Existing deployments kept running, and the images and Helm charts stayed available. That is the problem. An unmaintained edge proxy doesn’t fail on a schedule. It fails the day a CVE lands and there is no patched release to roll to.
Be precise about what was retired
Two things people mix up:
- The Ingress API is not going anywhere.
networking.k8s.io/v1Ingress is still part of Kubernetes. Other controllers implement it and are maintained. - The
ingress-nginxcontroller is retired. That is the one fromkubernetes/ingress-nginx. It’s a different project from F5’s NGINX Ingress Controller, which is maintained separately.
Before planning anything, find out which one you actually run:
kubectl get pods -A -l app.kubernetes.io/name=ingress-nginx
kubectl get ingressclass
The annotation inventory is the real migration
Changing controllers is easy. The real work is in the annotations. Years of nginx.ingress.kubernetes.io/* annotations encode rewrites, timeouts, body size limits, CORS, auth hooks and the occasional configuration-snippet holding raw NGINX config that nobody remembers adding.
List them across the cluster and sort by how often they appear:
kubectl get ingress -A -o json \
| jq -r '.items[].metadata.annotations // {} | keys[]' \
| grep nginx.ingress | sort | uniq -c | sort -rn
Each line is a behavior you need to reproduce somewhere else or deliberately drop. Snippets need the most care: they can do anything, and the new controller won’t do any of it for you.
Gateway API is the place to land
Gateway API is the upstream successor to Ingress, and it’s generally available. Things that used to be annotations, like header matching, traffic splitting and redirects, are now typed fields on HTTPRoute. It also splits ownership: the platform team owns the Gateway, and application teams own their routes.
The ingress2gateway project converts Ingress resources into Gateway API resources and gives you a first draft. Treat its output as a starting point and review it alongside the annotation list.
Run both, then shift traffic
Install the new controller next to the old one with its own load balancer. Migrate one hostname at a time: create the route, test it against the new address, then move DNS with a short TTL. Rolling back means pointing DNS back.
When the last hostname has moved and the old controller’s access logs have been quiet for a week, delete it. Not before.
If you can’t migrate this quarter
Then at least know what you’re running. Pin the version, document why it isn’t patched, put the controller behind a WAF if it faces the internet, and put a date on the migration. “Still works” is a description of today, not a plan.