# Ingress-NGINX EOL in 2026: a practical migration guide to Gateway API

> Ingress-NGINX reached end of life on March 26, 2026. Here's how to migrate to Gateway API with ingress2gateway 1.0, pick a controller (Traefik, Envoy Gateway, kgateway), and avoid the upload bug that bites WSGI apps.

- **Published:** 2026-04-25
- **Author:** Ownkube team
- **Category:** Engineering
- **Tags:** kubernetes, gateway-api, ingress-nginx, ingress2gateway, traefik, envoy-gateway, kgateway, httproute, migration
- **Canonical URL:** https://ownkube.io/blog/ingress-nginx-eol-gateway-api-migration
- **Cover:** https://ownkube.io/blog/ingress-nginx-eol-gateway-api-migration.png

---
If you're running ingress-nginx in production, the situation is now this: the project [reached end of life on March 26, 2026](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/). No more releases. No more bug fixes. No more CVE patches. The repos are going read-only. The Helm charts and images stay published, so your cluster won't suddenly break, but the next time a serious vulnerability lands, nobody upstream is going to fix it.

SIG Network estimates this affects [around 50% of cloud-native environments](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/). If your team is one of them, the question stopped being "should we migrate" and started being "to what, and how, and how fast."

This post is a practical answer. We'll cover why ingress-nginx was retired, what Gateway API actually fixes, how to use the new ingress2gateway 1.0 tool, which controller to pick, and the migration gotcha that has bitten several teams already.

## Why ingress-nginx was retired

The official statement is worth reading in full, but the short version: ingress-nginx had one or two maintainers doing the work on nights and weekends, and the project's flexibility had become a liability instead of a feature.

