Kubernetes Gateway API vs Ingress: Why It Replaces Annotations

Photo by Eric Kilby via Wikimedia Commons (CC BY-SA 2.0)
Yes. The Gateway API is the official successor to Ingress. The Ingress API is not being deleted and remains generally available, but it is feature-frozen, and all active networking development has moved to the Gateway API. New projects should start on the Gateway API rather than Ingress.
It depends on your controller. The kubernetes/ingress-nginx project reached end of life on March 24, 2026, so it gets no more bug fixes or CVE patches, making migration urgent for those users. If you run a managed cloud Ingress or another supported controller, you have more time, but the long-term direction favors the Gateway API.
They are the three main role-oriented resources. GatewayClass is the controller template installed by infrastructure providers, Gateway is the entry point with listeners and TLS owned by the platform team, and HTTPRoute holds the routing rules owned by application developers. This split mirrors how most organizations already divide ownership.
Yes, they can coexist, which is what makes incremental migration possible. You install a Gateway API controller alongside your existing Ingress controller and move one service at a time. Once a service's traffic runs cleanly through a Gateway and HTTPRoute, you delete its old Ingress resource.
ingress2gateway is a CLI from Kubernetes SIG-Network that reads existing Ingress resources and generates equivalent Gateway and HTTPRoute manifests, with version 1.0 translating more than thirty common ingress-nginx annotations. Treat it as a strong starting point, not a rubber stamp. Always review the generated manifests and validate routing parity before cutting traffic over.

Photo by Eric Kilby via Wikimedia Commons (CC BY-SA 2.0)
Key Takeaway
The Gateway API is the successor to Ingress in Kubernetes. It splits one overloaded resource into role-oriented pieces: GatewayClass, Gateway, and HTTPRoute. That kills the annotation soup Ingress relied on, gives platform and app teams clean ownership boundaries, and is now the recommended path since ingress-nginx reached end of life in March 2026.
I have run traffic through Ingress for years, and the pattern always rots the same way. You start with a clean host-and-path spec, then a TLS quirk appears, then a rewrite, then a rate limit, and six months later your Ingress manifest is a wall of controller-specific annotations that only one person on the team understands. Ingress was standardized in 2015 and its spec barely moved; every feature past basic host routing had to be smuggled in through annotations that are not portable between controllers.
The Gateway API fixes the root cause, not the symptom. It reached its stable v1 milestone and is now at version 1.5.x, with the API group gateway.networking.k8s.io. The timing matters: on March 24, 2026, the kubernetes/ingress-nginx project reached end of life. The repository is read-only, and there will be no more bug fixes or CVE patches. If you run ingress-nginx today, migration is no longer a nice-to-have.
The core design flaw of Ingress is that a single resource mixes two completely different jobs. It describes where traffic enters the cluster (the load balancer, its IP, its TLS certificates) and how traffic is routed to services (hosts, paths, backends) in the same object. In most organizations those are owned by different people: a platform or infrastructure team owns the edge, and application teams own their own routes. Ingress forces both concerns into one manifest, so either the platform team becomes a bottleneck approving every route change, or app teams get write access to the shared edge and can break each other.
The Gateway API splits that single resource along the exact lines your org chart already follows. There are three main resources, each with a clear owner.
An HTTPRoute attaches to a Gateway through a parentRefs field, and the Gateway decides via its allowedRoutes rules which namespaces may attach. That is the whole trick: the platform team locks down the edge and TLS once, then hands developers a safe, self-service surface for their own routing. No shared file, no annotation review bottleneck, no accidental blast radius across teams.
Here is the same idea in code. Below is a typical ingress-nginx manifest: a handful of standard fields plus a stack of annotations that only ingress-nginx understands. Move it to Traefik or HAProxy and those annotations mean nothing.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: 80The canary weight, the rewrite, the SSL redirect: none of that is in the Ingress spec. It lives in vendor annotations, which is why an Ingress manifest is not really portable. The Gateway API pulls those features into typed, first-class spec fields. Here is the equivalent HTTPRoute with a path rewrite and a 20 percent traffic split expressed natively.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shop
namespace: shop-team
spec:
parentRefs:
- name: prod-gateway
namespace: infra
hostnames:
- shop.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-v1
port: 80
weight: 80
- name: api-v2
port: 80
weight: 20The payoff of typed fields is not just portability. Because rewrites, header matches, and traffic weights are part of the schema, kubectl validation, admission policies, and your IDE all understand them. A typo in a weight is caught at apply time, not discovered at 2 a.m. when a canary sends 100 percent of traffic to the wrong service.
| Concern | Ingress | Gateway API |
|---|---|---|
| Resource model | One resource mixes edge and routing | Three roles: GatewayClass, Gateway, HTTPRoute |
| Ownership | Single user, no team boundaries | Platform owns edge, apps own routes |
| Advanced features | Vendor annotations, not portable | Typed spec fields, portable |
| Traffic splitting | Annotation-based, controller specific | Native backendRefs weights |
| Cross-namespace routing | Not supported cleanly | Explicit allowedRoutes and ReferenceGrant |
| Project status | Feature-frozen, still GA | Active development, stable v1.5.x |
The good news is that Ingress and the Gateway API can run side by side in the same cluster, so you migrate one service at a time. The Kubernetes SIG-Network team also shipped ingress2gateway 1.0 in March 2026, a CLI that reads your existing Ingress resources and generates equivalent Gateway and HTTPRoute manifests, including translation of more than thirty common ingress-nginx annotations. It is a starting point, not a rubber stamp: always review the output.
Do not treat the Gateway API as a drop-in that only your networking team touches. Its whole value is the ownership split, so decide up front which team owns GatewayClass and Gateway and which namespaces get HTTPRoute access. If you skip that conversation, you will recreate the old bottleneck with new YAML.
If you are on ingress-nginx, yes, and with some urgency, because it no longer receives security patches after its March 2026 end of life. If you run a managed cloud Ingress or another controller that is still supported, you have more time, but the direction of travel is settled: the Ingress spec is frozen and every new networking feature is landing in the Gateway API. For anything greenfield, I would not start a new cluster on Ingress in 2026. Start on the Gateway API, get the role boundaries right on day one, and skip the annotation-soup phase entirely.