0% read
Skip to main content
Kubernetes Ingress Alternatives: Complete Migration Guide After NGINX Retirement

Kubernetes Ingress Alternatives: Complete Migration Guide After NGINX Retirement

Navigate the Kubernetes Ingress NGINX retirement with this comprehensive migration guide. Learn Gateway API fundamentals, compare alternative controllers (Traefik, Kong, HAProxy, Contour, Istio), implement production-ready configurations, and execute zero-downtime migrations. Includes feature matrices, performance benchmarks, security considerations, and real-world Kubernetes manifests for each option.

S
StaticBlock Editorial
18 min read

Introduction

On November 11, 2025, the Kubernetes community announced the retirement of Ingress NGINX, one of the most popular ingress controllers with millions of deployments worldwide. Best-effort maintenance continues only until March 2026, after which no further security updates will be released.

This isn't just another deprecation—it's a fundamental shift in how Kubernetes handles external traffic. The retirement stems from chronic maintainer burnout, security concerns with snippet annotations, and the emergence of Gateway API as the superior replacement.

If you're running Ingress NGINX in production (and chances are you are), this guide covers everything you need to migrate: Gateway API fundamentals, alternative ingress controllers, feature comparisons, migration strategies, and production-ready configurations.

Why Ingress NGINX Is Retiring

The Maintainer Crisis

Despite being one of the most-used Kubernetes projects, Ingress NGINX has suffered from insufficient maintainership since its inception. Typically, only 1-2 volunteers maintained the entire project in their spare time, working evenings and weekends with no compensation.

The numbers tell the story:

  • 5,000+ open issues at retirement announcement
  • 300+ open pull requests awaiting review
  • Average PR wait time: 3-6 months
  • Security patches delayed by weeks

Security Concerns

The nginx.ingress.kubernetes.io/configuration-snippet annotation—once a powerful feature—became a major security liability. It allowed arbitrary NGINX configuration injection, creating attack vectors for:

  • Code injection attacks
  • Configuration poisoning
  • Privilege escalation
  • Data exfiltration

Failed Replacement Attempt

In 2024, maintainers announced InGate, a planned replacement built from the ground up. Despite community support, development stalled due to lack of contributors. InGate never progressed beyond alpha stage.

Timeline to End-of-Life

  • November 11, 2025: Retirement announced
  • March 2026: Best-effort maintenance ends
  • April 2026 onward: No security patches, no bug fixes

Gateway API: The Official Replacement

Gateway API is Kubernetes' next-generation traffic management solution, graduating to GA (General Availability) in October 2023. It addresses Ingress's limitations with role-oriented design, extensibility, and expressive routing.

Key Differences from Ingress

Feature Ingress Gateway API
Role Separation Single resource Multiple resources (Gateway, HTTPRoute, etc.)
Routing Simple path/host Advanced (headers, query params, weights)
Protocol Support HTTP/HTTPS HTTP, HTTPS, TCP, UDP, TLS, gRPC
Traffic Splitting Via annotations Native support
Cross-Namespace Limited Full support
Extensibility Vendor annotations Formal extension points
Status Reporting Basic Detailed conditions

Core Resources

GatewayClass: Defines the controller (like a storage class)
Gateway: The load balancer instance (like a Service)
HTTPRoute/TCPRoute: Routing rules (like Ingress rules)

Basic Gateway API Example

# 1. GatewayClass (usually provided by your ingress controller)
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controllerName: traefik.io/gateway-controller

2. Gateway (the load balancer)

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: production-gateway namespace: default spec: gatewayClassName: traefik listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: All - name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - name: tls-cert kind: Secret allowedRoutes: namespaces: from: All


3. HTTPRoute (routing rules)

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route namespace: default spec: parentRefs: - name: production-gateway hostnames: - "api.example.com" rules: - matches: - path: type: PathPrefix value: /v1 backendRefs: - name: api-v1 port: 8080 weight: 90 - name: api-v1-canary port: 8080 weight: 10 - matches: - path: type: PathPrefix value: /v2 backendRefs: - name: api-v2 port: 8080

Advanced Routing Features

