Abhinav C

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/v1 Ingress is still part of Kubernetes. Other controllers implement it and are maintained.
  • The ingress-nginx controller is retired. That is the one from kubernetes/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.

Filed under: things that still work until they very much do not.

More writing