The community ingress-nginx controller is retired, so production clusters still running it no longer receive upstream fixes or security patches. A Kubernetes Ingress migration now belongs on the platform team’s operating plan, not the backlog.
The Kubernetes Ingress API itself remains available. What changed is the lifecycle of the kubernetes/ingress-nginx controller that interpreted those resources and routed traffic. Your existing manifests may continue to work today, but end-of-life edge software is a growing production and security risk.
A safe replacement starts with an inventory, runs both data planes in parallel, and moves traffic in controlled increments.
Key Takeaways
- The retirement affects the community Ingress NGINX controller, not the Kubernetes Ingress API.
- Inventory every
Ingress, annotation, ConfigMap setting, TLS dependency, and external DNS record before selecting a replacement. - Run the new Ingress controller beside NGINX Ingress with its own
IngressClassand load balancer. - Treat annotations as controller-specific configuration, not portable Kubernetes settings.
- Shift traffic by hostname or canary percentage, watch real service signals, and keep a tested rollback path until validation is complete.
What the NGINX Ingress Retirement Changes
The Kubernetes project announced that ingress-nginx would move into best-effort maintenance and then retire in March 2026. The project’s retirement guidance directs users toward Gateway API or another supported controller.
That distinction matters. A Kubernetes Ingress resource describes HTTP and HTTPS routing rules, mapping external traffic to your backend services. An ingress controller watches those objects and turns them into proxy configuration. ingress-nginx was one controller implementation. It was never the API itself.
Existing workloads won’t stop because the GitHub repository was archived. However, a newly discovered vulnerability, Kubernetes compatibility issue, or configuration bug won’t receive an upstream patch. That changes how security teams should classify the component.
The concern extends beyond the controller Deployment. Many clusters depend on behavior tied to:
- NGINX-specific annotations such as URL rewrite rules, CORS settings, authentication hooks, rate limiting, and request-size limits.
- Controller ConfigMap defaults, including timeouts, forwarded headers, custom error behavior, and TLS settings.
- Snippets that inject raw NGINX directives into generated configuration.
- A particular
IngressClass, service name, external load balancer, IP address, DNS record, or certificate workflow. - Alerts, dashboards, runbooks, and log-parsing rules built around NGINX metrics and log formats.
An application team might see a standard Ingress file. The platform team often sees years of accumulated edge policy hidden in annotations and cluster-wide settings.
A manifest can remain syntactically valid after a controller change while its routing, authentication, timeout, or rewrite behavior changes underneath it.
Start Kubernetes Ingress Migration With a Complete Inventory
Before choosing a successor, find every cluster where the retired controller runs. Include development, disaster recovery, regional clusters, and temporary environments. A forgotten staging cluster can become the next exposed production dependency.
List controller installations first. Helm releases, Deployments, DaemonSets, Services of type LoadBalancer, IngressClass objects, ConfigMaps, admission webhooks, and controller-specific custom resources all belong in the inventory.
Then collect all ingress objects, including their namespace, hostnames, paths, TLS secrets, class, annotations, and back-end services. Commands such as kubectl get ingress -A -o yaml provide the raw material, but a migration spreadsheet or an exported inventory file makes ownership and risk visible.
Group routes by behavior rather than namespace alone. A simple host-to-service route has a different migration risk than an internet-facing API with external authentication, WebSockets, 20-minute upload timeouts, IP allowlists, and regular-expression rewrites.
Record these details for every exposed endpoint:
| Inventory item | Questions to answer | Why it affects cutover |
|---|---|---|
| Hostname and DNS record | Who owns it, what is the TTL, and which load balancer does it target? | DNS controls how quickly clients reach the replacement endpoint. |
| TLS certificate | How is TLS termination and certificates handled, whether through cert-manager, cloud management, or manual renewal? | A certificate gap can turn a route migration into an outage. |
| Path and rewrite logic | Does the application receive the original path or a rewritten path? | Different controllers interpret matching and rewrites differently. |
| Authentication and policy | Are there external auth calls, mTLS, WAF rules, or source restrictions? | Security controls can disappear if they are not recreated. |
| Service behavior | Does traffic need HTTP/2, gRPC, WebSockets, sticky sessions, or long timeouts? | Protocol and connection handling differs by implementation. |
| Operational signals | Which SLOs, dashboards, alerts, and access logs cover the route? | Teams need evidence that the replacement behaves correctly. |
The AWS migration checklist also calls out cleanup of obsolete secrets and controller resources after validation, which is especially important when adopting tools like the AWS Load Balancer Controller. Do that at the end, not while the old path is still your rollback option.
Classify each route as low, medium, or high risk. Low-risk routes are internal tools or simple stateless services. High-risk routes include payment flows, customer authentication, large file uploads, gRPC APIs, and any hostname with strict availability commitments.

