Ingress-NGINX Ends on AKS in November 2026: A Gateway API Migration Playbook
Ingress-NGINX Ends on AKS in November 2026: A Gateway API Migration Playbook
Most forced migrations in Azure are boring — bump an API version, change a SKU, move on. This one is not. Ingress-NGINX has an enormous installed base on AKS, the deadline is hard, and the replacement is not the same thing under a new name. It is a different data plane, a different object model, and a different split of responsibility between your platform and application teams.
This article is the map: what exactly ends, what replaces it, how to translate your annotations, and above all what has no equivalent — because those three annotations are what turn a one-week migration into a one-month one.
Two dates that matter
| Date | What happened / happens |
|---|---|
| March 2026 | The upstream ingress-nginx project stopped maintenance |
| November 2026 | AKS ships the last critical security patch for managed NGINX |
Nothing breaks after November 2026. The controller keeps running. But new NGINX CVEs will not be fixed, and that is the difference between "it works" and "it passes an audit". If you run anything under NIS2, PCI DSS, or a bank's internal security baseline, December 2026 is the month you have an unsupported component sitting at the network edge.
So plan for October 2026 as the real cutover, not November. You want a month of slack, not a race to the final patch.
What replaces it
The replacement is the App Routing add-on with a Gateway API implementation. It went GA in AKS release 20260428 and brought three things:
- a
GatewayClassnamedapprouting-istio— the data plane is Envoy driven by Istio, operated by Microsoft - managed installation of the Gateway API CRDs and controller — you no longer install them yourself or worry about something overwriting them
- release
20260529added Azure DNS and Key Vault integration, plus structured JSON Envoy access logs on stdout by default
That last item is quieter than it deserves. If you currently install cert-manager and external-dns on every cluster so that ingress can do TLS and DNS, you can uninstall both after this migration. Certificates are referenced straight from Key Vault without a SecretProviderClass, and the DNS record in your Azure DNS zone appears on its own.
The shift you need to grasp before the syntax
Ingress was one object. Gateway API is two, split by who owns them:
Ingress (1 object, owned by ... someone)
│
├─→ Gateway ← platform team: listeners, ports, TLS, IP address
│ one per cluster or per environment
│
└─→ HTTPRoute ← application team: hostnames, paths, backends, filters
one per app, lives in the app's namespaceThis is not cosmetic. It means application teams can no longer touch TLS configuration or the shared IP address — and conversely, the platform team no longer has to approve every path change. If you have been running one Ingress per application with everything in it, this migration imposes that separation whether you wanted it or not.
The Gateway belongs to the platform team:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gw-prod
namespace: platform
spec:
gatewayClassName: approuting-istio
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: '*.example.com'
tls:
mode: Terminate
certificateRefs:
# Key Vault directly, no SecretProviderClass
- kind: Secret
name: kv-wildcard-example-com
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: 'true'The HTTPRoute belongs to the application team, in its own namespace:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api
namespace: prod
spec:
parentRefs:
- name: gw-prod
namespace: platform
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: svc-api
port: 8080Note allowedRoutes on the Gateway. That is a security boundary Ingress never had — without it, any namespace can attach a route to your production IP.
Annotation mapping
This is the bulk of the work. Go through your Ingress objects annotation by annotation:
nginx.ingress.kubernetes.io/ annotation | Gateway API equivalent |
|---|---|
rewrite-target | URLRewrite filter, path.replacePrefixMatch |
ssl-redirect / force-ssl-redirect | RequestRedirect filter, scheme: https, statusCode: 301 |
permanent-redirect | RequestRedirect filter with hostname and path |
backend-protocol: GRPC | a separate GRPCRoute object |
canary + canary-weight | multiple backendRefs with a weight field |
canary-by-header | matches.headers — native, and more readable than the annotation |
cors-allow-* | partly ResponseHeaderModifier, otherwise Istio |
proxy-body-size | none in Gateway API — Istio ProxyConfig |
rate-limit-* | none — Envoy rate limiting via Istio |
auth-url / auth-signin | none — Istio AuthorizationPolicy (ext_authz) |
configuration-snippet | none, and there never will be |
server-snippet | none, and there never will be |
Those last two rows are the difference between a week and a month. configuration-snippet is the escape hatch teams have been pasting everything into for years, whenever an annotation fell short — and Gateway API is deliberately typed, so an equivalent will never exist. Every snippet has to be hand-translated into Istio configuration, or dropped.
Audit: size the job before you promise anything
Run this before you give an estimate. It lists every nginx.ingress annotation in the cluster with its occurrence count:
kubectl get ingress -A -o json \
| jq -r '.items[]
| . as $i
| (.metadata.annotations // {})
| to_entries[]
| select(.key | startswith("nginx.ingress.kubernetes.io/"))
| "\(.key)"' \
| sort | uniq -c | sort -rnTypical output from a mid-sized cluster looks like this:
34 nginx.ingress.kubernetes.io/rewrite-target
28 nginx.ingress.kubernetes.io/ssl-redirect
19 nginx.ingress.kubernetes.io/proxy-body-size
7 nginx.ingress.kubernetes.io/configuration-snippet
4 nginx.ingress.kubernetes.io/auth-url
2 nginx.ingress.kubernetes.io/canaryIgnore the top two, they are mechanical. Your actual work is the bottom three rows — and you need to read all seven configuration-snippet values individually, because each one contains something different.
The second query you want returns the namespaces owning each affected Ingress, which is your list of teams to talk to:
kubectl get ingress -A \
-o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,CLASS:.spec.ingressClassName \
--no-headers | sort | uniq -c | awk '{print $2}' | sort -uPhasing that works
Gateway API and Ingress can run side by side in the same cluster. Use that — a big-bang cutover makes no sense here.
- Enable App Routing with Gateway API and leave the old NGINX running. Nothing breaks; you simply have a second data plane.
- Build the
Gatewayin a platform namespace, with its own IP and a certificate from Key Vault. Test it on a throwaway hostname. - Migrate applications one at a time, easiest first. Create an
HTTPRoutefor each, verify on a temporary hostname, then move DNS. - Leave the
configuration-snippetapplications until last. Those need Istio configuration and possibly a decision that the behaviour is being dropped. - Uninstall
cert-managerandexternal-dnsonly at the very end, once nothing on the ingress path needs them. - Delete the NGINX controller — only then is the migration done.
Steps 1–3 fit in a normal sprint. Step 4 deserves its own estimate, which is exactly why you want the audit from the previous section before you commit to a date.
Where the line with Istio sits
If you are heading towards a service mesh anyway, consider going there directly. On AKS Automatic with Kubernetes 1.36+ you can disable the default app-routing add-on and run the Istio add-on with Istio CNI. You get the same Gateway API, with full control over mesh configuration.
The rule I use:
- You only want ingress → App Routing. The
approuting-istioGatewayClass uses Istio under the hood anyway, but Microsoft owns the upgrade cycle. - You want mTLS between services, L7 authorisation, or traffic mirroring → go straight to the Istio add-on. Otherwise you will be turning App Routing off again in six months.
If you are also revisiting network policy on the same cluster, that conversation overlaps with the dataplane choice — I covered it separately in the piece on migrating from Calico to Cilium.
What to take away
The deadline is November 2026, but your real date is October — you want a month of slack, not a sprint to the final patch. This is not a drop-in swap: the object model and the platform/application responsibility split both change, which makes it a process change, not just a YAML change.
And do not give an estimate until you have run that audit script. The gap between a cluster with only rewrite-target and ssl-redirect and one with seven configuration-snippet values is an order of magnitude.
The other things you want settled in an AKS cluster before a change this size are in my AKS production checklist. If you are planning a Gateway API migration across a larger estate and want a second opinion on phasing, take a look at my cloud architecture services.
Sources
- App Routing: Gateway API GA — AKS blog, 10 June 2026
- Azure/AKS issue #5516 — managed NGINX support timeline
About the author

Martin Rylko
Senior Cloud Architect & DevOps Engineer
14+ years in IT – from on-premises datacenters and Hyper-V clustering to cloud infrastructure on Microsoft Azure. I specialize in Landing Zones, IaC automation, Kubernetes and security compliance.
Frequently Asked Questions
What is the actual deadline for leaving Ingress-NGINX on AKS?▾
Is this just a controller swap, or do my manifests change?▾
What replaces cert-manager and external-dns?▾
Can I skip App Routing and deploy Istio directly?▾
You might also like
AKS Breaking Changes: What Is Retiring in March 2026 and How to Migrate
Windows Server 2019, Azure Linux 2.0, and kubelet certificate rotation – three AKS retirements with March 2026 deadlines. Practical migration guide with CLI commands and Bicep templates.
ReadAKS Cilium NetworkPolicy: Migrating From Calico Without Production Downtime
Practical playbook for migrating an AKS cluster from the Calico Network Policy engine to Azure CNI Powered by Cilium. Zero-downtime procedure, eBPF benefits, and typical rollout traps.
ReadAzure Container Apps vs AKS: A 2026 Decision Matrix
When to choose Azure Container Apps and when AKS – cost, operations overhead, networking, and typical use cases. Real decision examples from three different projects.
Read