|

Kubernetes Ingress to Gateway API Migration: How to Move Without Breaking Production

Kubernetes Ingress Architecture Series - ingress-nginx deprecation
>_ Kubernetes Ingress Architecture Series
>_ Part 0
The Decision Layer: Four Paths, Four Failure Modes
How to evaluate the ingress-nginx retirement before picking a direction
>_ Part 1
Gateway API Is the Direction. Your Controller Choice Is the Risk.
The architectural shift and what annotation sprawl costs over time
>_ Part 1.5
The Control Plane Shift
Every infrastructure decision now looks the same — and why that changes how you architect
▶ Part 2 — You Are Here
Kubernetes Ingress to Gateway API Migration: How to Move Without Breaking Production
Annotation audit, ingress2gateway reality, side-by-side pattern, failure modes
>_ Part 3 — Coming Soon
Operating Gateway API in Production
Observability, policy enforcement, multi-cluster governance, Day-2 failure patterns

To migrate ingress to Gateway API without breaking production, the work starts before you touch a manifest — in the annotation audit, the ConfigMap defaults, and the shared Ingress resources that no migration tool can handle for you.

Most migrations don’t fail during the cutover. They fail in the translation layer — quietly, before traffic ever moves. The annotation audit skipped. The ingress2gateway output treated as deployment-ready. The staging environment that shared none of the complexity of production. By the time the failure surfaces, it looks like a Gateway API problem. It isn’t. It’s a migration preparation problem.

Part 0 covered the four paths and their failure identities. Part 1 covered why the ecosystem shift is real and what annotation sprawl costs over time. The controller decision post covered which implementation fits which environment. This post is the execution layer.

Ingress-NGINX hit EOL on March 24 — the repository is read-only, no patches, no CVE fixes. Kubernetes 1.36 drops April 22 with Gateway API as the centerpiece. The window where this was a future consideration closed.

migrate ingress to gateway api architecture diagram showing translation layer between flat ingress annotation model and three-tier gateway api resource hierarchy
ingress2gateway 1.0 translates syntax. It cannot translate architectural intent. The gap between those two things is where production migrations fail.

Before You Migrate Ingress to Gateway API — The Annotation Audit

The annotation count per Ingress resource is the number that determines which migration path is actually viable. Run this before anything else:

Kubernetes ingress annotation complexity audit chart showing three migration risk tiers from simple to high-risk annotation surfaces
The annotation count per Ingress resource is the number that determines which migration path is actually viable. Run the audit before anything else.

bash

# Count annotations per ingress resource across all namespaces
kubectl get ingress -A -o json | \
  jq -r '.items[] | "\(.metadata.namespace)/\(.metadata.name): \(.metadata.annotations | length) annotations"' | \
  sort -t: -k2 -rn
>_ 0–5 Annotations
ingress2gateway 1.0 handles 80–90% of the translation. Most of what lands in your HTTPRoute manifests will be correct. Manual review still required.
✓ Tool does the heavy lifting
>_ 6–20 Annotations
Partial translation. Common annotations are covered. Less common ones — configuration-snippet, auth-url, server-snippet — require architectural decisions about where that logic moves.
⚠ Manual review required
>_ 20+ Annotations
The tool cannot help you here. What those annotations are collectively doing needs to be understood and redesigned for the Gateway API model before a single manifest is written.
✗ Architecture decision required

bash

# Find ingress resources routing multiple hosts — shared ingress candidates
kubectl get ingress -A -o json | \
  jq -r '.items[] | select(.spec.rules | length > 5) | 
  "\(.metadata.namespace)/\(.metadata.name): \(.spec.rules | length) host rules"'

ingress2gateway 1.0 — Syntax Translator, Not Architecture Translator

ingress2gateway 1.0 is a significant improvement over previous versions. It supports 30+ common Ingress-NGINX annotations with behavioral equivalence tests that verify the translated configuration matches runtime behavior in live clusters — not just YAML structure. For straightforward environments it is genuinely useful.

It is a syntax translator. It is not an architecture translator.

What ingress2gateway translates cleanly:

bash

# Run ingress2gateway against your cluster
ingress2gateway print \
  --providers=ingress-nginx \
  --namespace=production
>_ Translates Cleanly
  • > Host and path routing rules
  • > TLS referencing existing Secrets
  • > CORS headers
  • > Backend TLS protocol
  • > Path rewrites and regex matching
>_ Does Not Translate
  • > configuration-snippet (custom Lua)
  • > server-snippet (server-level config)
  • > auth-url / auth-signin
  • > ConfigMap global defaults
  • > Implicit proxy/timeout behavior

Implicit defaults that disappear — Ingress-NGINX applies defaults globally that you may not know exist: proxy buffer sizes, upstream keepalive connections, timeout values. These are not in your Ingress manifests. They are in your ConfigMap. They do not transfer to Gateway API automatically. Document your ConfigMap before migration and verify whether those defaults need to be explicitly set in your Gateway implementation.

What to Migrate First — and What to Leave Alone

