DEV Community

daniel jeong
daniel jeong

Posted on • Originally published at manoit.co.kr

Ingress-NGINX Is Officially Retired — Complete Gateway API Migration Guide With ingress2gateway 1.0

Ingress-NGINX Is Officially Retired — A Complete Gateway API Migration Guide (With ingress2gateway 1.0)

On March 24, 2026, kubernetes/ingress-nginx — the most widely used Ingress controller in the Kubernetes ecosystem — officially reached End-of-Life (EOL). The repository is now read-only. There will be no new features, no bug fixes, and critically, no more CVE patches. For any team running production workloads behind ingress-nginx, this demands immediate action.

Fortunately, Kubernetes SIG-Network has been maturing the Gateway API as the next-generation networking standard, and on March 20, 2026, they released ingress2gateway 1.0 — a stable migration tool supporting 30+ annotations. This guide covers the security implications, Gateway API fundamentals, and a step-by-step zero-downtime migration strategy.

Ingress-NGINX to Gateway API migration architecture diagram showing ingress2gateway 1.0 conversion flow and implementation options including Envoy Gateway, Istio, NGINX Gateway Fabric, and AWS ALB

1. Ingress-NGINX Retirement — What Happened

In November 2025, the Kubernetes project announced the retirement plan for ingress-nginx. On January 29, 2026, the Kubernetes Steering Committee and Security Response Committee issued a joint statement emphasizing security concerns. On March 24, 2026, the repository was archived to read-only.

The Security Background

Repeated security vulnerabilities drove the retirement decision. CVE-2025-1974 (IngressNightmare) in March 2025 was a critical unauthenticated RCE via exposed admission webhooks. Then on February 2, 2026, four HIGH-severity CVEs (CVE-2026-1580, CVE-2026-24512, CVE-2026-24513, CVE-2026-24514) were disclosed simultaneously.

CVE Severity Type Impact
CVE-2025-1974 CRITICAL (9.8) Unauthenticated RCE Remote code execution via admission webhook
CVE-2026-1580 HIGH Config Injection Privilege escalation through NGINX config injection
CVE-2026-24512 HIGH Path Injection NGINX config injection via rules.http.paths.path
CVE-2026-24513 HIGH Auth Bypass Unauthorized access through authentication bypass
CVE-2026-24514 HIGH Annotation Abuse Configuration manipulation via annotations

Compliance Impact: EOL software in the L7 data path triggers automatic findings in SOC 2, PCI-DSS, ISO 27001, and HIPAA audits. Some organizations are already seeing production deployments blocked.

What Changes After Retirement

The Kubernetes Ingress API itself is not removed. The Ingress resource spec remains part of the Kubernetes core. If you're using third-party Ingress controllers (Traefik, HAProxy, Kong), there's no immediate impact. The retirement only affects the kubernetes/ingress-nginx controller project.

However, if you're running ingress-nginx, the situation is different. With the repository archived, no patches will be released for newly discovered vulnerabilities. Some managed Kubernetes services like Azure AKS Application Routing have committed to vendor-extended support until November 2026, but this is a temporary measure.

2. Gateway API — The True Successor to Ingress

Gateway API is the next-generation service networking standard designed by Kubernetes SIG-Network to address Ingress's fundamental limitations. Since reaching v1.0 GA in October 2023, it has matured rapidly to v1.4, with 20+ conformant implementations.

Ingress vs Gateway API — Key Differences

Aspect Ingress + ingress-nginx Gateway API
Configuration Annotation-based (non-standard, varies by controller) Typed CRD fields (standardized, portable)
Role Separation None (cluster admin manages everything) GatewayClass(infra) → Gateway(ops) → Route(dev)
Protocol Support HTTP/HTTPS focused (TCP/UDP via annotation hacks) HTTPRoute, TLSRoute, TCPRoute, UDPRoute, GRPCRoute
Cross-namespace Limited Safe cross-namespace via ReferenceGrant
TLS Management Secrets referenced directly in Ingress BackendTLSPolicy for gateway↔backend TLS
Conformance Testing None SupportedFeatures-based automatic verification
Vendor Portability Low (annotation incompatibility) High (standard CRDs + extension points)

The 3-Layer Resource Model

Gateway API's most significant design innovation is role-based resource separation. Infrastructure admins, cluster operators, and application developers each work within their own permission scope.

# 1. GatewayClass — Defined by infrastructure admin
# Determines which controller manages Gateways of this class
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: production-gateway
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
  description: "Production traffic gateway managed by Envoy Gateway"
---
# 2. Gateway — Defined by cluster operator
# Provisions the actual load balancer instance
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: gateway-infra
spec:
  gatewayClassName: production-gateway
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: wildcard-tls
            namespace: cert-manager
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "true"
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same
Enter fullscreen mode Exit fullscreen mode
# 3. HTTPRoute — Defined by application developer
# Routing rules to their own services
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-routes
  namespace: app-production
