Migrating from NGINX Ingress Controller to Traefik on OVHcloud Managed Kubernetes
Find out how to migrate from NGINX Ingress Controller to Traefik on your OVHcloud MKS cluster with zero downtime
Objective
The Kubernetes NGINX Ingress Controller project has announced its retirement in March 2026. This guide helps OVHcloud Managed Kubernetes Service (MKS) users migrate from NGINX Ingress Controller to Traefik with zero downtime, covering OVHcloud-specific considerations.
Traefik v3.6.2+ includes a Kubernetes Ingress NGINX provider that automatically translates NGINX annotations into native Traefik configuration. Your existing Ingress manifests with ingressClassName: nginx therefore work immediately, without modification.
This guide focuses on OVHcloud-specific configurations. For the complete migration procedure, refer to the official Traefik nginx-to-traefik migration guide.
For a broader perspective on the transition from Ingress to Gateway API, read the OVHcloud blog post: Moving beyond Ingress: Why should OVHcloud MKS users start looking at the Gateway API.
This guide applies to MKS clusters running Kubernetes version 1.31 or later, which use the Public Cloud Load Balancer (OpenStack Octavia) by default.
Before you begin
This tutorial assumes that you already have:
- a working OVHcloud Managed Kubernetes Service cluster (version >= 1.31)
- the NGINX Ingress Controller deployed and serving traffic
kubectlandhelmCLI tools installed with cluster admin permissions- DNS access to update records for your services
We recommend creating backups before starting:
You should also be familiar with:
- Expose your applications using OVHcloud Public Cloud Load Balancer
- Getting the source IP behind the LoadBalancer
OVHcloud-specific considerations
Load Balancer (OpenStack Octavia)
On MKS clusters >= 1.31, the Public Cloud Load Balancer (based on OpenStack Octavia) is the default Load Balancer. Octavia operates at Layer 4 (TCP/UDP), meaning:
- TLS termination is handled by Traefik, not by the Load Balancer.
- Layer 7 routing (host-based, path-based) is handled by Traefik.
- Octavia provides health checking, Floating IP management, and traffic distribution.
You can optionally choose the Load Balancer size using the annotation loadbalancer.openstack.org/flavor-id (MKS Standard only; MKS Free uses loadbalancer.ovhcloud.com/flavor). If not specified, the default size is small. To list available flavors, install and configure the OVHcloud CLI and run ovhcloud cloud reference loadbalancer list-flavors <REGION>. For more details, see the Expose your applications using OVHcloud Public Cloud Load Balancer guide.
Proxy Protocol and source IP preservation
To preserve the client's source IP behind the Load Balancer, you must enable Proxy Protocol v2 between Octavia and Traefik. This requires configuration on both sides:
On the Load Balancer side (Service annotation):
On the Traefik side (Helm values), you must configure Traefik to accept Proxy Protocol and trust the Load Balancer IPs:
- Public network clusters: use the egress IPs from the Load Balancer annotation:
- Private network clusters: use your subnet CIDR range (e.g.,
10.0.0.0/20).
You must also set externalTrafficPolicy: Local on the Traefik Service to prevent source IP masquerading through inter-node SNAT.
CNI considerations
If you have NetworkPolicies targeting NGINX Ingress pods (labels, ports), you will need to update them to match Traefik's labels (app.kubernetes.io/name: traefik) and ports.
Step 1 - Install Traefik alongside NGINX
Add the Traefik Helm repository:
Create a traefik-values.yaml file adapted for OVHcloud MKS:
a. Public network clusters
b. Private network clusters
Install Traefik:
Verify both controllers are running:
The key configuration providers.kubernetesIngressNginx.enabled: true tells Traefik to watch for Ingress resources with ingressClassName: nginx and automatically translate NGINX annotations into native Traefik configuration. This requires Traefik v3.6.2 or later.
Step 2 - Verify Traefik handles traffic
Get the LoadBalancer IPs for both controllers:
Test your application through both controllers using curl --connect-to to bypass DNS:
Both commands should return the same response. Also verify that the source IP is correctly preserved in the X-Real-IP or X-Forwarded-For headers.
Check Traefik logs for Ingress discovery:
Step 3 - Shift traffic to Traefik (DNS-based)
The recommended approach is a DNS-based migration:
- Add the Traefik IP to your DNS records alongside the NGINX IP (round-robin).
- Monitor traffic on both controllers to ensure Traefik handles requests correctly.
- Remove the NGINX IP from your DNS records.
- Wait 24-48Â hours for DNS caches to expire before proceeding to the next step.
Some ISPs ignore DNS TTL values, caching records longer than specified. Keep NGINX running for at least 24-48Â hours after removing it from DNS to avoid dropping traffic.
We recommend reducing your DNS TTL to 300Â seconds (5Â minutes) before starting the migration. For detailed DNS switch instructions, see How to perform a DNS switch.
Step 4 - Retain the LoadBalancer Floating IP (OVHcloud-specific)
If you want Traefik to use the same IP as NGINX (to avoid DNS changes), follow this procedure:
- Ensure the
keep-floatingipannotation is set on both services:
-
Ensure Traefik is receiving traffic (via its own IP or DNS round-robin).
-
Delete the NGINX LoadBalancer service to release the Floating IP:
- Update
traefik-values.yamlto claim the released Floating IP:
- Upgrade Traefik:
- Verify Traefik claimed the IP:
Step 5 - Uninstall NGINX Ingress Controller
Preserve the IngressClass
The nginx IngressClass must survive the NGINX uninstallation for Traefik to continue discovering your Ingress resources.
If NGINX was installed via Helm, add the preservation annotation:
The --reuse-values flag is critical: it preserves all your existing NGINX configuration during this annotation update.
Delete admission webhooks
Uninstall NGINX
Verify the IngressClass is preserved
You should see the nginx IngressClass still present.
Clean up
Next steps: Gateway API
While Traefik with the NGINX Ingress provider is a suitable immediate solution, we recommend migrating to the Kubernetes Gateway API in the long term. Traefik natively supports Gateway API resources (HTTPRoute, TLSRoute, GRPCRoute, TCPRoute).
The recommended migration path is:
NGINX Ingress (current) → Traefik with NGINX provider (this guide) → Traefik with Gateway API
For more details on Gateway API with OVHcloud MKS, read the blog post: Moving beyond Ingress: Why should OVHcloud MKS users start looking at the Gateway API.
Troubleshooting
Ingresses not discovered by Traefik
Source IP not preserved
- Verify Proxy Protocol is enabled on the Service:
loadbalancer.openstack.org/proxy-protocol: "v2". - Verify
externalTrafficPolicy: Localis set on the Traefik Service. - Verify Traefik's
proxyProtocol.trustedIPsmatch your Load Balancer egress IPs (public clusters) or subnet CIDR (private clusters). - Check the
X-Real-IPandX-Forwarded-Forheaders in your application responses.
LoadBalancer IP not assigned
Verify that the Floating IP you are trying to claim is not still allocated to another service.
TLS certificates not working
Traefik terminates TLS using the secrets referenced in your Ingress spec.tls entries. Ensure that:
- TLS secrets exist in the same namespace as the Ingress.
- secrets contain valid
tls.crtandtls.keydata.
Go further
Official Traefik migration guide: Migrating from NGINX to Traefik
OVHcloud blog: Moving beyond Ingress
Expose your applications using OVHcloud Public Cloud Load Balancer
Getting the source IP behind the LoadBalancer
Traefik HTTP Middlewares (replacement for NGINX annotations)
Visit our dedicated Discord channel: https://discord.gg/ovhcloud. Ask questions, provide feedback and interact directly with the team that builds our Containers and Orchestration services.
For training or technical assistance implementing our solutions, contact your sales representative or visit our Professional Services page to request a quote and have your project analysed by our experts.
Join our community of users.