Gateway API Migration: How to Test It Before You Cut Over (2026)
Ingress-NGINX retired in March 2026. A practical test plan for Gateway API migration - conformance checks, translation review, traffic parity testing, and a rollback you can actually execute.
If you are migrating off Ingress-NGINX, the hard part is not writing HTTPRoutes. It is proving the new stack behaves identically before you move real traffic. Gateway API migration should be validated in four layers: conformance (does the controller actually implement what you need), translation review (what did the converter quietly fail to carry over), traffic parity (do real requests get identical responses), and rollback (can you revert in minutes, and have you rehearsed it). This post is a test plan for each layer.
Why this is urgent now
kubernetes/ingress-nginx reached end of life on 24 March 2026. Kubernetes SIG Network and the Security Response Committee formally retired the project, the repository is read only, and there are no further features, bug fixes or CVE patches.
The path there is worth understanding because it explains why the recommendation is firm rather than gentle. CVE-2025-1974, the “IngressNightmare” unauthenticated remote code execution via exposed admission webhooks, landed in March 2025. Four more high severity CVEs were disclosed together on 2 February 2026. The maintainers had already announced a wind-down and a planned successor controller, InGate, but that project never reached maturity and stalled. SIG Network’s guidance is to begin migration to Gateway API or another actively maintained Ingress controller immediately.
Two clarifications that save a lot of panic:
- The Ingress API is not being removed. The
networking.k8s.io/v1Ingress resource remains part of Kubernetes core. What retired is one controller implementation. - If you run Traefik, HAProxy, Kong or another maintained controller, nothing is on fire. You may still want Gateway API for its expressiveness and role separation, but on your own timeline.
For everyone still on Ingress-NGINX in production, the clock is running on unpatched CVEs. That is a security deadline, not a feature deadline, which is exactly why teams rush the migration and skip the testing.
Layer 1: conformance, before you install anything
The first question is not “how do I write this route” but “does this controller actually do what I need, the way the spec says it should”.
Gateway API answers that with a conformance programme, and it is one of the genuinely good things about the project. Three things to use:
Read published conformance reports first. Implementations submit conformance reports into the Gateway API repository via pull request. Before you shortlist controllers, read the reports for the versions you would actually run. This is free evidence and most teams never look at it.
Understand support levels. Gateway API classifies features as Core (expected everywhere), Extended (portable but not universal, and consistent where supported) and Implementation-specific (vendor territory, no portability guarantee). Write down which of your current Ingress behaviours map to each tier. Anything landing in Implementation-specific is a lock-in decision you are making, so make it deliberately.
Check supportedFeatures on the live GatewayClass. Gateway API v1.4.0 promoted supportedFeatures in GatewayClass status into the Standard channel. This means the controller running in your cluster tells you what it supports, in a machine-readable field. Assert on it in CI:
kubectl get gatewayclass my-class \
-o jsonpath='{.status.supportedFeatures}'
Turn that into a test. Keep a list of the features your platform depends on, and fail the pipeline if the installed controller stops advertising one after an upgrade. This is the single cheapest guard in the whole migration and almost nobody builds it.
Run the suite yourself when it matters. For a platform serving many teams, run the conformance suite against your own installation rather than trusting a report generated on someone else’s cluster with someone else’s configuration:
go test ./conformance -run TestConformance -args \
--gateway-class=my-class \
--supported-features=Gateway,HTTPRoute,ReferenceGrant
The suite also supports selecting conformance profiles, exempting features you do not use, and retaining test resources for inspection when something fails. Mesh conformance is a separate track under the GAMMA work, so if you are also using Gateway API for service mesh, test that path separately rather than assuming north-south results carry over.
Also pin your channel expectations. Standard contains graduated features. Experimental contains everything in Standard plus resources that may change in breaking ways or be removed entirely. At the v1.4.0 release, BackendTLSPolicy, named rules for Routes and supportedFeatures were Standard, while the dedicated Mesh resource, default gateways and the externalAuth HTTPRoute filter were Experimental. Build production dependencies on Standard only.
Layer 2: treat the converter output as a draft
ingress2gateway reached 1.0 on 20 March 2026 and it is genuinely good. The 1.0 release covers 30 or more common Ingress-NGINX annotations including CORS, backend TLS, regex path matching and rewrites, up from a handful before 1.0. It also ships controller-level integration tests that spin up live controllers and compare actual runtime behaviour, which is a much stronger correctness signal than unit-testing a translator in isolation.
What it does not do is make decisions for you. It warns about configuration it cannot translate and suggests alternatives. Every warning is a manual decision, and warnings are exactly what gets skimmed at 6pm on a Friday.
A review process that works:
- Run the converter and capture the full output including warnings to a file. Commit it. Warnings are migration backlog, not console noise.
- Inventory every annotation in the source Ingress set and classify each one as translated, translated with behaviour change, manually reimplemented, or dropped deliberately. A three-column table in the PR description is enough. The point is that a human signed off on each row.
- Pay special attention to the ones that silently change semantics. Rewrite rules and regex path matching are the classic offenders, because Ingress-NGINX regex capture group behaviour and Gateway API path modifiers do not map one to one. Auth annotations, rate limiting and custom snippets are usually not portable at all and need a real redesign.
- Diff the resulting route set for coverage, not just validity. Every hostname and path prefix that resolved before must resolve after. A manifest that applies cleanly and serves 404 on a path nobody tested is the standard failure.
Static validation still applies here. Run your usual manifest checks over the generated Gateway API resources the same way you would over any other workload, and if you already enforce policy at admission, extend those policies to the new resource kinds rather than leaving Gateway, HTTPRoute and BackendTLSPolicy as an unchecked blind spot. Our Kubernetes manifest hardening checklist covers the baseline.
Layer 3: traffic parity testing
This is the layer that actually catches problems, and the layer teams most often replace with “we clicked around the staging site”.
Build a golden request corpus. Sample real access logs across a full week, not a day. Weekly reporting endpoints, batch integrations and partner callbacks live in the tail and they are exactly what breaks. For each request keep method, host, path, query string, relevant headers and the observed response status. A few thousand distinct request shapes is usually plenty; you want coverage of shapes, not volume.
Replay against both data planes and diff. Point the corpus at the old Ingress-NGINX endpoint and the new Gateway endpoint, then compare on four axes:
| What to compare | Why it catches real bugs |
|---|---|
| Status code | Path matching and precedence differences show up here first |
| Final URL after redirects | Rewrite and redirect semantics differ most between the two models |
| Response headers | CORS, HSTS, cache control and custom headers are often annotation-driven and easily lost |
| Body hash for cacheable responses | Catches routing to the wrong backend when status codes happen to match |
Anything that differs is either a bug or a deliberate change someone has to sign off. Do not let “probably fine” resolve a diff.
Shadow live traffic where you can. Gateway API supports request mirroring, which sends a copy of live traffic to a second backend without affecting what the user receives. Mirroring the production Ingress path to the new Gateway stack for a week gives you parity evidence on real traffic including the requests you never thought to include in your corpus. Support and granularity vary by implementation, so check your GatewayClass supported features before designing around it, and make sure mirrored requests are non-mutating or that the shadow backend writes nowhere that matters.
Test the failure paths, not just the happy ones. Migrations change more than routing:
- TLS termination and certificate rotation. Does cert-manager still issue and mount correctly through the Gateway listener model? Force a renewal and watch.
- Backend TLS. If you were doing gateway-to-pod encryption via annotations, that is now BackendTLSPolicy, GA in the Standard channel since v1.4.0. Verify it actually negotiates rather than silently falling back.
- Timeouts and retries. Defaults differ between implementations. Test a slow backend deliberately.
- Large bodies and long-lived connections. Upload limits, WebSocket upgrades and server-sent events are frequent regressions.
- Behaviour under controller restart. Delete the controller pod during a load test and measure connection drops. This is where a chaos experiment is worth more than a checklist item.
Wire the parity diff into your pipeline as a gate rather than a report someone reads later. The same reasoning applies here as to any other release check, which we covered in Kubernetes deployment gates: a check that does not block is a check that gets ignored under deadline pressure.
Layer 4: a rollback you have actually rehearsed
Run both stacks in parallel through the cutover. Ingress-NGINX and a Gateway API controller can coexist on one cluster because they watch different resource kinds. Keep the old path live and warm.
Shift traffic at a layer you control instantly. Weighted DNS with a low TTL, or a load balancer target group weight, both work. What you want is a revert measured in minutes without a redeploy. If your rollback plan involves re-applying manifests and waiting for a controller to reconcile, it is not a rollback plan.
Then rehearse it. Do a cutover drill in a lower environment: shift 100 percent, break something on purpose, revert, and time it end to end. Write the number down. That number is the only honest input to a go or no-go decision.
Decide your abort criteria before the window opens and make them numeric. Error rate above baseline by some margin, p99 latency above a threshold, any 5xx on a named critical path. Agreeing thresholds while an incident channel fills up produces bad decisions.
Keep Ingress-NGINX installed but idle for at least one full business cycle after cutover, and remove it only when the parity diff has been clean throughout. The security argument for removing it fast applies to exposed Ingress-NGINX, so scale it down and take its listener out of the public path first. That captures most of the risk reduction while keeping the revert.
A migration test checklist
| Stage | Check | Gate |
|---|---|---|
| Pre-migration | Controller conformance report reviewed for target version | Manual sign-off |
| Pre-migration | Required features present in GatewayClass supportedFeatures | Automated, blocking |
| Translation | Every converter warning triaged and dispositioned | Manual sign-off |
| Translation | Annotation inventory classified and reviewed | Manual sign-off |
| Translation | Generated manifests pass policy and hardening checks | Automated, blocking |
| Parity | Golden corpus replay diff clean on status, redirects, headers | Automated, blocking |
| Parity | TLS issuance, rotation and backend TLS verified | Automated |
| Parity | Timeout, body size, WebSocket and SSE regressions tested | Automated |
| Resilience | Controller restart under load, connection drop measured | Manual, scheduled |
| Cutover | Rollback drill completed and revert time recorded | Manual, blocking |
| Post-cutover | Parity diff clean for one full business cycle | Automated |
| Cleanup | Old controller removed from public path, then uninstalled | Manual |
If you want the wider tooling context around these checks, our Kubernetes QA tools comparison maps which scanners and validators cover which stage.
The realistic timeline
For a mid-sized platform with a few hundred Ingress resources, budget roughly six to ten weeks: one to two weeks evaluating controllers against conformance evidence, two to three weeks on translation and annotation redesign, two to three weeks of parity testing including a full week of mirrored traffic, and a week for cutover plus soak.
Teams that compress this to a weekend get away with it on simple routing and get burned on the tail: one partner integration depending on a rewrite quirk, one endpoint whose CORS headers were annotation-driven, one cron job hitting a path nobody sampled. Cheap to catch with a corpus replay, expensive to catch in production.
The retirement deadline has passed. Migrating carefully is still faster than migrating twice.
Frequently Asked Questions
How do I validate a Gateway API migration before cutting over production traffic?
Validate in four layers, in order. First, conformance: confirm your chosen controller passes the Gateway API conformance suite for the features you depend on, and read its GatewayClass status.supportedFeatures rather than trusting its marketing page. Second, translation review: treat ingress2gateway output as a draft and manually resolve everything it warns about. Third, traffic parity: replay a golden corpus of real requests against old and new data planes and diff status codes, headers, redirects and rewrites. Fourth, rollback: prove you can revert at the DNS or load balancer layer in minutes, and test that path before you need it.
Is the Kubernetes Ingress API being removed?
No. The Ingress API itself remains part of Kubernetes core and is not scheduled for removal. What retired is the kubernetes/ingress-nginx controller project, which reached end of life on 24 March 2026 with the repository set read-only and no further bug fixes or CVE patches. If you run a different, actively maintained Ingress controller such as Traefik, HAProxy or Kong, your Ingress resources keep working and there is no forced migration. The urgency applies specifically to clusters running Ingress-NGINX.
What is the Gateway API conformance suite and how do I run it?
It is a behaviour-driven test suite maintained by the Gateway API project that checks whether an implementation actually matches the specification, split into Gateway (north-south) tests and Mesh tests. You run it against a live cluster with something like go test ./conformance -run TestConformance plus flags naming your GatewayClass and the features you claim to support. Useful flags include one for conformance profiles, one to exempt features you do not use, and one to leave test resources in place for inspection. Implementations publish conformance reports to the project repository, so you can also read someone else's results before you install anything.
Can ingress2gateway convert all my Ingress-NGINX annotations?
It converts a lot of them, and 1.0 was a large step up - the release covers 30 or more common Ingress-NGINX annotations including CORS, backend TLS, regex path matching and rewrites, versus a handful before 1.0. It also ships controller-level integration tests that compare live runtime behaviour between Ingress-NGINX and a Gateway API implementation, which is a meaningful quality signal. But it explicitly warns about configuration it cannot translate and suggests alternatives instead of silently dropping it. Read every warning. The output is a starting manifest, not a finished migration.
Which Gateway API version should I target in 2026?
Target the latest stable release your controller supports, and check the Standard channel rather than Experimental for anything production-facing. Gateway API v1.4.0 moved BackendTLSPolicy, named rules for Routes and supportedFeatures in GatewayClass status into the Standard channel, with a v1.4.1 patch correcting installation YAML in February 2026. Features still in the Experimental channel, such as the dedicated Mesh resource and the externalAuth HTTPRoute filter at the time of the v1.4.0 release, can change in breaking ways or be removed, so avoid building production dependencies on them.
How do I test traffic parity between Ingress and Gateway API?
Build a golden request corpus from real traffic - sample your access logs across a full week so you catch weekly batch and reporting paths - then replay it against both data planes and diff the responses. Compare status code, final URL after redirects, response headers, and body hash for cacheable content. Gateway API's request mirroring can shadow live traffic to the new stack without affecting user responses, which is the cleanest parity signal you can get, but mirroring support varies by implementation so confirm it appears in your GatewayClass supported features first. Run the diff continuously for at least one full business cycle before cutting over.
Ship Kubernetes with Confidence
Free for open-source use. No credit card required. Install kubeqa and run your first cluster scan in under 5 minutes.
Get Started Free