spec:
  parentRefs:
    - name: main-gateway
      namespace: gateway-infra
      sectionName: https
  hostnames:
    - "api.example.com"
  rules:
    # /api/v1/users -> user-service
    - matches:
        - path:
            type: PathPrefix
            value: /api/v1/users
      backendRefs:
        - name: user-service
          port: 8080
          weight: 100
    # /api/v1/courses -> course-service (canary deployment)
    - matches:
        - path:
            type: PathPrefix
            value: /api/v1/courses
      backendRefs:
        - name: course-service
          port: 8080
          weight: 90
        - name: course-service-canary
          port: 8080
          weight: 10
    # Header-based routing
    - matches:
        - path:
            type: PathPrefix
            value: /api/v1/
          headers:
            - name: X-Environment
              value: staging
      backendRefs:
        - name: staging-service
          port: 8080
Enter fullscreen mode Exit fullscreen mode

Gateway API v1.4 Key Features

Released in October 2025, Gateway API v1.4 adds production-critical capabilities: BackendTLSPolicy (GA) for fine-grained gateway-to-backend TLS management; TLSRoute (GA) for SNI-based TLS passthrough routing; client certificate validation for per-Listener mTLS policies; and SupportedFeatures conformance testing graduated to Standard channel.

# BackendTLSPolicy — Gateway to backend TLS configuration
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
  name: backend-tls
  namespace: app-production
spec:
  targetRefs:
    - group: ""
      kind: Service
      name: secure-backend
  validation:
    caCertificateRefs:
      - name: backend-ca-cert
        group: ""
        kind: ConfigMap
    hostname: secure-backend.app-production.svc.cluster.local
Enter fullscreen mode Exit fullscreen mode

3. ingress2gateway 1.0 — The Automated Migration Tool

On March 20, 2026, Kubernetes SIG-Network released ingress2gateway 1.0. The previous version supported only 3 ingress-nginx annotations; v1.0 supports 30+ common annotations and introduces a pluggable emitter architecture for vendor-specific output.

Supported Annotation Categories

Category Annotation Examples Conversion Target
CORS enable-cors, cors-allow-origin HTTPRoute Filter
Path Rewrite rewrite-target, use-regex URLRewrite Filter
TLS / SSL ssl-redirect, backend-protocol Gateway TLS + BackendTLSPolicy
Header Manipulation proxy-set-headers, custom-http-errors RequestHeaderModifier Filter
Canary / Traffic Split canary, canary-weight HTTPRoute backendRefs weight
Timeouts / Buffering proxy-read-timeout, proxy-buffer-size HTTPRoute timeouts + impl extensions
IP Allowlist whitelist-source-range Implementation-specific Policy CRD
gRPC backend-protocol: GRPC GRPCRoute

Installation and Basic Usage

# Install ingress2gateway (Go 1.22+)
go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0

# Or download release binary
curl -LO https://github.com/kubernetes-sigs/ingress2gateway/releases/download/v1.0.0/ingress2gateway-linux-amd64
chmod +x ingress2gateway-linux-amd64
sudo mv ingress2gateway-linux-amd64 /usr/local/bin/ingress2gateway

# Convert all Ingress resources to Gateway API (dry-run)
ingress2gateway print --providers ingress-nginx

# Specific namespace
ingress2gateway print --providers ingress-nginx --namespace production

# Save to file
ingress2gateway print --providers ingress-nginx --namespace production > gateway-resources.yaml

# Vendor-specific emitter (Envoy Gateway extensions)
ingress2gateway print --providers ingress-nginx --emitter envoy-gateway > envoy-gateway-resources.yaml
Enter fullscreen mode Exit fullscreen mode

Emitter Architecture

The 1.0 release introduces pluggable emitters for generating vendor-specific extension resources beyond standard Gateway API CRDs:

Emitter Target Controller Additional Resources
standard All conformant implementations Standard Gateway API CRDs only
envoy-gateway Envoy Gateway BackendTrafficPolicy, SecurityPolicy
kgateway Kgateway (Solo.io) RouteOption, VirtualHostOption
agentgateway Agent Gateway AI/Agent-specific routing policies

4. Production Migration Guide — Zero-Downtime Strategy

For production migrations, the recommended approach is Parallel Run: deploy both Ingress and Gateway API resources simultaneously, then gradually shift DNS weights.

Step 1: Install Gateway API CRDs

# Install Gateway API CRDs (v1.4.0)
# WARNING: v1.5.x causes istiod crash with Istio 1.28/1.29
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml

# Verify CRD installation
kubectl get crd | grep gateway

# For experimental channel (TCPRoute, UDPRoute)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/experimental-install.yaml
Enter fullscreen mode Exit fullscreen mode

Step 2: Analyze and Convert Existing Ingress

# Inventory all Ingress resources
kubectl get ingress --all-namespaces -o wide

# Analyze annotation usage patterns
kubectl get ingress --all-namespaces -o json | \
  jq -r '.items[].metadata.annotations // {} | keys[]' | \
  sort | uniq -c | sort -rn

# Preview conversion
ingress2gateway print --providers ingress-nginx --all-namespaces 2>&1 | tee migration-preview.yaml

# Check for unsupported annotations
ingress2gateway print --providers ingress-nginx --all-namespaces 2>&1 | grep "WARNING"
Enter fullscreen mode Exit fullscreen mode

