If your Kubernetes cluster routes traffic with the community Ingress-NGINX controller, it is running unmaintained software. The Kubernetes project announced its retirement in November 2025, and best-effort maintenance ended in March 2026. There are no more releases or security fixes, and an ingress controller is one of the most exposed components in a cluster.

The recommended path is Gateway API, the newer Kubernetes standard for traffic routing. This guide explains the model and walks through a low-risk migration.

First, check whether you are affected

The retirement covers the community kubernetes/ingress-nginx project. It does not cover the separate NGINX Ingress Controller maintained by F5/NGINX. Find out which one you run:

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

If you see pods from the ingress-nginx chart, or an IngressClass with the controller k8s.io/ingress-nginx, this guide applies to you.

Gateway API in plain language

The old Ingress resource packed everything into one object and relied on controller-specific annotations for anything beyond simple routing. Gateway API splits responsibilities into separate resources:

  • GatewayClass: which implementation runs the gateways, installed by the platform team.
  • Gateway: the actual entry point, with listeners, ports, hostnames and TLS certificates. Usually owned by the platform team.
  • HTTPRoute: routing rules from paths and headers to Services. Owned by application teams.

Features that needed annotations before, such as header matching, traffic splitting and redirects, are part of the standard API now, so routes are portable between implementations.

Choose an implementation

Gateway API is a specification; you still need a controller. Popular conformant options include Envoy Gateway, Istio, Cilium, kgateway, Traefik and NGINX Gateway Fabric, plus managed gateways on GKE, EKS and AKS. Choose based on what your team already runs, conformance level, and support. Install the Gateway API CRDs and your chosen controller alongside Ingress-NGINX; do not remove anything yet.

Convert your Ingresses with ingress2gateway

The Kubernetes SIG Network tool ingress2gateway reached 1.0 in March 2026. Earlier versions understood only three Ingress-NGINX annotations; 1.0 converts more than 30. It reads Ingress resources and prints equivalent Gateway API resources.

bash
ingress2gateway print --providers=ingress-nginx \
  --all-namespaces > gateway-resources.yaml

The output contains a Gateway and HTTPRoutes. An example of a converted route:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop
  namespace: shop
spec:
  parentRefs:
    - name: public-gateway
      namespace: gateway-system
  hostnames:
    - shop.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: shop-api
          port: 8080

Treat the output as a draft, not a finished migration. Read every file before applying it.

What the tool cannot convert

  • Raw NGINX snippets such as configuration-snippet and server-snippet. These are flagged as unsupported. Find out what each snippet does and replace it with a Gateway API feature or a policy resource from your implementation. Snippets were also a common source of security issues, so this is a good time to remove them.
  • cert-manager settings. The tool does not know which ClusterIssuer you want, so add certificates to the Gateway listeners yourself.
  • Implementation-specific behaviour, such as default timeouts, body size limits and regex path handling, which may differ between controllers.

Migrate with both stacks running

Do not switch everything at once. A safe sequence:

  1. Install the new controller and create the Gateway with its own load balancer address.
  2. Apply the converted HTTPRoutes. Both controllers now serve the same apps on different addresses.
  3. Test each hostname against the new address, for example with curl --resolve shop.example.com:443:<new-ip> https://shop.example.com/.
  4. Move DNS one hostname at a time, starting with low-risk services, with a short TTL so you can roll back quickly.
  5. Watch error rates and latency for each service after it moves.
  6. Delete the Ingress resources and uninstall Ingress-NGINX only when all traffic has moved.

Check route status

Gateway API resources report whether they were accepted. This is often the fastest way to find a mistake:

bash
kubectl describe httproute shop -n shop

Look at the Accepted and ResolvedRefs conditions. A route that references a Service in another namespace also needs a ReferenceGrant in that namespace; without it, ResolvedRefs is false.

Lock down who can attach routes

Because the Gateway and routes are separate, decide which namespaces may attach routes to a shared Gateway. Use allowedRoutes on each listener, for example to allow only namespaces with a specific label. This replaces informal conventions with an enforced boundary between platform and application teams.

Key takeaways

  • The community Ingress-NGINX controller is retired and no longer receives security fixes.
  • Gateway API separates infrastructure (Gateway) from routing (HTTPRoute) and standardises features that needed annotations.
  • ingress2gateway 1.0 converts most common annotations but not raw snippets or cert-manager settings.
  • Run old and new controllers side by side and move DNS one hostname at a time.
  • Use route status conditions and allowedRoutes to debug and secure the new setup.

Sources: Announcing Ingress2Gateway 1.0, Gateway API documentation, GKE: migrate Ingress to Gateway API.