Migrate from one ingress controller to another#
Why migrate ingress controllers?#
In 2026, the policy of best-effort maintenance of the Ingress NGINX Controller ended. Following the announcement of this plan, a considerable amount of discussion has taken place amongst Kubernetes users around the topic of a replacement.
In the near term, 2i2c has decided to migrate to the official NGINX Ingress Controller. This is likely not a “permanent” solution — alongside the Ingress NGINX Controller deprecation, the Kubernetes Ingress API itself is also frozen, with the Kubernetes project recommending the Gateway API instead. Although there has not been an announcement that the Ingress API will become deprecated in future, we may need/want to migrate to the Gateway API down the road.
Note
Concerns with ingress migration
Naively using the provided LoadBalancer (LB) from each ingress controller requires the update of DNS records to migrate domains from one LB to another. During this time, the cluster infrastructure will be unavailable to some of external users.
When migrating between controllers, we also want to avoid re-issuing TLS certificates, which are a “costly” resource.
How to migrate from Ingress NGINX Controller#
To facilitate zero downtime migration between controllers, we have introduced a new LoadBalancer ingress service. The purpose of this service is to provide a static external IP address that lives independently of the ingress controller. Consequently, we no longer need ingress controllers to create their own LBs — we can use simple clusterIP services.
For clusters that are still running Ingress NGINX Controller, the existing DNS records point to the controller-managed LoadBalancer service external IP. To migrate between two ingress controllers ingress-nginx and nginx-ingress, we must perform two separate migrations:
Migrate DNS records to dedicated LoadBalancer service#
We recently updated the support chart to enable the LoadBalancer service on all hubs. In this phase, we must migrate the DNS records for the cluster to the cluster-entrypoint LoadBalancer external IP. We can easily lookup the LB hostname with:
kubectl --namespace=support get service/cluster-entrypoint --template='{{$ingress := (index .status.loadBalancer.ingress 0)}}{{or $ingress.hostname $ingress.ip}}'
We must migrate the DNS records for the domain to point to this external IP. During the migration, both the “new” LB and existing ingress-nginx owned LB must be available.
Switch to official nginx-ingress controller#
Once the DNS records have been updated to point to the cluster-entrypoint LB, we can safely transition to the official ingress-nginx service:
Enable the
nginx-ingressservice in the support chart withnginx-ingress: # Enable controller enabled: true controller: ingressClass: # Claim the `nginx` ingress class create: true
Disable the
ingress-nginxcontroller:ingress-nginx: controller: # Turn off controller replicaCount: 0 # Let go of the `nginx` ingress class ingressClassResource: enabled: false
Point the
cluster-entrypointLB to the newnginx-ingressservice:clusterEntrypoint: targetController: nginx-ingress
How to handle future migrations#
Once all clusters are using the cluster-entrypoint LB for their DNS records, it should be trivial to migrate to a new ingress controller or Gateway that establishes a clusterIP service. Once a new controller/gateway is introduced, simply point the cluster-entrypoint LB at the new service pods.