Step 3: Deploy Gateway API Controller

# Install Envoy Gateway (Helm)
helm install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
  --version v1.3.0 \
  --namespace envoy-gateway-system \
  --create-namespace

# Verify GatewayClass
kubectl get gatewayclass
Enter fullscreen mode Exit fullscreen mode

Step 4: Parallel Deploy and Traffic Shift

# Gateway + ReferenceGrant for parallel deployment
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: migration-gateway
  namespace: gateway-infra
spec:
  gatewayClassName: eg
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            name: api-tls-cert
      allowedRoutes:
        namespaces:
          from: All
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-gateway-refs
  namespace: app-production
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: app-production
  to:
    - group: ""
      kind: Service
Enter fullscreen mode Exit fullscreen mode
# 1. Deploy Gateway API resources (parallel with existing Ingress)
kubectl apply -f gateway-resources.yaml

# 2. Get external IP assigned to Gateway
kubectl get gateway migration-gateway -n gateway-infra -o jsonpath='{.status.addresses[0].value}'

# 3. Gradually shift DNS weights
#    ingress-nginx LB: 90 -> 50 -> 10 -> 0
#    gateway API LB:   10 -> 50 -> 90 -> 100

# 4. Verify traffic
curl -H "Host: api.example.com" https://<GATEWAY_IP>/api/v1/health

# 5. Cleanup after full transition
kubectl delete ingress --all -n app-production
helm uninstall ingress-nginx -n ingress-nginx
Enter fullscreen mode Exit fullscreen mode

5. Troubleshooting — Common Migration Issues

Issue 1: CRD Version and Controller Compatibility Conflicts

The most reported issue in early 2026 is the Istio 1.28/1.29 incompatibility with Gateway API CRD v1.5.x. Installing v1.5.x CRDs causes istiod to crash due to API field mismatches.

# Symptom: istiod CrashLoopBackOff
kubectl logs -n istio-system deployment/istiod | grep "gateway"

# Fix: Downgrade CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
kubectl rollout restart deployment/istiod -n istio-system
Enter fullscreen mode Exit fullscreen mode

Issue 2: Unsupported Annotation Conversion

While ingress2gateway 1.0 supports 30+ annotations, custom or non-standard configurations won't convert automatically. Always check WARNING logs.

# Extract unsupported annotations
ingress2gateway print --providers ingress-nginx 2>&1 | \
  grep "WARNING.*annotation" | \
  sed 's/.*annotation "\(.*\)" is not.*/\1/' | \
  sort -u > unsupported-annotations.txt

# Common manual mappings:
# limit-rps -> Envoy Gateway RateLimitPolicy
# auth-url -> Envoy Gateway SecurityPolicy (ExtAuth)
# modsecurity-* -> Separate WAF solution required
Enter fullscreen mode Exit fullscreen mode

Issue 3: Cross-Namespace Reference Permission Missing

Gateway API requires explicit ReferenceGrant for cross-namespace references. Without it, routing fails silently with a RefNotPermitted condition.

# Fix: Create ReferenceGrant in the target namespace
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-from-app-ns
  namespace: shared-services
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: app-production
  to:
    - group: ""
      kind: Service
Enter fullscreen mode Exit fullscreen mode

6. Choosing a Gateway API Implementation

Implementation Maintained By Strengths Best For License
Envoy Gateway CNCF (Envoy) Highest conformance, extensibility, built-in rate limiting Standard-focused, multi-cloud Apache 2.0
NGINX Gateway Fabric F5 / NGINX Leverage NGINX operational experience Transitioning from ingress-nginx Apache 2.0
Istio Gateway Istio (CNCF) Service mesh integration, mTLS, traffic management Already using Istio Apache 2.0
AWS Gateway Controller AWS Native ALB/NLB, AWS IAM integration EKS-only environments Apache 2.0
Traefik Traefik Labs v3 native support, Let's Encrypt automation Small to mid-size clusters MIT

Selection Criteria: If you already run Istio, use Istio Gateway — no additional controller needed. For greenfield environments, Envoy Gateway offers the best conformance and extensibility. For a minimal-change transition from ingress-nginx, NGINX Gateway Fabric is the natural fit.

7. Conclusion — Act Now

The retirement of Ingress-NGINX formalizes a paradigm shift in Kubernetes networking: from non-standard annotation-based configuration to typed CRDs, from single-role management to a 3-layer separation model, and from HTTP-only to multi-protocol support.

The compliance implications cannot be ignored. EOL software in the L7 data path triggers automatic findings in SOC 2, PCI-DSS, and ISO 27001 audits. Delaying migration is not technical debt — it's business risk.

With ingress2gateway 1.0, the technical barrier to migration has been significantly lowered. The tools are ready. It's time to execute.

Three immediate actions:

  1. Run kubectl get ingress --all-namespaces to inventory your current Ingress resources
  2. Run ingress2gateway print to assess automatic conversion coverage and identify manual mapping needs
  3. Deploy a Gateway API controller in staging and validate converted resources

The future of Kubernetes networking is Gateway API. Start your migration today.


Originally published at ManoIT Tech Blog.

Top comments (0)