Migration sequence matters more than migration speed. The temptation is to start with the highest-traffic services to prove the pattern works. That is the wrong sequence.

>_ Migrate First
New services with no Ingress config yet. Internal services with 2–3 host rules and no custom annotations. These establish the operational pattern before it carries weight.
>_ Migrate Second
Services with standard CORS, TLS, and path rewrite annotations that ingress2gateway handles cleanly. Validate behavioral equivalence before decommissioning each Ingress resource.
>_ Migrate Last
configuration-snippet services, external auth integrations, shared Ingress resources, and anything with a P1 incident in the last 90 days. These require architectural design work — not migration commands.

The Side-by-Side Deployment Pattern — The Only Safe Model

Side-by-side Kubernetes ingress and gateway api deployment pattern showing shared load balancer IP with parallel traffic paths during migration
Both controllers share the same external IP. Traffic shifts incrementally. The DNS cutover is the final step — not the first.

Cutover-first is an anti-pattern. Deploying Gateway API and decommissioning Ingress in the same change window is how teams end up rolling back at 2AM.

The side-by-side deployment pattern runs both controllers simultaneously against the same cluster, sharing the same external load balancer IP. Traffic routes through Ingress for existing services. New and migrated services route through Gateway API. Neither controller touches the other’s resources.

bash

# Install Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml

# Deploy your chosen Gateway API controller alongside existing Ingress controller
# Example: NGINX Gateway Fabric
kubectl apply -f https://github.com/nginx/nginx-gateway-fabric/releases/download/v1.5.0/nginx-gateway-fabric.yaml

# Verify both controllers are running independently
kubectl get pods -n ingress-nginx
kubectl get pods -n nginx-gateway

Deploy a GatewayClass and Gateway resource pointing to your existing load balancer:

yaml

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx-gateway
spec:
  controllerName: gateway.nginx.org/nginx-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: production-gateway
  namespace: nginx-gateway
spec:
  gatewayClassName: nginx-gateway
  listeners:
  - name: http
    port: 80
    protocol: HTTP
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - name: production-tls
        namespace: nginx-gateway

Start routing new services through HTTPRoutes. Do not touch existing Ingress resources. Validate each migrated service under load before decommissioning its Ingress equivalent. The DNS cutover — updating the external record from the Ingress controller service to the Gateway controller service — happens last, after all services have been validated in the side-by-side state.

The only caveat: do not configure both an Ingress resource and an HTTPRoute for the same hostname and path simultaneously. The two controllers would compete for the same traffic. Migrate one or the other — never both active for the same route.

HTTPRoute Translation Reality — What Maps Clean, What Doesn’t

The basic HTTPRoute is straightforward for engineers coming from Ingress:

yaml

# Ingress equivalent
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
---
# Gateway API equivalent
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: production
spec:
  parentRefs:
  - name: production-gateway
    namespace: nginx-gateway
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /
    backendRefs:
    - name: api-service
      port: 8080

Traffic splitting is where Gateway API’s model is genuinely superior — what required custom annotations in Ingress is native in HTTPRoute:

yaml

# Canary deployment — native weight-based splitting
rules:
- backendRefs:
  - name: api-stable
    port: 8080
    weight: 90
  - name: api-canary
    port: 8080
    weight: 10

Adjacent Dependencies — TLS, cert-manager, ExternalDNS

Three ecosystem tools break first when you migrate. Address them before the first HTTPRoute goes live.

>_ cert-manager
Requires v1.14.0+ for Gateway API support. Configuration moves from Ingress annotations to Gateway resource annotations. Update Certificate resources to reference the Gateway, not an Ingress.
cert-manager.io/cluster-issuer on Gateway resource
>_ ExternalDNS
Requires v0.14.0+ for Gateway API support. DNS records for HTTPRoute hostnames will not be created automatically on older versions — DNS resolution for migrated services fails silently.
Upgrade before migration, not after
>_ Prometheus / Alerting
Gateway API controllers expose different metric structures than Ingress-NGINX. Dashboards and alerts keyed to Ingress-NGINX metric names will not work without updates.
Audit alerting rules before cutover

yaml

# cert-manager Gateway API integration
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: production-gateway
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - name: production-tls

The DNS Cutover — Zero-Downtime Execution

The shared-IP strategy makes the DNS cutover the safest step in the migration, not the riskiest. Because both controllers are running against the same load balancer IP during the side-by-side phase, the DNS record change is effectively a no-op for traffic that has already been migrated to HTTPRoutes.

>_ Cutover Sequence
01
All services validated under load via HTTPRoutes in side-by-side state
02
Ingress resources for migrated services still exist — keep for rollback
03
Reduce DNS TTL to 60 seconds — 24 hours before cutover
04
Update external DNS record or let ExternalDNS handle automatically
05
Monitor error rates for 30 minutes
06
Remove decommissioned Ingress resources after 24 hours of clean traffic — not before

Production Failure Modes — Works in Staging, Breaks in Production

Staging environments don’t have the annotation complexity, traffic volume, or cross-namespace dependency graph of production. These failure modes are invisible until they aren’t.

