Breaking: NGINX Ingress Controller Reaches End of Life
The Kubernetes Security Response Committee and SIG Network have announced that Ingress NGINX will be fully retired in March 2026, with no further releases, bugfixes, or security vulnerability updates afterward. This decision impacts an estimated 40-62% of all Kubernetes clusters worldwide, making it one of the most significant infrastructure changes in Kubernetes history.
If you’re running Kubernetes in production, this announcement demands immediate attention. Your ingress controller powers every external request to your applications, and running unmaintained infrastructure with known security vulnerabilities is not an option.
Why Is NGINX Ingress Being Retired?
The breadth and flexibility of Ingress NGINX has caused maintenance challenges, and what were once considered helpful options have sometimes come to be considered serious security flaws, such as the ability to add arbitrary NGINX configuration directives via the “snippets” annotations.
The reality is stark: Ingress NGINX has always struggled with insufficient or barely-sufficient maintainership, with only one or two people doing development work on their own time, after work hours and on weekends. The technical debt has become insurmountable, and the Kubernetes community has exhausted efforts to find sustainable support.
Key factors behind the retirement:
- Insufficient maintainership: Years of running on volunteer weekend work
- Security concerns: Features like configuration snippets have become attack vectors
- Technical debt: Flexibility turned into unmanageable complexity
- Sustainability: The maintenance burden permanently exceeds contribution rates
Immediate Impact and Timeline
Here’s what you need to know right now:
Current Status (November 2025)
- Best-effort maintenance continues
- No new features being added
- Critical security patches only
March 2026 - Full Retirement
- No more releases or updates
- No security patches for new vulnerabilities
- GitHub repositories become read-only
- Existing installations continue working (but unpatched)
Your Action Timeline
- NOW - December 2025: Complete assessment and planning
- January 2026: Test migrations in staging environments
- February 2026: Execute production migrations
- March 2026: Finalize all migrations before retirement
Step 1: Verify If You’re Using Ingress NGINX
Before panicking, confirm whether you’re actually using ingress-nginx. Run this command with cluster admin permissions:
kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx
If you see pods returned, you’re using ingress-nginx and need to migrate.
Additional verification commands:
# Check ingress class
kubectl get ingressclass
# List all ingress resources
kubectl get ingress --all-namespaces
# Check Helm releases
helm list --all-namespaces | grep ingress-nginx
Step 2: Assess Your Current Configuration
Document your existing setup before making any changes:
# Export all ingress resources
kubectl get ingress --all-namespaces -o yaml > ingress-backup.yaml
# Export ingress-nginx configuration
kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml > nginx-config-backup.yaml
# Document custom annotations used
kubectl get ingress --all-namespaces -o json | jq '.items[].metadata.annotations'
# Check for custom snippets (security risk)
kubectl get ingress --all-namespaces -o json | jq '.items[] | select(.metadata.annotations | to_entries[] | select(.key | contains("snippet")))'
Create an inventory spreadsheet with:
- All ingress resources and their namespaces
- Custom annotations being used
- TLS/SSL certificate configurations
- Rate limiting and authentication rules
- Custom NGINX configuration snippets
- External dependencies (cert-manager, external-dns, etc.)
Step 3: Choose Your Migration Path
The Kubernetes community recommends several alternatives. Here’s how to choose:
Option 1: Gateway API with Envoy Gateway (Recommended)
Best for: Future-proof infrastructure, CNCF-backed projects, teams wanting modern standards
Gateway API is the official successor to Ingress, offering better functionality and CNCF backing.
Advantages:
- Official Kubernetes networking API
- Role-oriented design (Infrastructure vs. Application teams)
- More expressive than Ingress
- Growing ecosystem support
- CNCF project with strong backing
Migration Complexity: Medium to High (API paradigm shift)
Option 2: Cloud-Native Solutions
Best for: Cloud-hosted clusters, teams preferring managed services
- AWS: AWS Load Balancer Controller
- Azure: Azure Application Gateway Ingress Controller
- GCP: GKE Ingress
- DigitalOcean: DigitalOcean Load Balancer
Advantages:
- Tight cloud integration
- Managed and maintained by cloud providers
- Native features (WAF, DDoS protection)
- Zero maintenance overhead
Migration Complexity: Low to Medium
Option 3: Alternative Ingress Controllers
Best for: Teams wanting minimal changes, specific feature requirements
Popular alternatives include:
- Traefik: Modern, feature-rich, excellent for microservices
- HAProxy Ingress: Best performance, proven reliability
- Kong Ingress: API gateway features, enterprise support
- Contour: Envoy-based, VMware-backed
- F5 NGINX Ingress Controller: Commercial support, NGINX Plus features
Migration Complexity: Low (similar concepts to ingress-nginx)
Step 4: Migration to Gateway API (Detailed Steps)
Here’s a complete migration guide for moving to Gateway API with Envoy Gateway:
Install Envoy Gateway
# Install Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# Install Envoy Gateway
helm repo add envoy-gateway https://gateway.envoyproxy.io
helm repo update
helm install eg envoy-gateway/gateway-helm --namespace envoy-gateway-system --create-namespace
Create Gateway Resource
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg-gateway
namespace: default
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-secret
allowedRoutes:
namespaces:
from: All
Convert Ingress to HTTPRoute
Before (Ingress):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubeace-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: app.kubeace.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
tls:
- hosts:
- app.kubeace.com
secretName: tls-secret
After (HTTPRoute):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: kubeace-app
spec:
parentRefs:
- name: eg-gateway
namespace: default
hostnames:
- "app.kubeace.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
Handle Common Annotations
URL Rewriting:
# Ingress annotation: nginx.ingress.kubernetes.io/rewrite-target: /$2
# Gateway API equivalent:
rules:
- matches:
- path:
type: RegularExpression
value: /old(/.*)?
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /new
Rate Limiting:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: rate-limit-policy
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: kubeace-app
rateLimit:
type: Local
local:
rules:
- limit:
requests: 100
unit: Minute
CORS Configuration:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy
metadata:
name: cors-policy
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: kubeace-app
cors:
allowOrigins:
- "https://kubeace.com"
allowMethods:
- GET
- POST
allowHeaders:
- "*"
Step 5: Migration to Traefik (Alternative Path)
For teams preferring an Ingress-compatible controller:
Install Traefik
# Add Traefik Helm repository
helm repo add traefik https://traefik.github.io/charts
helm repo update
# Install Traefik
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set ports.web.redirectTo.port=websecure
Update Ingress Resources
The good news: Most Ingress resources work with minimal changes.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubeace-app
annotations:
# Change ingress class
kubernetes.io/ingress.class: traefik
# Traefik-specific annotations (optional)
traefik.ingress.kubernetes.io/router.middlewares: default-redirect-https@kubernetescrd
spec:
# Or use ingressClassName field
ingressClassName: traefik
rules:
- host: app.kubeace.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
Create Middleware for Advanced Features
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
spec:
rateLimit:
average: 100
burst: 50
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
spec:
redirectScheme:
scheme: https
permanent: true
Common Migration Challenges and Solutions
Challenge 1: Custom NGINX Configuration Snippets
Problem: Snippets won’t work in Gateway API or other controllers.
Solution:
- Identify all ingresses using snippets:
kubectl get ingress -A -o json | jq '.items[] | select(.metadata.annotations | to_entries[] | select(.key | contains("snippet")))' - Reimplement using native features of new controller
- For Gateway API, use Envoy filters or Extension APIs
- For Traefik, use Middleware resources
- Document and test each custom configuration
Challenge 2: Rate Limiting Migration
Problem: NGINX rate limiting annotations need conversion.
Solution:
# Gateway API - BackendTrafficPolicy
# Traefik - Middleware with rateLimit
# Ensure per-client vs global rate limiting matches requirements
Challenge 3: Authentication/Authorization
Problem: NGINX auth annotations (basic auth, OAuth2) need replacement.
Solution:
- Gateway API: Use SecurityPolicy resources
- Traefik: Use BasicAuth or ForwardAuth middleware
- Consider external auth services (OAuth2 Proxy, Keycloak)
Challenge 4: WebSocket Support
Problem: Ensuring WebSocket connections work with new controller.
Solution:
- Test WebSocket-specific paths
- Verify timeout configurations
- Check upgrade header handling
# Gateway API supports WebSockets by default
# Traefik: usually works without changes
Monitoring Your New Controller
Set up comprehensive monitoring immediately:
# Prometheus ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: gateway-controller
spec:
selector:
matchLabels:
app: envoy-gateway
endpoints:
- port: metrics
interval: 30s
Key metrics to track:
- Request rate and latency (p50, p95, p99)
- Error rates (4xx, 5xx)
- TLS handshake failures
- Backend connection pool usage
- CPU and memory utilization
- Configuration reload times
Security Considerations Post-Migration
The retirement is partly due to security concerns. Ensure your new setup is secure:
- Eliminate configuration snippets: Never allow arbitrary configuration injection
- Enable mTLS: Use service mesh or controller features for mutual TLS
- Implement WAF: Consider ModSecurity or cloud WAF solutions
- Regular updates: Ensure your new controller has active maintenance
- RBAC controls: Restrict who can create/modify ingress resources
- Network policies: Implement pod-to-pod network restrictions
- Secret management: Use external secret managers (Vault, Azure Key Vault, AWS Secrets Manager)
Resources and Support
- Gateway API Documentation: https://gateway-api.sigs.k8s.io/
- Envoy Gateway: https://gateway.envoyproxy.io/
- Traefik Documentation: https://doc.traefik.io/traefik/
- Kubernetes Ingress Controllers List: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
- Official Retirement Announcement: https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/
Conclusion: Don’t Wait Until March
The Kubernetes community recommends that all Ingress NGINX users begin migration to Gateway API or another Ingress controller immediately. With only four months until the March 2026 deadline, delaying this migration puts your infrastructure at risk.
The retirement of ingress-nginx marks a significant shift toward more sustainable, secure, and modern networking solutions in Kubernetes. While migration requires effort, it’s an opportunity to adopt better architectures and eliminate technical debt.
The maintainers of ingress-nginx deserve immense gratitude for years of volunteer work powering billions of requests worldwide. Now it’s our responsibility to migrate gracefully and support the next generation of Kubernetes networking.
Need help with your migration? At KubeAce, we specialize in zero-downtime Kubernetes migrations and infrastructure modernization. Contact us for a migration assessment and implementation support.