Ingress-NGINX has been the default “it just works” ingress controller for a lot of Kubernetes estates for years — which is exactly why its announced retirement (March 2026) is such a big deal. If you’re migrating to Gateway API (or to a different ingress controller), the hardest part isn’t learning a new YAML shape. The hard part is discovering which Ingress-NGINX-specific behaviors your applications have quietly come to rely on.
The Kubernetes project recently published a migration-focused post that’s refreshingly blunt: even when a translation looks correct, you can still cause outages if you don’t account for Ingress-NGINX quirks. That’s the right framing. Most platforms don’t fail because a team can’t write an HTTPRoute — they fail because the old controller had surprising defaults, and the new controller has different semantics.
Step 0: Treat this as a behavior migration, not a manifest migration
Before you touch production manifests, decide what “done” means:
- Traffic parity: requests route to the same backends under the same conditions.
- Security parity: TLS settings, redirects, header behaviors, and auth hooks still enforce what you expect.
- Operational parity: SLOs, dashboards, and debugging workflows still work (or are improved).
Then build a compatibility inventory from your current cluster(s): list every Ingress, every annotation, and every snippet/ConfigMap feature you use. If you’re a platform team, this is the moment to standardize and deprecate your own “creative” ingress patterns before the external deprecation bites.
Step 1: Audit your Ingress-NGINX annotations and hidden dependencies
Ingress-NGINX deployments typically accumulate features via annotations. The risk is that these knobs are not standardized across controllers, and some are outright incompatible with Gateway API concepts.
Create a simple matrix:
- Routing: path matching mode, regex usage, host rules, canary/weighting, header-based routing.
- TLS: SNI behaviors, default certificates, client cert auth, protocol constraints.
- Security headers: HSTS, redirects, header rewrites, request/response buffering limits.
- Timeouts: upstream connect/read/write timeouts, keepalive tuning.
- Edge cases: websocket upgrades, gRPC, large uploads, streaming responses.
Anything in the “edge cases” bucket should trigger targeted testing. The fastest failures in ingress migrations are “it worked in staging” failures caused by different header, timeout, or regex semantics.
Step 2: Watch for semantic mismatches (regex, pathType, and “ImplementationSpecific”)
The Kubernetes post highlights a deceptively dangerous example: regex path matching behavior. Ingress-NGINX can treat regex matches as prefix-based and case-insensitive in ways people don’t expect. If your existing Ingress rules depend on that behavior (even accidentally), a “clean” Gateway API translation can become a breaking change.
Gateway API gives you better primitives, but it also shifts responsibility: regular expression handling is implementation specific and varies by gateway. Envoy-based gateways often behave differently than NGINX-based controllers. Your migration plan needs to name your gateway implementation and test against its actual matching behavior, not the abstract spec you wish were universal.
Step 3: Choose a migration strategy that matches your blast radius
Three strategies tend to work in practice:
- Side-by-side: run the new gateway in parallel; migrate one hostname or path at a time using DNS or weighted traffic splitting upstream (if available). Best for large estates.
- Namespace-by-namespace: pick a low-risk domain/namespace, migrate everything there, then scale out. Best when teams share patterns.
- Controller swap: replace the controller behind the same Ingress resources. Fast, but risky — and Gateway API doesn’t always fit here.
If you can do side-by-side, do it. The first time you discover an unexpected behavior should be on a low-volume hostname, not on your primary API domain.
Step 4: Build a “behavior test suite” for ingress
Ingress migrations are one of those changes where integration testing is vastly more valuable than unit testing. Your goal is to capture reality: for each important endpoint, validate that routing, headers, and status codes match expectation.
A pragmatic suite usually includes:
- Golden curl tests (host header + path + query combos).
- Header assertions (redirects, HSTS, custom headers, auth headers).
- Timeout tests (slow upstream, streaming response, large body upload).
- Protocol tests (websocket, gRPC, HTTP/2 where relevant).
Don’t forget negative tests: requests that should not route. Regex/path changes often broaden matches unintentionally, creating security exposures that look like “works fine” in happy-path tests.
Step 5: Use migration as a forcing function to simplify the edge
Most platform teams find they have accrued far too much logic at ingress: bespoke rewrites, custom auth fragments, and “temporary” snippets that became permanent. Gateway API migrations are a good moment to move policy into:
- Dedicated auth gateways (OIDC proxies, API gateways) instead of per-Ingress snippets.
- Service meshes or L7 policy engines where appropriate (but beware of adding new complexity mid-migration).
- Application-level redirects/rewrite logic when it’s truly app behavior.
The point isn’t purity. It’s reducing the number of invisible behaviors that can change when you swap controllers.
What to do this week (if March feels close)
- Inventory: export all Ingress objects and list every annotation used.
- Classify: mark which annotations are “must keep,” “nice to have,” and “should remove.”
- Pick a gateway: decide which Gateway API implementation you’ll standardize on.
- Test parity: start with a single domain and build the behavior test suite.
Ingress migrations can be calm and boring — but only when you treat them as the careful, behavior-preserving change they are.
