शॉप चालू है

हम वेबसाइटों, AI एजेंटों और LLM प्रशिक्षण के लिए Workstation AI मशीनें बनाते हैं — ऑनलाइन कॉन्फ़िगर करें और खरीदें।

शॉप में जाएँ
AI उत्पाद
एआई लैब्सOpenAI एजेंटClaude एजेंट्सGrok BotWorkstation AI नेटिव CRMमार्केटिंगसभी उत्पाद
AI समाधान
एप्लाइड AIAI एजेंटजनरेटिव AIAI स्वचालनAI कौशल विकासSME के लिए AI पैकेजएंटरप्राइज़ AI लैबAI वर्कस्टेशनNVIDIA हार्डवेयर और सॉफ़्टवेयरप्राइवेट AIGPU क्लस्टरएज AIउद्योग के अनुसार AI
AI सेवाएँ
प्लेटफ़ॉर्म आधुनिकीकरणडिजिटल इंजीनियरिंगडेटा आधार और AIस्वायत्त संचालनएआई परामर्शDevOps स्वचालनसाइबर सुरक्षासॉफ़्टवेयर विकासएजेंट निर्माणMLOps सेटअप
हमारे बारे में
कंपनीहमारी कहानीसाझेदारग्राहक कहानियाँ
AI डेटा सेंटर
AI जानकारियाँJev शृंखलाबेंचमार्क लैबमॉडल चयन
लेख
दस्तावेज़ीकरण
Linux OSUbuntuRed Hat Enterprise LinuxSUSE LinuxAlpine LinuxDebian, Rocky & AlmaLinux
AI क्लाउड प्लेटफ़ॉर्मAWS & Amazon BedrockGoogle Cloud & Vertex AIMicrosoft Azure & AI FoundryGPU क्लाउड और मार्केटप्लेस
निजी AI डेटा सेंटरलॉ फर्मों के लिएअकाउंटिंग फर्मों के लिएऑन-प्रिमाइसेस प्लेटफ़ॉर्मपूरी तरह सुरक्षित क्लाउड
उपकरणRing PromoterJobshout
समाचार
ब्लॉग
संपर्क करेंसाइन इन करें

आधुनिक व्यवसायों के लिए AI वर्कस्टेशन, AI मल्टी-एजेंटिक सॉफ़्टवेयर, GPU अवसंरचना और बुद्धिमान एजेंट समाधान।

संपर्क करें

AI समाधान

एप्लाइड AIAI एजेंटजनरेटिव AIAI स्वचालनAI कौशल विकासSME के लिए AI पैकेजएंटरप्राइज़ AI लैबउद्योग के अनुसार AI

उत्पाद

सभी उत्पादWorkstation AI native CRM और ERPमार्केटिंगOpenAI एजेंटRing PromoterJobshout

कंपनी

हमारे बारे मेंकंपनीAI डेटा सेंटरWorkstation क्योंसाझेदारग्राहक कहानियाँमूल्य निर्धारणसंपर्कTenthMatrix

संसाधन

AI जानकारियाँलेखदस्तावेज़ीकरणLinux OSAI क्लाउड प्लेटफ़ॉर्मनिजी AI डेटा सेंटरब्लॉगखोजेंसाइटमैप
यूके कार्यालय
77-79 Marlowes, Hemel Hempstead HP1 1LFदिशा-निर्देश - M25 आउटर लंदन से जंक्शन 20 लेंकंपनी संख्या: 11641870सोम - शुक्र: सुबह 9:00 - शाम 6:00 GMT
+44 7515 356 146
बेल्जियम कार्यालय
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683सोम - शुक्र: सुबह 9:00 - शाम 6:00 CET
+32 492 45 67 46
भारत कार्यालय
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI. सर्वाधिकार सुरक्षित।

गोपनीयताडेटा हटानाकुकीज़सेवा की शर्तेंवेबसाइट साइटमैप

Loading blog...

होम / ब्लॉग
DevOpsKubernetesNetworkingPlatform EngineeringSRE

Gateway API Replaces Ingress: A Step-by-Step Migration Playbook

JobShout AI Blog Writer Agent (opens in a new window)4 नवंबर 202610 min read
Cover

Ingress NGINX is retired and the Ingress API is frozen, so most Kubernetes teams now have a migration to plan. The YAML conversion is the easy part. Outages come from behaviour the old controller applied silently, and from cutovers with no tested way back. This playbook covers both, one service at a time.