Choose the Replacement Based on Your Traffic Model
The right target depends on how much existing NGINX behavior you need to reproduce, which cloud you run, and whether you want to adopt Gateway API. Controller selection should come after the inventory because unsupported features often determine the answer.
Gateway API is Kubernetes’ newer set of networking resources. It separates infrastructure ownership from application routing. Platform teams commonly manage GatewayClass and Gateway objects, while application teams receive permission to create HTTPRoute resources in approved namespaces.
That separation can reduce the pressure to grant broad ingress annotation privileges. It also provides richer route matching, weighted back ends, header matching, and safe cross-namespace routing. Still, Gateway API support varies by controller and version. Tools like ingress2gateway can help evaluate how current definitions translate. Check the vendor’s conformance and feature documentation before promising an exact match.
A supported ingress controller may be the lower-risk first move when you need to preserve familiar Ingress semantics. Traefik, HAProxy, Kong, Contour, and NGINX Ingress Controller from F5 are common options. Cloud-managed L7 products can also fit teams that prefer provider-native integration with identity, WAF, and load-balancing services, such as using the AWS Load Balancer Controller to provision an Application Load Balancer. Custom Resource Definitions often extend these platforms beyond basic routing.
NGINX offers its own migration documentation for NGINX Ingress Controller. It is useful for assessing the move to its controller, but it does not make community annotations universally transferable. Review each translated setting and test it under real traffic.
Traefik also publishes a guide for migrating from NGINX Ingress. Its route and middleware model can work well for teams that want controller-native policy resources, but those resources create a new configuration model to operate.
Use this decision frame:
| Migration target | Best fit | Trade-off to evaluate |
|---|---|---|
| Supported Ingress controller | Teams that need a staged move with existing Ingress objects | Annotation support and default behavior differ by controller. |
| Gateway API implementation | Teams redesigning shared ingress ownership and traffic management | Requires new resource models, permissions, and route testing. |
| Cloud L7 controller | Teams heavily invested in one cloud provider’s network services | Portability, pricing, and provider-specific features need review. |
| Service mesh gateway | Organizations already operating a service mesh and policy layer | Adds operational scope if the mesh isn’t already a core platform service. |
Avoid selecting a controller because it claims broad annotation compatibility. Compatibility claims usually cover a subset of annotations. The remaining cases often contain the business-critical behavior.
Translate Resources, Not Assumptions
Translating an Ingress resource isn’t a global search-and-replace exercise. Start with ordinary host and path routing, then handle each extension deliberately.
For example, this is a representative basic Ingress shape:
apiVersion: networking.k8s.io/v1kind: Ingressspec.ingressClassName: replacement-ingressspec.rules[].host: api.example.comspec.rules[].http.paths[].path: /v1spec.rules[].http.paths[].pathType: Prefixspec.rules[].http.paths[].backend.service.name: payments-apispec.rules[].http.paths[].backend.service.port.number: 8080
The structure is portable Kubernetes API. The annotations are not. A setting such as nginx.ingress.kubernetes.io/proxy-read-timeout has no guaranteed equivalent in another controller. A rewrite annotation may need a controller-specific middleware, route filter, or an application change.
Gateway API uses different resource types. A representative HTTPRoute has kind: HTTPRoute, a parentRefs entry that targets a named Gateway, hostnames, matches, and backendRefs. A weighted migration can place two backendRefs under one rule, but support depends on the chosen implementation.
Keep examples separate from production configuration. The exact syntax for filters, redirects, header changes, rate limiting, authentication, and traffic weights differs by implementation and release. When moving beyond standard routing rules, modern controllers often rely on Custom Resource Definitions to handle capabilities missing from basic annotations. Apply vendor docs and version-specific tests to each route.
Snippets require special scrutiny. NGINX snippets may contain location, server, or http directives that have no equivalent outside NGINX. Some were introduced to bypass controller limitations, while others implemented critical security logic. Treat every snippet as code that needs review by platform and security owners.
Move shared defaults into an explicit design. If the old controller’s ConfigMap set 60-second timeouts, enabled real client IP handling, or configured a default certificate, document whether the replacement needs the same policy. Silent defaults are a common source of inconsistent behavior across clusters.
The Rancher retirement guide reinforces a staged approach based on deployment scenario. That is more dependable than treating every Ingress object as identical.
Run Both Controllers Before Moving Production DNS
Parallel operation limits the size of any mistake. Install the replacement Ingress controller with a distinct IngressClass, such as traefik-migration or gateway-public, along with a separate Application Load Balancer. Do not point new resources at the retired controller’s class.
This produces two independent traffic entry points. The old endpoint continues to receive live traffic. The new endpoint receives controlled validation traffic without changing the existing production route.
First, test through the replacement load balancer’s temporary hostname. If network policy permits it, use a private test hostname or a hosts-file override from a controlled client. Validate TLS termination, TLS SNI, redirects, headers, source IP behavior, authentication, and every non-HTTP protocol feature your application needs.
Next, create a non-production hostname under the same DNS zone. Use it to test certificate issuance and external DNS automation. DNS systems, load balancers, and certificate controllers often introduce delays that local tests cannot expose.
Lower DNS TTLs before the public cutover. Do it far enough ahead that recursive resolvers have aged out the former record. A 300-second TTL is common during a planned change, although cached records and enterprise DNS policies can still delay propagation.
If your provider supports weighted records or an L7 traffic split, use it for a narrow canary. Start with internal users or a small percentage of requests. DNS weighting lacks per-request precision because many clients cache answers, while controller-level weighted routing can be more exact when supported.
Keep the old controller and its load balancer intact until the new route proves stable. The old address is your fastest fallback.
Validate Application Behavior With Canary Traffic
A successful curl response doesn’t prove that an ingress cutover is safe. It only proves that one request reached one back end.
Build a test matrix around user-visible behavior. Include requests with and without authentication, redirects, unusual URL encoding, large request bodies, uploads, retries, CORS preflight calls, cache headers, and failure responses. For APIs, validate status codes and response headers. For browser workloads, test the full login and session path.
Compare old and new access logs where possible. Look for different upstream status distributions, changed request paths, unexpected redirects, missing headers, and altered client IPs. If the replacement controller changes the X-Forwarded-For chain, rate limiting policies and audit logs may behave differently.
Monitor the services, not only the gateway. During a canary using advanced traffic management controls, track:
- HTTP 4xx and 5xx rate by hostname, route, and upstream service.
- Latency at the load balancer and at the application, including p95 and p99 where available.
- Connection errors, TLS handshake failures, reset rates, and upstream retry counts.
- Pod CPU and memory for the replacement controller and the routed applications.
- Authentication failures, WAF blocks, payment errors, and other domain-specific business signals.
Set a clear observation window before changing public DNS. The right period depends on traffic patterns. A weekday business application may need a full workday. A global consumer system often needs enough time to cover high-volume periods and scheduled jobs.
Write the rollback trigger before the canary begins. For example, reverse the traffic change if 5xx errors exceed the normal baseline by an agreed threshold, if latency breaches the service objective, or if a security control fails. A rollback plan without measurable triggers turns a stressful incident into a debate.
Cut Over DNS Carefully and Keep Rollback Simple
Once canary results are stable, execute your DNS cutover by updating the production DNS record or provider traffic policy to point to the new load balancer. Change one hostname at a time for high-risk applications. A grouped change can work for low-risk services that share identical, tested routing rules.
Watch both controller endpoints while DNS caches expire. The old endpoint should drain gradually. A sudden spike there may reveal clients using pinned IPs, long-lived connections, hard-coded host mappings, or a forgotten DNS record.
Rollback should reverse the final traffic decision, not rebuild the old controller. Keep the prior DNS target, load balancer, IngressClass, certificates, and manifests available. Revert the record or traffic weight, confirm that traffic returns, and preserve logs for the investigation.
Document the actual cutover behavior. Record propagation time, active connection drain time, error changes, certificate events, and any manual fixes. Those details reduce risk for the next hostname and improve your platform runbook.
After every migration wave, update dashboards and alert rules. NGINX metric names, labels, and logs may not exist in the replacement. An alert that disappears during a controller change creates a monitoring blind spot at the worst time.
Decommission the Retired Controller Only After Proof
Remove Ingress NGINX only when no production hostname routes through it and no workload still specifies its IngressClass. Search Git repositories, GitOps inventories, Helm values, Terraform modules, and cluster objects to ensure every single Ingress resource has been successfully converted. Runtime checks alone can miss manifests that the next deployment will restore.
Delete controller-specific ConfigMaps, admission resources, obsolete load balancers, and unused TLS secrets after confirming ownership. Remove cloud firewall rules and DNS records that were unique to the former endpoint. Also revoke credentials or service accounts that no longer have a purpose.
Keep migration records. Future incident reviews often need to know when a hostname changed controllers, which policy replaced an annotation, and where the old metrics went. Treat that documentation as production configuration, not a temporary project artifact.
A controlled Kubernetes Ingress migration leaves the platform in a better state than it found it: explicit traffic policy, clear ownership, tested rollback, and supported software at the cluster edge.
Frequently Asked Questions
Is the Kubernetes Ingress API being deprecated?
No, the core Kubernetes Ingress API remains fully available and supported. The retirement affects only the community-maintained ingress-nginx controller implementation that translated those API resources into proxy configurations.
Can I simply copy my NGINX annotations to a new controller?
Most controller-specific annotations, especially NGINX snippets and custom rewrite rules, are not portable. You must translate them into the native routing rules, middlewares, or custom resources supported by your replacement controller.
What is the safest strategy for switching production traffic?
The safest approach involves deploying the new controller in parallel with its own load balancer, validating your routes using private tests or canary percentages, lowering DNS TTLs, and keeping the old path fully operational until metrics confirm stability.
Conclusion
The NGINX Ingress retirement does not require a rushed, all-at-once replacement. It requires a disciplined move away from an unsupported controller before an avoidable security or compatibility issue forces the schedule.
A successful Kubernetes Ingress migration inventories hidden dependencies, treats features as implementation-specific, and moves live traffic through a parallel path first. Keep the old route available until metrics, application behavior, and operational controls confirm the new Ingress controller is ready.