The clearest example is the `nginx.ingress.kubernetes.io/configuration-snippet` annotation, which let any user with permission to create an Ingress object inject arbitrary NGINX config into the data plane. That was useful in 2018. By 2024 it was the source of repeated CVEs that allowed attackers to read service-account tokens off the controller. The Kubernetes Steering and Security Response Committees concluded that ["it is no longer reasonable or even possible to continue maintaining the tool even if resources did materialize"](https://kubernetes.io/blog/2026/01/29/ingress-nginx-statement/).

Two things to keep straight:

1. **The Ingress API itself is not deprecated.** Only the ingress-nginx controller is. If you switch to a different Ingress controller (HAProxy, F5 NGINX, AWS Load Balancer Controller), your existing `Ingress` resources still work.
2. **Existing deployments will keep running.** This is a stop-shipping-fixes event, not a stop-running event. You have time to plan, but not forever.

## What Gateway API actually fixes

Gateway API has been GA since 2023 and is the official successor to the Ingress spec. If you've only ever lived in Ingress-land, the headline differences are worth understanding before you pick a controller.

**No more annotation soup.** The original Ingress spec under-specified almost every interesting feature: traffic splitting, header manipulation, timeouts, retries, rewrites. Vendors filled the gaps with controller-specific annotations. Switching from nginx to Traefik meant rewriting every annotation. Gateway API has first-class fields for these things, defined in the spec.

**Role-oriented resources.** Gateway API splits ingress into three resources:

- `GatewayClass`: cluster-wide, owned by the platform team. Defines which controller implementation handles a class of gateways.
- `Gateway`: namespace-scoped, owned by network operators. Defines listeners, certs, and which routes can attach.
- `HTTPRoute` / `TCPRoute` / `GRPCRoute`: owned by app developers. Defines actual routing logic.

This split matters. With Ingress, every developer with `Ingress` create permission could touch the listener config, the TLS cert, the load balancer. With Gateway API, the platform team owns the gateway, and developers attach routes to it through `ReferenceGrant`. RBAC finally maps to how teams actually work.

**Cross-namespace routing.** A `HTTPRoute` in the `frontend` namespace can target a service in the `backend` namespace, gated by a `ReferenceGrant`. With Ingress, this required either putting Ingress objects in the wrong namespace or running an ExternalName shim.

**Traffic splitting and weighted routing as first-class features.** Canary deploys, blue-green, header-based splits. No annotations, no controller-specific CRDs. Just `weight` and `matches` fields.

## ingress2gateway 1.0 makes the translation tractable

The Kubernetes networking team [released ingress2gateway 1.0 on March 20, 2026](https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/), six days before the ingress-nginx EOL date. This is the tool you want.

It translates your existing Ingress manifests into Gateway API resources, preserving behavior where it can and warning you where it can't. The 1.0 release expanded support from 3 to over 30 ingress-nginx annotations, including CORS, backend TLS, regex matching, path rewrite, body size limits, and timeouts. It also added integration tests that spin up real ingress-nginx and Gateway API controllers to verify the translated config behaves the same way at runtime, not just on paper.

Basic usage:

```bash
# Translate a manifest file
ingress2gateway print --input-file my-ingress.yaml \
  --providers=ingress-nginx > gwapi.yaml

# Translate everything in a namespace
ingress2gateway print --namespace prod \
  --providers=ingress-nginx > gwapi.yaml

# Translate the whole cluster
ingress2gateway print --providers=ingress-nginx \
  --all-namespaces > gwapi.yaml
```

The most important step is the one nobody likes: **review the output and the warnings carefully**. ingress2gateway is not a one-click migrator. It is a translator that flags what it can't translate so you can decide what to do manually. For complex setups (mTLS, custom Lua snippets, weird rewrite chains), expect to do real engineering work on top of the generated YAML.

## Picking a controller

You have real choices here. The honest summary, based on the [gateway-api-bench numbers](https://github.com/howardjohn/gateway-api-bench) and the migration tooling each project ships:

- **Traefik.** Lightweight, great DX, single binary, ships compatibility shims for many ingress-nginx annotations. Strong for indie teams and small clusters. Loses some throughput at very high connection counts (over 32 concurrent), but that's not where most teams live.
- **Envoy Gateway.** CNCF, vendor-neutral, strict Gateway API conformance. Good for teams that want a pure standards-compliant gateway without service-mesh complexity. Built-in OIDC, rate limiting, and OAuth2.
- **kgateway** (formerly Gloo Gateway). Envoy data plane, optimized control plane, ships its own fork of ingress2gateway with extra annotation coverage. AI-native routing primitives if you're building LLM apps. Best for high-churn CI/CD environments.
- **HAProxy Kubernetes Ingress Controller.** Stays on the Ingress spec, not Gateway API. A reasonable choice if you want to defer the Gateway API migration and just swap the controller.
- **F5 NGINX Ingress Controller.** Different project from ingress-nginx, Apache 2.0, maintained by F5. Also Ingress-spec-based. Familiar config model for teams that don't want to learn a new resource model.

If your priority is the smallest possible diff to your current setup, F5 NGINX or HAProxy is the path of least resistance. If your priority is being on a maintained, modern, standards-tracking stack three years from now, Gateway API on Traefik or Envoy Gateway is the better long-term call. Don't pick based on benchmarks unless you've actually measured your own workload.

## The migration gotcha most teams hit

The sneakiest bug in ingress-to-Gateway-API migrations isn't a routing rule. It's request body handling.

ingress-nginx buffers request bodies by default before forwarding upstream. Most modern Gateway API controllers (Traefik, Envoy-based) stream request bodies upstream with `Transfer-Encoding: chunked`. For most apps, this is a performance win. For [WSGI apps running under uWSGI or Gunicorn](https://devoriales.com/quiz/20/gateway-api-learning-lab-from-zero-to-hero), it's a silent disaster: WSGI servers expect a `Content-Length` header and don't reliably handle chunked transfer encoding. File uploads arrive as zero-byte files. The controller logs look clean. The app logs look clean. Your users just can't upload anything.

If you run any Python WSGI service, any Ruby Rack app on an older server, or any framework that predates ASGI, test file uploads on a staging cutover before you flip production traffic. The fix is usually a controller-side body buffer or a switch to ASGI/Uvicorn/Gunicorn-with-async, but you want to discover this on staging.

## A learning path

If you want to go from "I read this blog" to "I can defend a Gateway API migration in a design review," there's a free 12-lesson hands-on course at [devoriales.com](https://devoriales.com/quiz/20/gateway-api-learning-lab-from-zero-to-hero) that uses Traefik and a real bookstore app on a local k3d cluster. It covers the resource model, TLS with mkcert and cert-manager, traffic splitting, ReferenceGrant, PDBs and HPAs for the gateway itself, and extending Traefik with custom Go plugins via Yaegi. About 6 to 8 hours, self-paced. The content is open; only progress tracking needs an account.

It's the most practical hands-on resource we've found, and it's specifically built around the migration story instead of treating Gateway API as a greenfield exercise.

## When to stay on Ingress (for now)

A few honest cases where migrating today is the wrong call:

- You're running F5 NGINX Ingress Controller, HAProxy, or a cloud-managed controller (AWS ALB, GKE Ingress). Your project isn't being retired. You can wait until Gateway API gives you a feature you actually want.
- You have one cluster, three services, and ingress-nginx works. Move to a maintained Ingress controller (F5 NGINX is the closest swap), table the Gateway API migration for next quarter.
- You're mid-migration on something else (cluster upgrade, mesh rollout, region split). Don't stack two migrations.

If you're running ingress-nginx in production with custom snippet annotations, multi-tenant clusters, or compliance requirements (SOC 2, PCI-DSS, HIPAA), the calculus is different. Unpatched CVEs in your data plane will become an audit finding fast.

## Where Ownkube fits

This is exactly the kind of work a platform layer should absorb. When we provision a cluster on your AWS or GCP account, ingress is set up on Gateway API from day one with Cloudflare on the edge for DDoS, bot, and scrape protection, and a ready-to-share preview domain per project. No Route 53 to configure, no controller to pick, no cert-manager to wire up, no annotation soup to translate.

If ingress-nginx EOL is the second migration you've had to plan this year, the answer isn't to keep getting better at migrations. It's to stop owning the parts of the stack where the answer is the same for everyone.

If you want a Heroku-style developer experience in your own cloud account, with the ingress and edge story already solved, [start on Ownkube](https://app.ownkube.io/signup). Free for teams on k3s mode (as of April 2026), and ten dollars per vCPU plus five per GB RAM on EKS mode when you scale. You pay AWS wholesale for the compute, we run the platform on top, and AWS Activate credits apply directly to your cloud bill.

Sources:
- [Ingress NGINX Retirement: What You Need to Know (Kubernetes blog)](https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/)
- [Ingress NGINX: Statement from the Kubernetes Steering and Security Response Committees](https://kubernetes.io/blog/2026/01/29/ingress-nginx-statement/)
- [ingress2gateway 1.0 release announcement](https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/)
- [Gateway API Learning Lab on devoriales.com](https://devoriales.com/quiz/20/gateway-api-learning-lab-from-zero-to-hero)
- [gateway-api-bench (Howard John)](https://github.com/howardjohn/gateway-api-bench)