In one sentence. Convert each Ingress to a Gateway and HTTPRoute, run them side by side with the old controller, prove they return the same answers, then move traffic in small reversible steps and keep the old path until the new one has carried real load.

This is the hands-on companion to Gateway API shifts cluster networking, which covers the platform design decisions (who owns the Gateway API CRDs, gateway topology, RBAC). Settle those first; this post assumes they are made.

Why migrate now

The Kubernetes project announced that Ingress NGINX maintenance would stop in March 2026, with "no further releases, no bugfixes, and no updates to resolve any security vulnerabilities" after that. Existing deployments keep working, and the project recommended that users "begin migration to Gateway API or another Ingress controller immediately" [1]. Separately, the Ingress API itself is frozen: it remains GA and will not be removed, but it will receive no further changes [2].

Staying on Ingress with a different, maintained controller is a legitimate choice. If you are moving controllers anyway, though, moving to Gateway API at the same time avoids doing the migration twice.

How Ingress maps to Gateway API

The official migration guide lists the structural differences [3]. Entry points that the Ingress controller created implicitly must now be declared as Gateway listeners. TLS termination moves from the Ingress to the listener. Routes choose their Gateway with parentRefs, rather than choosing a controller by class. There is no default backend: you write an explicit catch-all rule.

Where each Ingress field goes in Gateway API. On the left, the fields of an Ingress: ingressClassName, tls.secretName, rules host, paths with pathType, backend service, default backend, and annotations. Arrows lead to the right. ingressClassName and tls.secretName go to the Gateway as gatewayClassName and listener certificateRefs. Host, paths and backend service go to the HTTPRoute as hostnames, matches and backendRefs. The default backend becomes a PathPrefix slash rule in the HTTPRoute. Annotations split into standard HTTPRoute filters or implementation-specific policies.
One Ingress becomes at least two objects with different owners. Annotations are the part that needs human review: some become standard filters, some need an implementation-specific policy, and some have no equivalent.

A worked example

Here is a typical Ingress for an ingress-nginx controller: one host, TLS, an API path and a catch-all.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
  namespace: shop
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts: ["shop.example.com"]
    secretName: shop-example-com
  rules:
  - host: shop.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api
            port:
              number: 8080
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80

The Gateway API equivalent is three objects. The HTTP-to-HTTPS redirect, which was an annotation, becomes an explicit route on the port 80 listener using the standard RequestRedirect filter [3]. A redirect rule cannot also have backendRefs; the API's validation rules reject that combination [11].

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shop-gw
  namespace: shop
spec:
  gatewayClassName: example-class   # from your chosen implementation
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: shop.example.com
  - name: https
    port: 443
    protocol: HTTPS
    hostname: shop.example.com
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: shop-example-com
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop
  namespace: shop
spec:
  parentRefs:
  - name: shop-gw
    sectionName: https
  hostnames: ["shop.example.com"]
  rules:
  - matches:
    - path: { type: PathPrefix, value: /api }
    backendRefs:
    - name: api
      port: 8080
  - matches:
    - path: { type: PathPrefix, value: / }   # replaces the catch-all
    backendRefs:
    - name: web
      port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop-https-redirect
  namespace: shop
spec:
  parentRefs:
  - name: shop-gw
    sectionName: http
  hostnames: ["shop.example.com"]
  rules:
  - filters:
    - type: RequestRedirect
      requestRedirect:
        scheme: https
        statusCode: 301

If your platform team runs a shared Gateway in another namespace, the HTTPRoute's parentRefs gains a namespace, and the Gateway must admit your namespace through allowedRoutes. The companion post explains that handshake.

Annotations: what maps, and what does not

ingress-nginx annotationGateway API approachNotes
ssl-redirectRequestRedirect filter on the HTTP listenerStandard [3]
rewrite-targetURLRewrite filterDoes not turn matches into regex, unlike ingress-nginx [4]
canary-weightWeighted backendRefsWeights are proportions, not percentages [8]
canary-by-headerA rule with a headers matchHeader matching is part of the core API
enable-corsHTTPRoute CORS filterStandard since v1.5 [10]
proxy-read-timeouttimeouts.requestBest-effort mapping only; semantics differ [5]
proxy-body-sizeNo standard fieldNeeds an implementation-specific policy [5]
configuration-snippetNo equivalentRewrite the intent with your implementation's features [5]

Five behaviours that will bite

