Migrating from NGINX Ingress Controller to HAProxy: A Step-by-Step Guide
The Kubernetes community announced the retirement of Ingress NGINX with best-effort maintenance ending March 2026. This guide walks you through a safe, tested migration path to HAProxy Kubernetes Ingress Controller—with code examples, annotation mappings, and production tips.
⚠️ Important: The Kubernetes SIG Network and Security Response Committee announced that Ingress NGINX will be retired in March 2026. After this date, there will be no security patches, bug fixes, or new releases. Existing deployments will continue to function, but running unmaintained infrastructure in production carries significant risk.
If you’re using ingress-nginx today, now is the time to plan your migration. In this post, I’ll walk you through migrating to the HAProxy Kubernetes Ingress Controller—a production-ready, high-performance alternative with a clear migration path.
🔗 Sources:
- Kubernetes Blog: Ingress NGINX Retirement
- HAProxy: Ingress NGINX Is Retiring
- HAProxy Migration Assistant
Why Migrate? The Ingress NGINX Retirement Timeline
| Date | Milestone |
|---|---|
| Nov 2025 | Retirement announcement by Kubernetes SIG Network & SRC |
| Mar 2026 | Best-effort maintenance ends; no more releases or security fixes |
| Post-Mar 2026 | Repositories become read-only; artifacts remain available |
✅ Good news: Your existing
ingress-nginxdeployments won’t break. But without security updates, you’ll accumulate technical debt and exposure to newly discovered vulnerabilities.
Why HAProxy?
HAProxy isn’t just a “drop-in replacement”—it’s an upgrade:
- 🚀 2× higher throughput with lower CPU usage (verified in public benchmarks)
- 🔐 Safer configuration model: No arbitrary config snippets; structured annotations and CRDs
- ♻️ Zero-downtime reloads: Apply config changes without dropping connections
- 📊 Rich native Prometheus metrics—no sidecars required
- 🌐 First-class Layer 4 + Layer 7 support: TCP, gRPC, HTTP/S, WebSocket
- 🆓 100% open source, with optional enterprise support via HAProxy One
Migration Strategy: 4 Phases to Zero Downtime
Phase 1: Assess Your Current Setup
First, confirm you’re using Ingress NGINX:
kubectl get pods --all-namespaces \
--selector app.kubernetes.io/name=ingress-nginx
Then inventory your annotations:
kubectl get ingress -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations}{"\n"}{end}' \
| grep nginx.ingress.kubernetes.io
Phase 2: Deploy HAProxy Ingress Controller in Parallel
Install HAProxy alongside your existing controller—no disruption required.
# Add the HAProxy Helm repo
helm repo add haproxytech https://haproxytech.github.io/helm-charts
helm repo update
# Install in a dedicated namespace
helm install haproxy-ingress haproxytech/kubernetes-ingress \
--namespace haproxy-controller \
--create-namespace \
--set controller.ingressClass=haproxy \
--set controller.service.type=LoadBalancer \
--set controller.replicaCount=2
Phase 3: Migrate Ingress Resources (With Examples)
Before (NGINX):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- my-app.tld
secretName: my-app-tls
rules:
- host: example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
After (HAProxy):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: haproxy
haproxy.org/path-rewrite: / # ← rewrite-target equivalent
haproxy.org/ssl-redirect: "true" # ← ssl-redirect equivalent
spec:
tls:
- hosts:
- my-app.tld
secretName: my-app-tls
rules:
- host: example.com
http:
paths:
- path: /app
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
| Nginx | HAproxy |
|---|---|
| nginx.ingress.kubernetes.io/load-balance | haproxy.org/load-balance |
| nginx.ingress.kubernetes.io/backend-protocol | haproxy.org/backend-protocol |
| nginx.ingress.kubernetes.io/proxy-connect-timeout | haproxy.org/proxy-connect-timeout |
| nginx.ingress.kubernetes.io/cors-allow-origin | haproxy.org/cors-allow-origin |
| nginx.ingress.kubernetes.io/affinity | haproxy.org/affinity |