Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

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.

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:

  1. Enable the nginx-ingress service in the support chart with

    nginx-ingress:
      # Enable controller
      enabled: true
      controller:
        ingressClass:
          # Claim the `nginx` ingress class
          create: true
  2. Disable the ingress-nginx controller:

    ingress-nginx:
      controller:
        # Turn off controller
        replicaCount: 0
        # Let go of the `nginx` ingress class
        ingressClassResource:
          enabled: false
  3. Point the cluster-entrypoint LB to the new nginx-ingress service:

    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.