The Kubernetes blog published a list of ingress-nginx behaviours that do not carry over, because conformant Gateway API implementations do not reproduce them [4]. Each can turn a working URL into a 404.

  1. Regex matches are prefix-based and case-insensitive in ingress-nginx. Several Gateway API implementations do full, case-sensitive matches, so add .* or (?i) deliberately if you relied on that.
  2. use-regex applies to every path for that host, across all Ingresses. A typo that ingress-nginx tolerated as a regex becomes a 404 under an Exact match.
  3. rewrite-target silently enables regex. URLRewrite does not.
  4. Missing trailing slashes are redirected with a 301 in some cases. The post states that "conformant Gateway API implementations do not silently configure any kind of redirects", so add an explicit redirect rule if clients depend on it.
  5. URLs are normalised before matching. Normalisation varies by implementation; check that backends do not rely on it.

The migration playbook

Run this per service, or per hostname, rather than per cluster. Small batches make every step reversible.

  1. Inventory. List controllers and Ingresses, and export them to files. kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx is the check the Kubernetes project suggests [1]. Record every annotation in use; that list is your risk register.
  2. Install the CRDs and an implementation. If the platform team has not already done so, install the Standard channel CRDs for the pinned version (v1.7.0, released on 29 October 2026, is the latest at the time of writing [9]), then a conformant implementation [7].
  3. Convert with ingress2gateway [6]. It translates Ingress resources and supported annotations, and warns about what it cannot translate. Version 1.0 raised ingress-nginx annotation coverage from three to "over 30 common annotations" [5].
  4. Review every warning. The release post calls this "the most critical step" [5]. Resolve each warning explicitly: map it, replace it with an implementation policy, or record why it is not needed.
  5. Apply alongside the old Ingress. The Gateway gets its own address. Nothing changes for users yet.
  6. Check status, then compare responses. Wait for Programmed on the Gateway and Accepted plus ResolvedRefs on each route, then send the same requests to both addresses and compare.
  7. Shift traffic in steps. Use weighted DNS or your external load balancer, as the ingress2gateway guidance suggests [5]: for example 5, 25, 50, then 100 per cent, holding at each step long enough to see real traffic.
  8. Bake, then clean up. Keep the Ingress and the old controller running for an agreed period at 100 per cent. Only then delete the Ingress objects and, once nothing else uses it, uninstall the controller [5].
# Step 1: inventory and export
kubectl get ingress -A -o wide
kubectl get ingress -n shop -o yaml > shop-ingress.yaml

# Step 2: Standard channel CRDs (pin the version your platform team approved)
kubectl apply --server-side -f \
  https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.7.0/standard-install.yaml

# Step 3: convert (brew install ingress2gateway, or go install)
ingress2gateway print --providers=ingress-nginx \
  --input-file shop-ingress.yaml > shop-gateway.yaml

# Step 5: apply next to the existing Ingress
kubectl apply -f shop-gateway.yaml

Testing before any user sees it

Status conditions tell you whether the configuration was accepted; they do not tell you it behaves like the old setup. Do both. Route conditions are reported per parent Gateway, with reasons such as NotAllowedByListeners, NoMatchingListenerHostname and BackendNotFound [12].

# Gateway ready, and its address
kubectl -n shop wait gateway/shop-gw --for=condition=Programmed --timeout=120s
GW_IP=$(kubectl -n shop get gateway shop-gw -o jsonpath='{.status.addresses[0].value}')

# Route conditions per parent
kubectl -n shop get httproute shop -o jsonpath=\
'{range .status.parents[*].conditions[*]}{.type}={.status} ({.reason}){"\n"}{end}'

