Ingress-NGINX Is Retired: How to Migrate to Gateway API Safely
Ingress-NGINX stopped getting patches in March 2026. How to find it in your clusters, translate it with ingress2gateway, and cut over to Gateway API.
If your Kubernetes cluster serves web traffic, there is a good chance a single pod called ingress-nginx-controller sits between the internet and every app you run. That controller was retired in March 2026. The GitHub repository was archived on March 24, 2026, and the project's own README now says plainly that if you are not already running it, you should not deploy it.
Nothing broke on retirement day, which is the problem. The Kubernetes Steering and Security Response Committees put it this way: "Existing deployments will continue to work, so unless you proactively check, you may not know you are affected until you are compromised." The same statement cites Datadog research that about 50% of cloud native environments relied on the controller.
Seven months later, two things make this week a good time to finish the job. Kubernetes 1.37 shipped in August, and the final ingress-nginx release lists end-to-end testing only up to Kubernetes 1.35. And if you use the AKS application routing add-on, Microsoft's critical security patches for its NGINX resources end in November 2026.
TL;DR
- Ingress-NGINX gets no releases, bug fixes, or security patches after March 2026; existing installs keep running, unpatched.
- Check every cluster with one
kubectlcommand, and check managed add-ons too: the AKS application routing add-on runs ingress-nginx under a different class name. - Gateway API is the upstream replacement; the Ingress API itself is frozen, not removed, so another Ingress controller is also a valid short-term path.
ingress2gateway1.0 translates over 30 common ingress-nginx annotations, but its warnings are the real deliverable: snippets, body size limits, and URL normalization need human decisions.- Ingress-NGINX regex paths are case-insensitive prefix matches and it adds trailing-slash redirects silently; a literal translation can turn working URLs into 404s.
- Run old and new data planes side by side, test against the new IP with
curl --resolve, then move traffic with a low-TTL DNS change you can reverse.
What "retired" means in practice
The retirement announcement is precise: after March 2026 "there will be no further releases, no bugfixes, and no updates to resolve any security vulnerabilities that may be discovered." Helm charts and container images stay available, so helm upgrade still works and nothing alerts you.
Two clarifications save a lot of confusion in planning meetings:
- Ingress-NGINX is not NGINX Ingress. The retired project is the community controller at
kubernetes/ingress-nginx. F5's NGINX Ingress Controller is a separate product that also uses NGINX as its data plane. Check which one you run before you plan anything. - The Ingress API is not going away. The Ingress documentation states the API "has been frozen": no new features, but your
Ingressobjects remain valid. Upstream recommends Gateway API, and if you need to stay on Ingress for now, the list of other Ingress controllers is the alternative it points to.
Step 1: Find every copy
The committees' check, run with cluster-admin rights against each cluster:
kubectl get pods --all-namespaces \
--selector app.kubernetes.io/name=ingress-nginx
The selector depends on labels the official Helm chart sets, so a hand-rolled install can slip through. Two more checks catch most of those:
# IngressClasses served by the community controller
kubectl get ingressclass \
-o custom-columns=NAME:.metadata.name,CONTROLLER:.spec.controller
# Any container running the community controller image
kubectl get pods -A \
-o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}' \
| grep 'ingress-nginx/controller'
An IngressClass whose controller is k8s.io/ingress-nginx belongs to the retired project. On AKS, also run kubectl get nginxingresscontrollers: the application routing add-on can run several controllers, each with its own class (the default is webapprouting.kubernetes.azure.com) and its own load balancer IP.
Then list what depends on it: kubectl get ingress -A gives every hostname and the IP it resolves to. Write down anything upstream that pins that IP, such as a CDN origin, a WAF, a partner's firewall allow list, or a health check in your uptime monitor. Those are the things that break during cutover, not the YAML.
Step 2: Pick where you are going
| Your situation | Sensible target |
|---|---|
| AKS with the application routing add-on | Microsoft's application routing Gateway API implementation (approuting-istio), or Application Gateway for Containers |
| Self-managed ingress-nginx on EKS, GKE, AKS, or bare metal | A conformant Gateway API implementation, such as Envoy Gateway, Istio, or kgateway |
Heavy use of configuration-snippet or Lua, no time for a redesign | Another Ingress controller now, Gateway API later, with a dated plan |
| Already running a service mesh | That mesh's Gateway API support |
For a small team, the deciding factor is usually who patches the controller. A cloud-managed implementation moves that job to your provider. A self-installed one keeps it with you, which is the same situation that got you here, so pick a project with an active release cadence and put its upgrades on the same calendar as your cluster upgrades.
Step 3: Translate with ingress2gateway, then read the warnings
Ingress2Gateway 1.0, released by SIG Network on March 20, 2026, reads your Ingress objects and their ingress-nginx annotations and writes Gateway API manifests. Support went from three annotations to over 30, including CORS, backend TLS, regex matching, and path rewrites, each backed by tests that compare live controller behavior.
go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0
# or: brew install ingress2gateway
ingress2gateway print --providers=ingress-nginx --all-namespaces > gwapi.yaml
Add --emitter envoy-gateway (or kgateway, agentgateway) to get implementation-specific extensions for settings that standard Gateway API cannot express. On AKS, Microsoft notes the tool reads only the nginx class by default; pass --ingress-nginx-ingress-class=<class> once per add-on class.
The output file is the easy half. The warnings it prints tell you where behavior will change:
configuration-snippetis not translated. Raw NGINX config has no Gateway API equivalent. Every snippet needs a decision: move it into the application, use an implementation extension, or delete it. Where snippets are enabled, they are also a security concern in their own right: anyone who can edit an Ingress can inject proxy configuration.proxy-body-sizeis not translated. Upload endpoints that worked at 1 GB may start returning 413 errors against your new proxy's default limit.- Timeouts are approximated. Ingress-NGINX timeouts are TCP-level; the tool maps them to a Gateway API request timeout, which is a different thing. Set it per route from what the service needs.
- URL normalization varies by implementation and standard Gateway API cannot configure it.
Step 4: Know the five behaviors that cause outages
SIG Network published a post titled Five Surprising Ingress-NGINX Behaviors, and every one of them turns a "correct" translation into a 404. The short version:
- Regex paths are prefix-based and case-insensitive.
/[A-Z]{3}under ingress-nginx also matches/uuid/anything. Envoy-based implementations do a full, case-sensitive match. use-regex: "true"leaks across Ingresses. It turns every path on that host into a regex, including paths in other Ingress objects markedExact.rewrite-targetimplies regex, with the same host-wide side effect.- Missing trailing slashes get a 301. A
Prefixpath of/my-path/redirects/my-path. Conformant Gateway API implementations never add redirects silently. - URLs are normalized before matching, so
////uuidand/ip/abc/../../uuidreach the/uuidbackend.
Ingress2gateway preserves the first one by writing (?i)/users/(\d+).*. That keeps current behavior, but it also keeps routing traffic your developers never meant to expose. Decide route by route. If clients depend on the trailing-slash redirect, add it explicitly:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: trailing-slash-redirect
spec:
parentRefs:
- name: public-gateway
hostnames: ["app.example.com"]
rules:
- matches:
- path:
type: Exact
value: /my-path
filters:
- type: RequestRedirect
requestRedirect:
path:
type: ReplaceFullPath
replaceFullPath: /my-path/
statusCode: 301
The fastest way to find which behaviors you rely on is your access logs: export a week of request paths from the ingress-nginx controller and replay a sample against the new gateway in staging.
Step 5: Cut over with DNS, keep a way back
Both upstream and Microsoft describe the same sequence: run both data planes at once, prove the new one, then move clients.
-
Lower DNS TTLs to 60 seconds for each affected hostname, then wait out the old TTL before anything else.
-
Deploy the Gateway and HTTPRoutes alongside the existing Ingress. The new gateway gets its own load balancer IP; the old path keeps serving users.
-
Test the new IP directly, every hostname and path, over HTTPS with the production certificate:
curl -sS -o /dev/null -w '%{http_code}\n' \ --resolve "app.example.com:443:${GW_IP}" \ https://app.example.com/api/healthExercise POST bodies, authentication, WebSockets, gRPC, and large uploads, not only
GET /. -
Point DNS at the gateway and update anything upstream that pinned the old IP. On AKS, Microsoft warns you cannot move the old IP over: managed public IPs are deleted with their Service even when marked
Static. -
Watch the old controller's request rate fall to zero, keep TTLs low for a few hours, then delete the Ingress objects and uninstall ingress-nginx.
Until step 5, rollback is one DNS change. That is the property worth protecting, so keep the Ingress objects in place until you are sure.
Where this fits in your platform work
Treat this as a cluster lifecycle task, not a one-off ticket. Whatever replaces ingress-nginx will have its own CVEs and release notes, and someone needs to own them on the same schedule as node and control-plane upgrades. Ingress traffic also belongs in your supply chain and dependency inventory: an internet-facing proxy that stopped receiving patches is exactly what that inventory exists to catch.
If you would rather hand over the inventory and the plan, our Cloud & DevOps Audit Sprint covers retired components like this one alongside cost and reliability findings, and our Kubernetes service runs migrations like this end to end. For the rest of the cluster, see our guides to Kubernetes cost optimization and securing AI agents on Kubernetes.
Frequently asked questions
Will ingress-nginx stop working now that it is retired? No. Existing deployments keep running and the images and Helm charts remain available. What stopped is maintenance: no releases, bug fixes, or security patches since March 2026. The risk grows over time, as new vulnerabilities go unpatched and new Kubernetes versions go untested; the final release lists testing only up to Kubernetes 1.35.
Do I have to move to Gateway API, or can I switch to another Ingress controller? Both work. The Ingress API is frozen, not deprecated for removal, so another maintained Ingress controller is a valid way to get off an unpatched component quickly. Gateway API is where upstream development happens, and a move to it now avoids a second migration later. Teams with heavy NGINX snippet use often switch controllers first and redesign afterwards.
How long does a migration take for a small team? For a single cluster with a dozen or so Ingress objects and few custom annotations, the translation is a day or two. Most of the time goes into testing the behaviors above, finding upstream systems pinned to the old IP, and waiting out DNS TTLs. Plan for a couple of weeks of calendar time per cluster, longer if you rely on configuration snippets.
Put this into practice
Book a free 1-hour call with a senior engineer about your infrastructure, or check your email security in 30 seconds.
Related Services
Related Articles
Kubernetes Cost Optimization: How to Cut Your K8s Bill by 40%
A practitioner's guide to cutting Kubernetes costs 40%: resource requests, right-sizing, spot nodes, autoscaler, quotas, and idle detection.
Securing AI Agents in Production: Why Kubernetes Isn't Enough
Kubernetes secures your containers, not what your AI agents decide to do. The threat model SMBs are missing and eight controls that close it.
Platform Engineering vs DevOps: What SMBs Actually Need in 2026
Platform engineering is the hottest infrastructure trend, but most SMBs don't need a full internal developer platform. How to decide what fits.
Get articles like this in your inbox
Practical security, infrastructure, and DevOps insights for teams in regulated industries. Published weekly.