Skip to content

Migrating from Ingress NGINX to Gateway API without outages

Translating the YAML is the easy part. The outages come from behaviour Ingress NGINX applied implicitly and Gateway API does not.

Dopstack Engineering

· 5 min read

Quick answer

Kubernetes announced that Ingress NGINX would receive no further releases, bugfixes or security updates after March 2026. Migrate to Gateway API by translating routes with ingress2gateway 1.0, then test behaviour, not YAML. The outages come from implicit behaviour: regex matching, rewrites, trailing-slash redirects and URL normalization.

If you run Ingress NGINX, the project's own notice says what happens after March 2026: no further releases, no bugfixes, and no updates for security vulnerabilities discovered later [1]. Your cluster keeps working. It just stops being patched. The recommended path is Gateway API, and the tooling to get there now exists. The risk is not the tooling. It is behaviour you never configured on purpose.

Why is Ingress NGINX being retired?#

Kubernetes SIG Network and the Security Response Committee retired it because it could no longer be maintained safely [1]. Three reasons are stated in the announcement:

  • Too little maintainership. For years the project had one or two people doing development in their own time [1].
  • Flexibility turned into risk. Options once seen as helpful, such as adding arbitrary NGINX configuration through the "snippets" annotations, are now considered serious security flaws [1].
  • No successor. The planned replacement controller, InGate, never matured and will also be retired [1].

Existing deployments are not broken, and Helm charts and container images stay available [1]. That is the trap: nothing fails on the day, so the migration slips.

How do you know whether you run Ingress NGINX?#

Run this with cluster administrator permissions. The Kubernetes notice gives it as the check that works in most cases [1].

bash
kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx

Managed Kubernetes platforms sometimes bundle it, so also check your provider's add-ons. Do not confuse it with NGINX Ingress from F5, which is a separate controller that happens to use NGINX as well [3].

What does ingress2gateway 1.0 do, and what does it leave to you?#

Ingress2Gateway translates Ingress resources and implementation-specific annotations into Gateway API manifests, and warns you about configuration it cannot translate [2]. Before 1.0 it handled three Ingress NGINX annotations. Version 1.0 handles over 30 common ones, including CORS, backend TLS, regex matching and path rewrite, each backed by tests against live controllers [2].

translate.sh
# From manifest files
ingress2gateway print --input-file my-manifest.yaml --providers=ingress-nginx > gwapi.yaml

# From a namespace, or the whole cluster
ingress2gateway print --namespace my-api --providers=ingress-nginx > gwapi.yaml
ingress2gateway print --providers=ingress-nginx --all-namespaces > gwapi.yaml

The project is explicit that this is "a migration assistant, not a one-shot replacement", and that reviewing the output and its warnings is the most critical step [2]. Treat every warning as a ticket.

Which Ingress NGINX behaviours break a correct-looking migration?#

A route that looks right can still return 404s because Ingress NGINX did something implicitly that Gateway API will not do for you [3]. These are the five documented cases:

BehaviourIngress NGINXGateway APIWhat to do
Regex pathsPrefix-based and case-insensitiveRegularExpression is implementation specific. Istio, Envoy Gateway and Kgateway do a full, case-sensitive matchTest real request paths. Use (?i) and a trailing .* to keep the old matching
use-regex scopeApplies to every path on that host, across all IngressesExact and Prefix are never silently treated as regexList hosts that use it. Check other Ingresses on the host for patterns that only worked because of it
rewrite-targetSilently turns on regex for the hostURLRewrite filter has no such side effectTreat any host with rewrite-target like a use-regex host
Trailing slash301 redirect from /path to /path/ (not for regex paths)No implicit redirectsAdd an explicit RequestRedirect rule if clients depend on it
URL normalizationNormalizes ., .. and duplicate slashes before matchingIstio, Envoy Gateway and Kgateway normalize . and .. out of the box. Check each implementationTest requests with //, /./ and /../ against the new gateway
Implicit Ingress NGINX behaviour and what to do in Gateway API (source: Kubernetes blog [3])

The regex case shows the pattern. An Ingress with /[A-Z]{3} routes /uuid too, because matching is a case-insensitive prefix. A Gateway API implementation that does a full case-sensitive match returns 404 for the same request [3]. To keep the old behaviour you write it down on purpose:

httproute.yaml
matches:
- path:
    type: RegularExpression
    value: "(?i)/[a-z]{3}.*"

How do you test that behaviour is preserved?#

This is our approach, not a Kubernetes procedure. It treats the old controller as the specification.

  1. InventoryList every Ingress, its annotations and its host. Flag hosts that use use-regex or rewrite-target, because their other paths behave differently.
  2. Translate and read the warningsRun ingress2gateway and resolve each warning. Decide, per item, whether to translate it, replace it, or drop it.
  3. Replay real pathsTake paths from your access logs, including the ugly ones: wrong case, missing trailing slash, double slashes. Send them to both controllers and compare status codes and Location headers.
  4. Run both in parallelDeploy the Gateway next to the old controller and move traffic gradually. Keep the old path until the diff is clean.
  5. Remove the old controller lastOnce traffic has been stable, delete it and its annotations.

Frequently asked questions#

Is Ingress NGINX the same as NGINX Ingress?
No. Ingress-NGINX is maintained by the Kubernetes community and was scheduled to retire in March 2026. NGINX Ingress is a separate controller from F5. Both use NGINX as the data plane, but they are otherwise unrelated.
Will my existing Ingress NGINX deployment stop working?
No. Per the Kubernetes announcement, existing deployments continue to function and artifacts such as Helm charts and container images remain available. What stops is new releases, bugfixes and security updates.
Do I have to move to Gateway API?
No. Kubernetes recommends Gateway API as the modern replacement, but says that teams who must keep using Ingress can choose from the alternative Ingress controllers listed in the Kubernetes documentation.
Does ingress2gateway migrate everything in one step?
No. The project calls it a migration assistant, not a one-shot replacement. It translates supported configuration, warns about what it cannot translate, and expects you to review the output. Version 1.0 supports over 30 ingress-nginx annotations.
What is the most common cause of outages in this migration?
Implicit behaviour. Ingress NGINX treats regex paths as case-insensitive prefixes, enables regex on a whole host through use-regex or rewrite-target, and redirects missing trailing slashes. Gateway API does none of this silently, so unchanged clients start getting 404 responses.

Continue reading