Martin Rylko
  • Services
  • Blog
  • About
  • Contact
  • Get in Touch
Martin Rylko

Senior Cloud Architect & DevOps Engineer. Specializing in Microsoft Azure, IaC, Cloud Security and AI.

Navigation

  • Services
  • Blog
  • About
  • Contact

Collaboration

Looking for an experienced architect for your Azure project? Get in touch.

rylko@cloudmasters.cz

© 2026 Martin Rylko. All rights reserved.

Built in the cloud. Deployed via Azure Static Web Apps.

Home/Blog/Ingress-NGINX Ends on AKS in November 2026: A Gateway API Migration Playbook
All articlesČíst česky

Ingress-NGINX Ends on AKS in November 2026: A Gateway API Migration Playbook

7/9/2026 6 min
#AKS#Kubernetes#Gateway API#Ingress#Azure#Migration

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

DateWhat happened / happens
March 2026The upstream ingress-nginx project stopped maintenance
November 2026AKS 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 GatewayClass named approuting-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 20260529 added 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 namespace

This 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: 8080

Note 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/ annotationGateway API equivalent
rewrite-targetURLRewrite filter, path.replacePrefixMatch
ssl-redirect / force-ssl-redirectRequestRedirect filter, scheme: https, statusCode: 301
permanent-redirectRequestRedirect filter with hostname and path
backend-protocol: GRPCa separate GRPCRoute object
canary + canary-weightmultiple backendRefs with a weight field
canary-by-headermatches.headers — native, and more readable than the annotation
cors-allow-*partly ResponseHeaderModifier, otherwise Istio
proxy-body-sizenone in Gateway API — Istio ProxyConfig
rate-limit-*none — Envoy rate limiting via Istio
auth-url / auth-signinnone — Istio AuthorizationPolicy (ext_authz)
configuration-snippetnone, and there never will be
server-snippetnone, 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 -rn

Typical 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/canary

Ignore 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 -u

Phasing 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.

  1. Enable App Routing with Gateway API and leave the old NGINX running. Nothing breaks; you simply have a second data plane.
  2. Build the Gateway in a platform namespace, with its own IP and a certificate from Key Vault. Test it on a throwaway hostname.
  3. Migrate applications one at a time, easiest first. Create an HTTPRoute for each, verify on a temporary hostname, then move DNS.
  4. Leave the configuration-snippet applications until last. Those need Istio configuration and possibly a decision that the behaviour is being dropped.
  5. Uninstall cert-manager and external-dns only at the very end, once nothing on the ingress path needs them.
  6. 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-istio GatewayClass 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
Tags:#AKS#Kubernetes#Gateway API#Ingress#Azure#Migration
LinkedInX / Twitter

About the author

Martin Rylko

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.

Email LinkedInFull profile

Frequently Asked Questions

What is the actual deadline for leaving Ingress-NGINX on AKS?▾
The upstream ingress-nginx project stopped maintenance in March 2026. Microsoft has committed to shipping critical security patches for managed NGINX on AKS only until November 2026. Nothing switches off after that date — your controller keeps running — but new CVEs will not be fixed. For a regulated workload that means from December 2026 you are operating an unsupported component at the network edge, which no audit will accept.
Is this just a controller swap, or do my manifests change?▾
Your manifests change. This is not a drop-in replacement. One Ingress object becomes a pair: Gateway (infrastructure, owned by the platform team) and HTTPRoute (routing, owned by the application team). The data plane is Envoy instead of NGINX, and behaviour is configured through typed fields instead of annotations. Most common annotations have an equivalent, but configuration-snippet and auth-url have none.
What replaces cert-manager and external-dns?▾
Since AKS release 20260529, App Routing integrates Azure DNS and Key Vault directly. A TLS certificate is referenced straight from Key Vault with no SecretProviderClass, and the DNS record in your Azure DNS zone is created automatically. For most clusters that means you can uninstall two Helm charts you had been maintaining yourself.
Can I skip App Routing and deploy Istio directly?▾
Yes, and on AKS Automatic with Kubernetes 1.36+ it is a supported path — disable the default app-routing add-on and run the Istio add-on with Istio CNI. It makes sense if you are heading towards a service mesh anyway. If you only want ingress, App Routing is fewer moving parts: the approuting-istio GatewayClass uses Istio under the hood regardless, but Microsoft operates it.

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.

Read

AKS 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.

Read

Azure 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