Issue #028 - ingress-nginx: four months archived, and nothing has broken yet
What actually retired, why InGate died too, the five real migration targets, and the annotations that don't port
The repo went read-only on 24 March. I know the exact date because I went and looked it up this week, after an audit script flagged a cluster I had forgotten about - a small internal one, three services, an ingress-nginx install that had been sitting there since before I joined. It was serving traffic. It had been serving traffic every day for the four months since the project that maintains it stopped existing.
Nothing broke. Nothing is going to break tomorrow either. An archived controller doesn't stop reconciling, it doesn't phone home and refuse to start, it just keeps doing exactly what it did on 23 March and will keep doing it until the day something else forces the issue. Which means the deadline everybody planned around was never a real deadline. It was a date after which the failure mode changed from "we get a patch" to "we don't", and that change is invisible from the outside.
So this isn't a migration guide written before the fact. It's one written 124 days after, when the urgency has drained out of the room and the thing is still running in a lot of clusters, including probably one of yours.
🏗️ Architectural Pattern: what retired, and what everyone thinks retired
The announcement was narrower than the panic
SIG Network and the Security Response Committee announced the retirement on 12 November 2025. Best-effort maintenance would continue until March 2026, and after that there would be no releases, no bug fixes, and no security patches. The repository - kubernetes/ingress-nginx, 19.5k stars - was archived on 24 March 2026 and is read-only now.
What retired is one specific implementation. Four things that people routinely believe also retired didn't:
The Ingress API itself is fine. It's feature-frozen, has been for years, and networking.k8s.io/v1 isn't going anywhere. Your Ingress manifests are still valid Kubernetes objects. They just need something to act on them.
NGINX the web server is fine. It's F5's product, it ships releases on its own cadence, and 1.29.7 in March 2026 flipped upstream keepalive on by default. Unrelated project, unrelated lifecycle.
nginx/kubernetes-ingress is fine, and this is the one that trips people up most. F5 maintains a separate ingress controller with a confusingly similar name, 5k stars, released v5.5.4 this month. It isn't the archived project. If you're on that one you aren't affected at all, and a surprising number of teams can't tell you offhand which of the two they installed.
And the reason for all of it wasn't technical. The project had one or two people doing the work, on their own time, after hours, for a controller that Datadog's telemetry put in roughly half of all cloud native environments. That ratio held for years. It was never sustainable, and eventually the maintainers said so out loud instead of continuing to absorb it.
The official successor died first
The plan, back in November, was InGate: a new controller built jointly by the ingress-nginx maintainers and the Gateway API community, meant to be the blessed migration path. It never got there. The repo is kubernetes-sigs/ingate, its description now literally starts with [EOL], and it's archived alongside the thing it was supposed to replace.
I want to sit on this for a second, because it's the most useful fact in the whole story and it gets skipped in most of the migration posts. The recommended path didn't exist. If you started planning in December against "we will move to InGate when it's ready," you spent six months waiting for a project that shipped nothing in that window, and you're now four months past the deadline with no plan at all. That isn't a hypothetical - it's the single most common reason I've heard this month for why a cluster is still on the archived controller.
The lesson generalises past this incident. When an upstream announces a retirement and names a successor in the same breath, those are two separate claims with two separate confidence levels. The retirement is a decision, and decisions get executed. The successor is a forecast, and forecasts made by burnt-out maintainers about volunteer capacity aren't worth much. Plan against the retirement, treat the successor as a maybe.
Links
🆚 The Showdown: five migration targets and what each one actually costs
There's no drop-in replacement. The committees said so in the January statement, and everyone who has done the move confirms it. What you're choosing between is five different shapes of work.
Traefik is the closest thing to a soft landing, and it's the biggest project in the space by a wide margin - 64k stars, v3.7.9 last week. It ships an ingress-nginx provider that translates a good chunk of the annotation surface, so a simple Ingress moves with little more than a class change. Coverage isn't complete, and the gaps are exactly where you'd expect: anything that reached into raw nginx config. ModSecurity lives in Traefik Hub, which is the commercial tier.
Envoy Gateway is the Gateway API answer with the least ceremony. 2.9k stars, v1.8.3, active. You're rewriting Ingress into Gateway plus HTTPRoute, which is real work, but the resource model is cleaner and the project isn't trying to also be a service mesh. If you've decided Gateway API is where you're going anyway, this is the shortest route with the fewest opinions attached.
Contour is CNCF-incubating, 3.9k stars, v1.33.5, and has been doing Envoy-behind-a-controller longer than most. Same Gateway API rewrite cost. Smaller community than Envoy Gateway now, which wasn't true two years ago.
kgateway is the one that surprised me when I went looking at current numbers - 5.6k stars, v2.4.0, and moving fast. Envoy-based, Gateway API native, with an AI-gateway angle bolted on that you can ignore if you don't need it. Younger, so the "someone has already hit my edge case and blogged about it" factor is lower.
HAProxy Ingress at 1.2k stars is the small one, and I keep it on the list for exactly one reason: it has real embedded ModSecurity with Core Rule Set support. If your migration is blocked on a WAF ruleset you can't rewrite, this is the option that doesn't force you to stand up a separate WAF tier.
The benchmark nobody wants to talk about
John Howard - an Istio maintainer, who says up front that this makes him biased - published a benchmark harness comparing seven Gateway API implementations across attached routes, route propagation time, route scale, and traffic performance. The findings that stuck with me weren't the throughput numbers. They were the behavioural ones: Traefik consolidating all Gateways into a shared component, which is an isolation problem, and accepting traffic before config is applied. Cilium bottlenecking on a single CPU core for traffic performance.
The meta-point is worth more than any individual number. Nearly all of these sit on Envoy, and they still behave completely differently, because the proxy isn't the product. The controller is. Conformance tests cover the base case and stop well short of the things that will page you.
Treat the numbers as a prompt to run your own, not as a ranking. The harness is public.
Links
👮 The Policy: audit the annotations before you pick the controller
Every migration write-up I read starts with "pick your target." That's backwards, and it's why so many of these stall in week three. You can't evaluate targets until you know what you're actually using, and almost nobody does, because the annotation surface accumulated over five years across teams that have since reorganised.
Start here instead:
kubectl get ingress -A -o json | jq -r '
.items[] | .metadata.annotations // {} | keys[]
' | grep '^nginx.ingress.kubernetes.io/' | sort | uniq -c | sort -rnThat gives you a frequency-ranked list of every ingress-nginx annotation in the cluster. Most of it will be rewrite-target, ssl-redirect, proxy-body-size - portable everywhere, boring, fine. What you're hunting for is the tail.
Four categories don't port cleanly, and finding them late is what turns a two-week migration into a two-quarter one.
Snippets. configuration-snippet and server-snippet inject raw nginx config. There's no equivalent in Envoy, because it isn't nginx - the config languages have no common ground. Every snippet is a bespoke rewrite, and some of them encode behaviour that nobody remembers requesting. Later ingress-nginx releases already restricted these by default, after the IngressNightmare CVE work, so you may have fewer live than you fear.
ModSecurity. enable-modsecurity and friends. Either HAProxy Ingress, or Traefik Hub, or a WAF tier in front. There's no path where the rules move unchanged into an Envoy-based controller.
Auth subrequest. auth-url and auth-signin have equivalents nearly everywhere, but the semantics differ in the details - which headers get forwarded, what happens on a non-2xx, how the redirect is built. This is the category that passes staging and fails in production, because the difference only shows up on the error path.
Session affinity edge cases. Plain cookie affinity is universal. Custom cookie names combined with path scoping and affinity-mode: persistent is where implementations diverge, and the failure is a user getting silently rebalanced mid-session rather than an error anyone sees.
The honest part
Two weeks minimum on staging before you touch production. I would say four if auth subrequest showed up in your audit. Run both controllers side by side with a split at the DNS or load balancer layer if your setup allows it, because the rollback story for "we swapped the ingress controller" is otherwise "we swap it back and hope the annotations still mean what they meant."
And a thing I've changed my mind about: I used to tell people to go straight to Gateway API on the grounds that the Ingress API is frozen and you'll have to move eventually. I now think that's bad advice for a team under time pressure. Moving to Traefik on Ingress semantics buys you a maintained controller in days rather than months, and the Gateway API migration is still there afterwards, on your schedule, decoupled from the security problem. Two smaller moves beat one big one when the first move is the urgent one. Gateway API is the right destination. It doesn't have to be the next step.
Links
Four months of nothing
The thing that makes this hard to prioritise is that the risk curve doesn't look like the deadline curve. On 24 March nothing changed operationally. The controller in that forgotten cluster of mine is running the same binary, serving the same traffic, with the same behaviour it had in February. The only thing that changed is what happens next time somebody finds a bug in it, and nobody can tell you when that's.
That's also why I wouldn't let this sit much longer. Not because of a date that has already passed, but because the audit takes an afternoon and the answer determines whether your migration is a week or a quarter. Run the annotation query. If the tail is empty, you have a boring week ahead of you and you should just do it. If ModSecurity or auth subrequest shows up, you've found out now instead of in the middle of an incident, which is the whole point.
I ran it on the forgotten cluster. Twelve annotations, all boring, one afternoon of work. The one I haven't run it on yet is the big one, and I'm fairly sure I know why I keep not getting to it.
Questions? Feedback? Reply to this email. I actually read them.
Ilia


