For years, the Kubernetes Ingress object was the de facto way to expose services to the outside world. But as traffic patterns got more complex — path-based routing, weighted canary splits, header-based routing, and multiple ingress controllers — the classic Ingress API started to show its seams. In 2026, the Kubernetes Gateway API has officially reached GA for most core resources and is rapidly becoming the standard way SMBs route traffic into their clusters. If you’re still glued to nginx-ingress annotations, this guide will show you why — and how — to make the switch.
Why Gateway API Is Replacing Ingress
The original Ingress API was designed when Kubernetes had just a handful of users and one or two ingress controllers. It could only express a limited set of routing rules, and every controller vendor built its own proprietary annotations to fill the gaps. The result? Your Ingress config was locked to your controller, and advanced routing meant copying magic strings from vendor docs.
Gateway API fixes this with a role-based, expressive, and vendor-neutral model built around three core concepts:
- Gateway — the infrastructure itself (the load balancer, one or more listeners/ports).
- GatewayClass — the controller that implements the Gateway (e.g.,
nginx,traefik,istio,cilium). - HTTPRoute (and TCPRoute, TLSRoute, UDPRoute) — the routing rules that attach to a Gateway.
This separation means a platform team defines the infrastructure, while application teams define the routes — a clean boundary that maps perfectly to a DevOps/SRE operating model.
Core Concepts: Gateway, GatewayClass, and HTTPRoute
Let’s look at a real example. First, define a GatewayClass to say which controller implements the gateway:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
Next, define the Gateway itself — the actual load balancer listening on a port:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: public-gateway
namespace: infra
spec:
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
tls:
certificateRefs:
- name: wildcard-tls
Now the app team attaches an HTTPRoute — no annotations, no controller-specific magic:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shop-routes
namespace: shop
spec:
parentRefs:
- name: public-gateway
namespace: infra
hostnames:
- shop.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: shop-api
port: 8080
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: shop-web
port: 3000
Notice that Gateway and HTTPRoute live in different namespaces. This is the role-based model in action: the platform team owns infra/public-gateway, and the app team owns its routes. No cross-team bikeshedding, no conflicting annotation wars.
Canary Deployments and Traffic Splitting Without Custom Annotations
One of the biggest wins for SMBs is built-in traffic splitting. With classic Ingress, canary releases meant installing a dedicated canary ingress controller and copying vendor annotations. With Gateway API, it’s just fields on the route:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shop-routes
namespace: shop
spec:
parentRefs:
- name: public-gateway
namespace: infra
hostnames:
- shop.example.com
rules:
- backendRefs:
- name: shop-web-v2
port: 3000
weight: 10
- name: shop-web
port: 3000
weight: 90
Here 10% of traffic goes to shop-web-v2 and 90% to the stable shop-web. When your canary passes the error budget check, bump the weight to 100 and cut over. Combined with a GitOps tool like Argo CD, this becomes a fully declarative, auditable progressive-delivery workflow that any lean DevOps team can operate.
You can also add header-based routing to send only internal testers to the canary:
- matches:
- headers:
- name: x-canary
value: "true"
backendRefs:
- name: shop-web-v2
port: 3000
Moving from Ingress to Gateway API: A Migration Path
Don’t rip out your Ingress resources overnight. The cleanest migration is to run both in parallel while you progressively migrate traffic. Most mature ingress controllers (nginx-ingress, Traefik, Istio ingress, Cilium) now support the Gateway API, so you can point both at the same underlying load balancer.
A pragmatic rollout looks like this:
- Audit: List every Ingress resource and its routes:
kubectl get ingress -A - Install a Gateway API–compliant controller and create your
GatewayClass+Gateway. - Migrate one namespace at a time: translate each
Ingressinto anHTTPRouteand attach it to the new Gateway. - Validate: confirm traffic flows, then delete the old Ingress resource in that namespace.
- Cut over DNS/load balancer when the Gateway has taken over all namespaces.
Here’s a handy one-liner to see which Ingress objects still exist so you don’t leave stragglers behind:
kubectl get ingress -A --no-headers | wc -l
kubectl get httproute -A --no-headers | wc -l
Migration is the ideal time to consolidate. If you have five separate Ingress controllers, replacing them with one Gateway-based controller immediately reduces your operational surface — a small but meaningful step in the fight against tool sprawl.
TLS, Certificates, and Real-World Gotchas
A few things trip up teams during migration:
- Wildcard listeners conflict: Gateway validates
hostnamesagainst listener ports. If two routes on the same listener claim overlapping hostnames, the more specific match wins — but overlapping*.example.comroutes can silently shadow each other. Usekubectl get httproute -A -o jsonpath='{.items[*].spec.hostnames}'to audit. - TLS lives on the Gateway, not the route. Certificate management moves up to the platform layer, which is actually great for SMBs — one team rotates certs centrally instead of every app team reinventing it.
- Not every controller supports every route type. Check your controller’s supported features table before promising HTTPRoute, TCPRoute, and GRPCRoute support to your teams.
If you’re pairing this with a service mesh, Gateway API integrates tightly with the mesh’s inbound traffic handling, giving you a single, standards-based way to express both mesh ingress and east-west routing — worth reviewing before you standardize. Check out our deep dive on when a service mesh makes sense for your SMB.
Is Now the Right Time to Move?
If your cluster is small, your routing is simple, and your nginx Ingress “just works,” the Gateway API may not be urgent. But if you’re layering on canary releases, multi-tenancy, team boundaries, or multiple entry points, the migration pays for itself quickly in reduced config complexity and fewer controller-specific hacks. The Gateway API is also the path forward — Ingress is in maintenance mode, and the ecosystem is consolidating around the new standard.
Migrating your traffic layer is a perfect “safe deployment” project: it’s incremental, reversible, and you can validate every namespace independently before cutting over. If you’d like a hand planning the rollout for your cluster, our engineers can help you move safely without the all-weekend guessing game that used to be the norm for infrastructure rewrites. Book a free architecture review today and let’s get your ingress on solid, standards-based footing.