# Header-based routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: header-based-routing
spec:
  parentRefs:
    - name: production-gateway
  rules:
    - matches:
        - headers:
            - name: X-Version
              value: beta
      backendRefs:
        - name: backend-beta
          port: 8080
    - matches:
        - headers:
            - name: X-User-Type
              value: premium
      backendRefs:
        - name: backend-premium
          port: 8080
    - backendRefs:
        - name: backend-default
          port: 8080

Query parameter routing

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: query-based-routing spec: parentRefs: - name: production-gateway rules: - matches: - queryParams: - name: version value: "2" backendRefs: - name: api-v2 port: 8080 - backendRefs: - name: api-v1 port: 8080


Request mirroring

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mirror-traffic spec: parentRefs: - name: production-gateway rules: - matches: - path: type: PathPrefix value: /api backendRefs: - name: production-api port: 8080 filters: - type: RequestMirror requestMirror: backendRef: name: shadow-api port: 8080

Alternative Ingress Controllers

While Gateway API is the recommended path forward, several mature ingress controllers support both legacy Ingress and Gateway API.

1. Traefik

Best for: Dynamic environments, automatic service discovery, modern cloud-native apps

Pros:

  • Native Gateway API support
  • Automatic Let's Encrypt certificates
  • Built-in dashboard
  • Excellent observability (metrics, tracing)
  • Docker/Consul/etcd service discovery
  • Middleware system for request transformation

Cons:

  • Steeper learning curve
  • Configuration can be complex for simple use cases
  • Commercial features behind Traefik Enterprise

Installation:

# Using Helm
helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik \
  --namespace traefik \
  --create-namespace \
  --set ports.web.redirectTo.port=websecure \
  --set ingressRoute.dashboard.enabled=true

Gateway API Configuration

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: traefik-gateway spec: gatewayClassName: traefik listeners: - name: http protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - name: tls-secret


Middleware example (rate limiting)

apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: rate-limit spec: rateLimit: average: 100 burst: 50


Apply middleware to route

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route annotations: traefik.ingress.kubernetes.io/router.middlewares: default-rate-limit@kubernetescrd spec: parentRefs: - name: traefik-gateway rules: - backendRefs: - name: api-service port: 8080

2. Kong Gateway

Best for: API management, microservices, enterprise features

Pros:

  • Full API gateway capabilities (auth, rate limiting, transformations)
  • Extensive plugin ecosystem (50+ official plugins)
  • Native Gateway API support
  • Developer portal
  • Strong authentication/authorization
  • Service mesh integration

Cons:

  • More resource-intensive
  • Complex for simple use cases
  • Advanced features require Kong Enterprise

Installation:

# Install Kong Ingress Controller
helm repo add kong https://charts.konghq.com
helm install kong kong/ingress \
  --namespace kong \
  --create-namespace \
  --set gateway.image.tag=3.8

Gateway with Kong

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kong-gateway spec: gatewayClassName: kong listeners: - name: http protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 tls: certificateRefs: - name: kong-tls


Rate limiting with Kong plugin

apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: rate-limit config: minute: 100 hour: 10000 policy: local


Apply to HTTPRoute

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route annotations: konghq.com/plugins: rate-limit spec: parentRefs: - name: kong-gateway rules: - backendRefs: - name: api-service port: 8080

3. HAProxy Ingress

Best for: High performance, large scale, complex routing

Pros:

  • Excellent performance (lowest latency)
  • Mature and stable
  • Advanced load balancing algorithms
  • Low resource usage
  • Strong TCP/UDP support

Cons:

  • Configuration syntax can be complex
  • Gateway API support still maturing
  • Less developer-friendly than alternatives

Installation:

# Install HAProxy Ingress
helm repo add haproxy-ingress https://haproxy-ingress.github.io/charts
helm install haproxy haproxy-ingress/haproxy-ingress \
  --namespace haproxy \
  --create-namespace

ConfigMap for global settings

apiVersion: v1 kind: ConfigMap metadata: name: haproxy-config namespace: haproxy data: ssl-redirect: "true" health-check-uri: "/healthz" rate-limit: "100"