Four Gateway API migration production failure modes — header routing mismatch, ReferenceGrant missing, TLS handshake surprise, and implicit defaults disappearing
Staging environments never have the annotation complexity, traffic volume, or cross-namespace dependencies of production. These failure modes are invisible until they aren’t.
>_ Header Routing Mismatch
HTTPRoute header matching is exact by default. Ingress-NGINX treats some header matching case-insensitively. Verify your Gateway implementation’s behavior if routing logic depends on header values.
Works in staging ✓ — breaks in prod ✗
>_ ReferenceGrant Missing
An HTTPRoute in namespace frontend referencing a Service in namespace api requires a ReferenceGrant in the api namespace. Without it the route fails silently — accepted status, 500 response.
Most common failure in multi-team clusters
>_ TLS Handshake Surprise
Ingress-NGINX’s default TLS configuration includes specific cipher suites set in the ConfigMap. Gateway API controllers start from their own defaults. Validate TLS behavior explicitly against legacy clients before cutover.
Legacy clients and partner integrations at risk
>_ Implicit Defaults Gone
Proxy timeouts, upstream keepalive, buffer sizes set globally in the Ingress-NGINX ConfigMap don’t transfer to Gateway API. A service relying on a 600-second proxy timeout reverts to the controller’s default silently.
Audit ConfigMap before first service migrates

The ReferenceGrant fix — required for any cross-namespace HTTPRoute:

yaml

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

Multi-Cluster Considerations

Gateway API’s typed resource model makes multi-cluster standardization significantly cleaner than Ingress — but only if GatewayClass and Gateway configuration is consistent across clusters.

Define a standard GatewayClass per environment tier and manage it through the same GitOps pipeline that manages cluster provisioning. HTTPRoute resources then become portable. The annotation sprawl that accumulated in Ingress configs over three years will accumulate in Gateway configurations over the next three years if there is no governance layer enforcing consistency.

The Kubernetes Cluster Orchestration guide covers the cluster fleet management model that keeps this consistent at scale. For AI infrastructure workloads with deterministic networking requirements, the deterministic networking for AI infrastructure post covers where Gateway API’s traffic management model intersects with inference workload latency requirements.

Kubernetes 1.36 — What Changes April 22

>_ Kubernetes 1.36 — April 22, 2026
Gateway API — further stabilization, WatchCache improvements for large clusters with many HTTPRoute resources. No breaking changes to existing configurations.
Ingress API — remains GA and fully supported. The retirement was of the ingress-nginx controller implementation, not the API spec. Third-party Ingress controllers continue to function.
DRA graduation — Dynamic Resource Allocation graduates to beta, affecting scheduling behavior for clusters running GPU workloads alongside routing infrastructure.

Architect’s Verdict

The Gateway API migration is not complicated. It is detailed — and the details are where teams get into trouble.

ingress2gateway 1.0 is a genuine improvement and it handles the majority of straightforward migrations cleanly. The gap it cannot close is between syntax translation and architectural translation. Annotations that encode behavior — external auth flows, custom Lua, upstream connection tuning — require architectural decisions that no tool can make for you. Find them during the audit, not during the rollback.

The side-by-side pattern is not a conservative approach. It is the correct one. Both controllers running against the same load balancer IP costs nothing in complexity and eliminates the primary risk vector of Gateway API migrations: the all-at-once cutover that discovers production failure modes under incident conditions.

Migrate simple services first. Let the pattern prove itself before it carries your annotation-heavy services. Run the annotation audit before you touch a manifest. Address cert-manager, ExternalDNS, and your ConfigMap defaults before the first HTTPRoute goes live. Keep your Ingress resources around for 24 hours after the DNS cutover.

The migration doesn’t fail where you think it will. It fails in everything you assumed would just translate.

Additional Resources

Editorial Integrity & Security Protocol

This technical deep-dive adheres to the Rack2Cloud Deterministic Integrity Standard. All benchmarks and security audits are derived from zero-trust validation protocols within our isolated lab environments. No vendor influence.

Last Validated: April 2026   |   Status: Production Verified
R.M. - Senior Technical Solutions Architect
About The Architect

R.M.

Senior Solutions Architect with 25+ years of experience in HCI, cloud strategy, and data resilience. As the lead behind Rack2Cloud, I focus on lab-verified guidance for complex enterprise transitions. View Credentials →

The Dispatch — Architecture Playbooks

Get the Playbooks Vendors Won’t Publish

Field-tested blueprints for migration, HCI, sovereign infrastructure, and AI architecture. Real failure-mode analysis. No marketing filler. Delivered weekly.

Select your infrastructure paths. Receive field-tested blueprints direct to your inbox.

  • > Virtualization & Migration Physics
  • > Cloud Strategy & Egress Math
  • > Data Protection & RTO Reality
  • > AI Infrastructure & GPU Fabric
[+] Select My Playbooks

Zero spam. Includes The Dispatch weekly drop.

Need Architectural Guidance?

Unbiased infrastructure audit for your migration, cloud strategy, or HCI transition.

>_ Request Triage Session

>_Related Posts