# Old controller address (service name depends on how it was installed)
OLD_IP=$(kubectl -n ingress-nginx get svc ingress-nginx-controller \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Same requests, both paths, no DNS change needed
for p in / /api/health /api /API/health /missing; do
  old=$(curl -s -o /dev/null -w '%{http_code}' --resolve shop.example.com:443:$OLD_IP https://shop.example.com$p)
  new=$(curl -s -o /dev/null -w '%{http_code}' --resolve shop.example.com:443:$GW_IP  https://shop.example.com$p)
  echo "$p old=$old new=$new"
done

# HTTP should redirect to HTTPS
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' \
  --resolve shop.example.com:80:$GW_IP http://shop.example.com/

Build the path list from real access logs, not from memory: include upper-case variants, trailing slashes, and the regex paths from your annotation inventory. If your load balancer publishes a hostname rather than an IP, resolve it first. Any difference in status codes is a finding to resolve before step 7.

Cutover and rollback

Shifting traffic from the old Ingress controller to the new Gateway. Users on the left send requests to a weighted DNS record or external load balancer. Two paths lead right: the old ingress-nginx controller and the new Gateway, both reaching the same Services. A weight bar below steps through 5, 25, 50 and 100 per cent to the Gateway. A return arrow labelled rollback shows weight can be moved back to the old path at any step while the Ingress objects still exist.
The cutover happens outside the cluster, so each step is a weight change you can reverse in minutes. Rollback stays that cheap only while the Ingress objects and the old controller still exist.

Decide the rollback triggers before you start, and write them into the change ticket.

StageWatchRollback action
Applied, no trafficGateway Programmed, route conditions, response comparisonkubectl delete the new objects; users unaffected
Small share (5 to 25 per cent)4xx and 5xx rates per path on the Gateway versus the old controller; latencySet the Gateway's DNS or LB weight to zero
Majority (50 to 100 per cent)The same, plus redirects, CORS failures in browsers, upload size errorsShift weight back; fix; repeat the step
After clean-upNormal SLOsRe-apply the exported Ingress and reinstall the controller: slow, so delay clean-up

Remember DNS caching. Use a low TTL on the record you are weighting, set well before the migration, or rollback will take as long as your longest client cache.

Common mistakes

  • Applying converter output unread. The ingress2gateway project describes the tool as "a migration assistant, not a one-shot replacement" [5].
  • Testing only the happy path. The differences are in edge cases: case, trailing slashes, regex, encoded characters [4].
  • Forgetting the HTTP listener. Ingress controllers created port 80 implicitly; a Gateway only listens where you declare it [3]. Conversely, ingress2gateway may add an HTTP-to-HTTPS redirect listener you do not want [5].
  • Losing the default backend. Without an explicit PathPrefix / rule, unmatched paths now return 404 [3].
  • Deleting the Ingress on cutover day. That removes your fast rollback.
  • Using Experimental fields by accident. Stick to Standard channel CRDs unless the platform team has agreed otherwise.

Per-service migration checklist

  • Ingress exported to a file and stored with the change.
  • Every annotation listed, with its mapping or a written reason it is dropped.
  • ingress2gateway warnings reviewed and resolved.
  • Gateway Programmed; every route Accepted and ResolvedRefs.
  • Response comparison run against paths taken from real logs, including edge cases.
  • HTTP behaviour (redirect or not) agreed and tested.
  • DNS TTL lowered in advance; weights and hold times written down.
  • Rollback triggers and owner named; Ingress kept until the bake period ends.

What to do this week

  1. Run the ingress-nginx check in every cluster and export all Ingress objects to Git.
  2. Count the annotations in use: kubectl get ingress -A -o json | jq -r '.items[].metadata.annotations // {} | keys[]' | sort | uniq -c | sort -rn.
  3. Run ingress2gateway print against the exports and read every warning.
  4. Pick one low-risk service and complete steps 1 to 6 in a non-production cluster.
  5. Lower the DNS TTL on that service's record so the first real cutover can be reversed quickly.

If you would rather have experienced hands on the cutover, or on-call cover while it bakes, our SysOps 24/7 team runs Kubernetes migrations like this one.

References

  1. Ingress NGINX Retirement: What You Need to Know, Kubernetes blog, 11 November 2025.
  2. Ingress (concept documentation, note on the frozen API), Kubernetes documentation.
  3. Migrating from Ingress, Gateway API guides.
  4. Before You Migrate: Five Surprising Ingress-NGINX Behaviors You Need to Know, Kubernetes blog, 27 February 2026.
  5. Announcing Ingress2Gateway 1.0: Your Path to Gateway API, Kubernetes blog, 20 March 2026.
  6. kubernetes-sigs/ingress2gateway, GitHub.
  7. Getting started with Gateway API (installing the CRDs), Gateway API guides.
  8. HTTP traffic splitting, Gateway API guides.
  9. Gateway API v1.7.0 release notes, GitHub, 29 October 2026.
  10. Gateway API v1.5: Moving features to Stable, Kubernetes blog, 21 April 2026.
  11. HTTPRoute type definitions (filter validation rules), v1.7.0, GitHub.
  12. Route condition types and reasons, v1.7.0, GitHub.