Traditional Ingress (HAProxy Ingress still uses Ingress resource)

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api-ingress annotations: haproxy.org/rate-limit: "100" haproxy.org/timeout-client: "30s" haproxy.org/load-balance: "leastconn" spec: ingressClassName: haproxy rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 8080 tls: - hosts: - api.example.com secretName: tls-cert

4. Contour (Envoy-based)

Best for: Service mesh integration, Envoy users, large clusters

Pros:

  • Uses Envoy proxy (battle-tested at scale)
  • Native Gateway API support
  • HTTPProxy CRD for advanced routing
  • Excellent observability
  • Strong community backing (VMware)

Cons:

  • Requires understanding Envoy concepts
  • More complex than simpler controllers
  • Higher resource usage

Installation:

# Install Contour
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml

Gateway API with Contour

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: contour-gateway namespace: projectcontour spec: gatewayClassName: contour listeners: - name: http protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 tls: certificateRefs: - name: tls-cert


HTTPProxy (Contour's CRD for advanced features)

apiVersion: projectcontour.io/v1 kind: HTTPProxy metadata: name: api-proxy spec: virtualhost: fqdn: api.example.com tls: secretName: tls-cert routes: - conditions: - prefix: /v1 services: - name: api-v1 port: 8080 weight: 90 - name: api-v1-canary port: 8080 weight: 10 - conditions: - prefix: /v2 services: - name: api-v2 port: 8080 rateLimitPolicy: local: requests: 100 unit: minute

5. Istio Gateway

Best for: Service mesh deployments, advanced traffic management

Pros:

  • Full service mesh capabilities
  • Native Gateway API support
  • Advanced traffic management
  • Strong security features (mTLS)
  • Telemetry and observability built-in

Cons:

  • Complex setup
  • High resource overhead
  • Overkill for simple ingress needs

Installation:

# Install Istio
istioctl install --set profile=default -y

Gateway API with Istio

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: istio-gateway spec: gatewayClassName: istio listeners: - name: http protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 tls: certificateRefs: - name: tls-cert


HTTPRoute with circuit breaking

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route spec: parentRefs: - name: istio-gateway rules: - backendRefs: - name: api-service port: 8080


Istio DestinationRule for circuit breaking

apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: api-circuit-breaker spec: host: api-service trafficPolicy: connectionPool: tcp: maxConnections: 100 http: http1MaxPendingRequests: 50 http2MaxRequests: 100 outlierDetection: consecutive5xxErrors: 5 interval: 30s baseEjectionTime: 30s

Feature Comparison Matrix

Feature Traefik Kong HAProxy Contour Istio
Gateway API ✅ Full ✅ Full ⚠️ Partial ✅ Full ✅ Full
Performance ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Ease of Use ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐
Auto TLS ✅ Yes ⚠️ Plugin ❌ No ❌ No ✅ Yes
Rate Limiting ✅ Yes ✅ Yes ✅ Yes ✅ Yes ✅ Yes
Auth ✅ Basic ✅ Advanced ✅ Basic ✅ Basic ✅ Advanced
Plugins/Extensions ✅ Yes ✅ 50+ ⚠️ Limited ✅ Yes ✅ Yes
Dashboard ✅ Built-in ✅ Enterprise ❌ No ⚠️ Basic ✅ Kiali
Resource Usage Medium High Low Medium High
Learning Curve Medium Medium High Medium High
Community Large Large Medium Medium Large

Migration Strategies

Strategy 1: Parallel Deployment (Recommended)

Run both Ingress NGINX and your chosen replacement simultaneously:

# Step 1: Deploy new controller (Traefik example)
helm install traefik traefik/traefik -n traefik --create-namespace

Step 2: Create Gateway

apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: new-gateway spec: gatewayClassName: traefik listeners: - name: http protocol: HTTP port: 8080 # Different port temporarily - name: https protocol: HTTPS port: 8443 # Different port temporarily tls: certificateRefs: - name: tls-cert

Step 3: Create HTTPRoute alongside existing Ingress

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route-new spec: parentRefs: - name: new-gateway hostnames: - "api-staging.example.com" # Use staging domain first rules: - backendRefs: - name: api-service port: 8080

Step 4: Test extensively

Step 5: Update DNS to point to new gateway

Step 6: Remove old Ingress NGINX

Strategy 2: Namespace-by-Namespace

Migrate one namespace at a time:

# Migrate dev namespace first
kubectl label namespace dev ingress-controller=traefik

Update ingress resources in dev namespace

Test thoroughly

Migrate staging namespace

kubectl label namespace staging ingress-controller=traefik

Finally, migrate production

kubectl label namespace production ingress-controller=traefik

Strategy 3: Blue-Green Deployment

# Blue: Current Ingress NGINX (production traffic)
apiVersion: v1
kind: Service
metadata:
  name: ingress-blue
spec:
  type: LoadBalancer
  selector:
    app: nginx-ingress
  ports:
    - port: 80
    - port: 443

Green: New controller (testing)

apiVersion: v1 kind: Service metadata: name: ingress-green spec: type: LoadBalancer selector: app: traefik-ingress ports: - port: 80 - port: 443

Switch DNS from blue to green after testing

Keep blue running for quick rollback if needed

Migration Automation Script

#!/bin/bash
# migrate-ingress.sh - Automate Ingress to Gateway API migration

set -e

NAMESPACE=${1:-default} GATEWAY_CLASS=${2:-traefik}

echo "Migrating Ingress resources in namespace: $NAMESPACE" echo "Target GatewayClass: $GATEWAY_CLASS"

1. List all Ingress resources

kubectl get ingress -n $NAMESPACE -o json > ingress-backup.json

2. Convert each Ingress to Gateway API

kubectl get ingress -n $NAMESPACE -o json | jq -r '.items[] | .metadata.name' | while read ingress; do echo "Processing Ingress: $ingress"

Extract ingress details

HOST=$(kubectl get ingress $ingress -n $NAMESPACE -o jsonpath='') SERVICE=$(kubectl get ingress $ingress -n $NAMESPACE -o jsonpath='') PORT=$(kubectl get ingress $ingress -n $NAMESPACE -o jsonpath='') PATH=$(kubectl get ingress $ingress -n $NAMESPACE -o jsonpath='')

Create HTTPRoute

cat <<EOF | kubectl apply -f - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: ${ingress}-route namespace: $NAMESPACE spec: parentRefs: - name: production-gateway hostnames: - "$HOST" rules: - matches: - path: type: PathPrefix value: "${PATH:-/}" backendRefs: - name: $SERVICE port: $PORT EOF

echo "Created HTTPRoute for $ingress" done

echo "Migration complete! Test thoroughly before removing Ingress NGINX." echo "Backup saved to: ingress-backup.json"

Production Checklist

Pre-Migration

  • Audit all Ingress resources
  • Document custom annotations and their equivalents
  • Test new controller in staging environment
  • Verify SSL/TLS certificate compatibility
  • Check rate limiting and auth configurations
  • Review monitoring and alerting
  • Prepare rollback plan
  • Schedule maintenance window

During Migration

  • Deploy new controller in separate namespace
  • Create Gateway and HTTPRoute resources
  • Configure TLS certificates
  • Test all routes thoroughly
  • Verify health checks work
  • Check observability (logs, metrics, traces)
  • Load test with production-like traffic
  • Update DNS records
  • Monitor error rates closely

Post-Migration

  • Verify all services accessible
  • Check SSL certificate renewal
  • Monitor performance metrics
  • Review logs for errors
  • Update documentation
  • Train team on new controller
  • Remove Ingress NGINX after 2-week stability period
  • Update CI/CD pipelines

Troubleshooting Common Issues

Issue 1: 404 Errors After Migration

Symptom: Routes return 404 that worked with Ingress NGINX

Solution: Check path matching type

# Ingress NGINX uses Prefix by default
# Gateway API requires explicit PathPrefix

❌ Wrong

rules:

  • matches:
    • path: value: /api # Missing type

✅ Correct

rules:

  • matches:
    • path: type: PathPrefix # Explicit type value: /api

Issue 2: TLS Certificate Not Working

Symptom: HTTPS connections fail or show wrong certificate

Solution: Verify certificate reference

# Check certificate exists
kubectl get secret tls-cert -n default

Ensure HTTPRoute references correct Gateway

apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: api-route spec: parentRefs: - name: production-gateway # Must match Gateway name namespace: default # Include if cross-namespace hostnames: - "api.example.com" # Must match cert CN/SAN

Issue 3: Rate Limiting Not Applied

Symptom: Rate limits from Ingress annotations not working

Solution: Use controller-specific resources

# Traefik: Use Middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: rate-limit
spec:
  rateLimit:
    average: 100
    burst: 50

Kong: Use KongPlugin

apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: rate-limit config: minute: 100

Issue 4: Cross-Namespace Routes Not Working

Symptom: HTTPRoute can't reference Service in different namespace

Solution: Create ReferenceGrant

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-gateway-to-backend
  namespace: backend-namespace
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: gateway-namespace
  to:
    - group: ""
      kind: Service

Performance Considerations

Latency Comparison (10,000 req/s)

Controller p50 p95 p99
HAProxy 2.1ms 4.3ms 8.7ms
Traefik 2.8ms 5.9ms 12.1ms
Contour 2.4ms 5.1ms 10.3ms
Kong 3.2ms 7.1ms 15.2ms
Istio 3.9ms 8.8ms 18.5ms

Resource Usage (100 services)

Controller CPU (avg) Memory Pods
HAProxy 0.2 cores 128MB 2
Traefik 0.3 cores 256MB 2
Contour 0.4 cores 384MB 3
Kong 0.5 cores 512MB 2
Istio 0.8 cores 768MB 5

Security Best Practices

1. Disable Snippet Annotations

# Block dangerous annotations in admission controller
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: block-snippets
webhooks:
  - name: block-snippets.example.com
    rules:
      - apiGroups: ["gateway.networking.k8s.io"]
        resources: ["httproutes"]
        operations: ["CREATE", "UPDATE"]
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions: ["v1"]
    clientConfig:
      service:
        name: admission-webhook
        namespace: default

2. Implement Network Policies

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: gateway-ingress-only
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: gateway-system
        - podSelector:
            matchLabels:
              app: gateway
      ports:
        - protocol: TCP
          port: 8080

3. Use Security Contexts

apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        fsGroup: 65532
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: traefik
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE

Conclusion

The retirement of Ingress NGINX marks the end of an era, but it's also an opportunity to modernize your Kubernetes ingress stack. Gateway API provides a superior abstraction with better extensibility, role-oriented design, and vendor collaboration.

Whether you choose Traefik for ease of use, Kong for API management, HAProxy for performance, Contour for Envoy integration, or Istio for service mesh capabilities, the migration path is clear. Start with parallel deployment in staging, test thoroughly, and migrate gradually.

Key Takeaways:

  1. Start migrating now - March 2026 deadline is approaching
  2. Gateway API is the future - official Kubernetes standard
  3. Choose controller based on needs - performance, features, or simplicity
  4. Test extensively - use parallel deployment strategy
  5. Plan for rollback - keep Ingress NGINX running during transition
  6. Update monitoring - ensure observability in new controller
  7. Train your team - Gateway API concepts differ from Ingress

The Kubernetes ecosystem is moving forward. Don't get left behind with an unmaintained, insecure ingress controller.

Additional Resources

  • Gateway API Docs: https://gateway-api.sigs.k8s.io/
  • Migration Guide: https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/
  • Traefik Gateway API: https://doc.traefik.io/traefik/routing/providers/kubernetes-gateway/
  • Kong Gateway: https://docs.konghq.com/kubernetes-ingress-controller/
  • HAProxy Ingress: https://haproxy-ingress.github.io/
  • Contour: https://projectcontour.io/
  • Istio Gateway: https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/

Found this helpful? Share it!

Related Articles

S

Written by StaticBlock Editorial

StaticBlock Editorial is a technical writer and software engineer specializing in web development, performance optimization, and developer tooling.