Skip to main content

Command Palette

Search for a command to run...

Migrating from Ingress NGINX to Gateway API : something to be afraid of ?

Updated
5 min read
Migrating from Ingress NGINX to Gateway API : something to be afraid of ?

The CNCF has recently announced a major transition: Ingress Nginx, the “de facto” considered ingress controller, will officially reach end-of-life in March 2026.

Official source here : https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/#:~:text=In%20March%202026%2C%20Ingress%20NGINX,and%20left%20available%20for%20reference.

Of course, it will still be possible to use it but it will no longer receive maintenance, patches or security updates.

The reason are quite simple. The traditional Ingress API:

  • Only exposes hostnames, paths, and backends

  • Does not handle advanced TLS scenarios

  • Does not offer traffic policies or advanced L7 behavior

  • Cannot support multi-tenant or complex routing without an overload of annotations

  • Annotations (while powerful) became difficult to maintain, inconsistent, and controller specific.

So, what should we do to avoid CVEs and upcoming troubles ? The answer is quite clear : use a new standard, Gateway API.

In fact, that’s not a new concept : the Gateway API appeared in 2020 and a lot of controllers appeared from 2021 (Envoy, Istio, Nginx via their own provider, Cilium) and started to be massively used since 2022.

Gateway API is a new architecture, not a drop-in replacement

This new approach introduces a richer and more structured model with objects such as:

  • GatewayClass

  • Gateway

  • HTTPRoute, TCPRoute, GRPCRoute, etc.

This brings far better separation of concerns compared to Ingress.

New features to implement more advanced traffic control

Gateway API supports various features such as:

  • Header matching

  • Weighted routing (example here)

  • Traffic splitting (for blue / green or canary)

  • Multi-listener setups

  • Better TLS configuration

  • Multi-protocol routing

With Ingress, enabling the same functionalites usually required multiple and controller-specific annotations.

Support for diverse traffic types

Gateway API handles not only HTTP, but also:

  • gRPC

  • TCP

  • TLS passthrough

  • UDP (via implementations that support it)

Ingress is fundamentally HTTP-centric and lacks this protocol diversity.

A practical, real-world migration path: Ingress NGINX to Envoy Gateway

So, now, let’s switch to the best part: a practical (and rollback friendly) way to go from Ingress Nginx to Envoy Gateway. We choose Envoy for this example but we could have chosen Istio, Kong, Traefik, and many more.

Step 1 — Install Envoy Gateway

helm install eg oci://docker.io/envoyproxy/gateway-helm \
    --version v1.6.0 \
    -n envoy-gateway-system \
    --create-namespace

We choose to use Envoy Gateway to become the control-plane responsible for processing Gateway API.

It’s quite simple to install with the helm install command.

Step 2 — Create a GatewayClass

We now have to create an GatewayClass

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: gatewayclass1
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

This ensures that all converted resources referencing gatewayClassName: gatewayclass1 are correctly handled by Envoy Gateway.

Step 3 — convert your objects with ingress2gateway

This tool scans existing Ingress objects and generates Gateway API equivalents:

  • Gateway

  • HTTPRoute

  • BackendRefs

  • TLS references

  • Host rules

The project code sources are available here:

https://github.com/kubernetes-sigs/ingress2gateway

To install it, just run this command

go install github.com/kubernetes-sigs/ingress2gateway@latest

Once it’s install, you can run this command to first get the converted resources taken from your ingress related objects and thenmove it to api Gateway objects.

In this example, we took the objects from our "gitlab” namespace.

#first, list
/root/go/bin/ingress2gateway print \
    --namespace gitlab \
    --providers ingress-nginx 

#then,  apply
/root/go/bin/ingress2gateway print \
    --namespace gitlab \
    --providers ingress-nginx \
    | kubectl apply -f -

Expected output:

  • A new Gateway resource in the target namespace

  • A set of HTTPRoute objects matching the original ingress rules

  • Listeners and TLS configured under the Gateway

  • Routing logic now controlled by Envoy Gateway

Final step — Verify IP assignment and Gateway readiness

Run this command to list the gateways and services.

kubectl get gateways -A
kubectl get svc -A | grep envoy

This should confirm that:

  • The Gateway shows PROGRAMMED=True , meaning that the gateway is ready and running

  • An IP is assigned via LoadBalancer (or any IP provider, for example MetalLB)

  • Routes are attached to the appropriate listeners

  • DNS or host file entries point to the correct address

Warning: This will not simply “move” your existing Ingress resources into the Gateway API. As explained earlier, this process is reversible because we are not deleting the existing Ingress objects. This means that the new LoadBalancer services created by the Gateway will receive new IP addresses and will not replace the existing Ingress LoadBalancers!

If you need to keep the same IP address, just edit que “loadBalancerIP” parameter in your LoadBalancer services. If you’re using Metallb, don’t forget to restart your controller pod in order to avoid IP attribution errors.

Lessons learned during the migration

Here’re different aspect to care about when preparing your gateway API adoption.

Gateway listeners must include all hostnames

If the Gateway does not list a hostname, Envoy will reject the traffic, even if the HTTPRoute is valid.

TLS is configured on the Gateway, not the HTTPRoute

This is a key difference from Ingress and a common migration pitfall. Here’s the example we used to reference our secret.

Namespace scoping matters

allowedRoutes: Same restricts routes to the Gateway’s namespace.
Incorrect scoping causes silent routing failures.

Ingress2gateway accelerates the process but a manual review is still required

Of course, this tool is very useful and helps to gain a lot of time when enabling gateway APIs, but don’t trust it too much. You need to check all your objects with validations including:

  • Correct backends

  • Correct hostnames

  • Presence of path / matchers

  • TLS secret validity

  • Route-to-listener alignment