Migrate Ingress to Kubernetes Gateway API: 2026 Tutorial
May 10, 2026
TL;DR
To migrate Ingress to Gateway API in 2026, you install the v1.5.1 Standard channel CRDs, run a conformant Gateway controller, and convert each existing Ingress with the ingress2gateway v1.0.0 CLI before cutting traffic over with weighted HTTPRoute rules. This guide walks through that exact sequence. You will migrate a working ingress-nginx deployment to Kubernetes Gateway API v1.5.1 end-to-end on a local kind v0.31.0 cluster. The walkthrough installs the Standard channel CRDs, runs Envoy Gateway v1.7.2 as the conformant controller, converts your existing Ingress YAML with ingress2gateway v1.0.0, lands the new Gateway and HTTPRoute resources, executes a weighted canary split between two app versions, and finishes with a verified rollback path. Every version is pinned, every command is copy-paste runnable, and the same pattern moves cleanly to GKE, EKS, AKS, or any conformant cluster.123
This guide exists because ingress-nginx reached end-of-life in March 2026 — no further releases, no bug fixes, no security patches, and the GitHub repository was archived on March 24, 2026.4 The community ingress-nginx controller was a default ingress path for a large share of cloud-native clusters, and the official replacement path is Gateway API. Most existing tutorials predate ingress2gateway 1.0 (released March 20, 2026, with support for over 30 ingress-nginx annotations2), and the official sigs.k8s.io guide is reference-style rather than copy-paste runnable. This post fills that gap.
What you will learn
- How to set up a local kind cluster that mirrors a real production layout for ingress-to-gateway migration
- How to install Gateway API v1.5.1 CRDs from the Standard channel
- How to install Envoy Gateway v1.7.2 as a conformant Gateway controller via Helm
- How to deploy a sample app behind ingress-nginx the way a typical 2024-era cluster does it
- How to use
ingress2gatewayv1.0.0 to convert that Ingress into aGateway+HTTPRouteautomatically - How to run both controllers in parallel with separate external IPs so the cutover is risk-free
- How to perform a weighted canary deployment with
HTTPRoutebackendRefs(no annotations required) - How to roll back safely when the canary regresses, and how to clean up the legacy Ingress only after
GatewayProgrammed=True - A migration checklist plus the five most common gotchas teams hit during real cutovers
Prerequisites
| Tool | Version pinned in this tutorial | Why this version |
|---|---|---|
| Docker (or Podman with the docker shim) | 25.x or newer | Required by kind v0.31.0 |
kind | v0.31.0 | Default node image is kindest/node:v1.35.0 (Kubernetes 1.35), released December 18, 202556 |
kubectl | matching v1.35.x | Match the cluster minor version |
helm | v3.18.0 or newer (3.20.2 recommended) | Envoy Gateway Helm chart targets Helm 3.x; 3.20.2 was the latest 3.x at time of writing7 |
go (only if installing ingress2gateway from source) | 1.22+ | Needed for go install |
ingress2gateway | v1.0.0 | First release with broad ingress-nginx annotation coverage2 |
| Gateway API CRDs | v1.5.1 (Standard channel) | Latest patch as of writing; v1.5.0 cut on February 27, 2026; v1.5.1 patch on March 14, 202618 |
| Envoy Gateway | v1.7.2 | Released April 17, 2026; conformant against Gateway API v1.53 |
You also need roughly 4 GB of free RAM for the kind cluster, the demo app, and Envoy Gateway, plus port 80/443 free on localhost.
Step 1: Create a kind cluster with port mapping
Save this as kind-config.yaml. The extraPortMappings block lets the host reach LoadBalancer services without cloud-provider-kind so the tutorial stays self-contained.
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.35.0
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 8080
protocol: TCP
- containerPort: 443
hostPort: 8443
protocol: TCP
- role: worker
image: kindest/node:v1.35.0
The ingress-ready=true label on the control-plane node is mandatory: the kind-specific ingress-nginx manifest schedules the controller pod with a nodeSelector that requires this label, so without it the controller pod will sit Pending indefinitely.9
Create the cluster:
kind create cluster --name gw-migration --config kind-config.yaml
kubectl cluster-info --context kind-gw-migration
Expected output ends with:
Kubernetes control plane is running at https://127.0.0.1:<port>
CoreDNS is running at https://127.0.0.1:<port>/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
If kind create cluster hangs at "Creating control plane", make sure Docker has at least 4 CPUs and 6 GB of RAM in its resource settings — the default 2 GB is not enough for a two-node cluster plus the workloads we add later.
Step 2: Deploy the legacy ingress-nginx setup
This is the "before" state — what your existing cluster probably looks like. We use the deprecated controller intentionally so the migration step has something real to convert.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.7/deploy/static/provider/kind/deploy.yaml
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=180s
Now deploy a sample app — two versions of an HTTP "echo" so we can exercise canary splitting later:
# echo-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v1
labels: { app: echo, version: v1 }
spec:
replicas: 2
selector:
matchLabels: { app: echo, version: v1 }
template:
metadata:
labels: { app: echo, version: v1 }
spec:
containers:
- name: echo
image: ghcr.io/mendhak/http-https-echo:40
ports: [{ containerPort: 8080 }]
env:
- name: HTTP_PORT
value: "8080"
- name: ECHO_INCLUDE_ENV_VARS
value: "1"
- name: VERSION
value: "v1"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo-v2
labels: { app: echo, version: v2 }
spec:
replicas: 2
selector:
matchLabels: { app: echo, version: v2 }
template:
metadata:
labels: { app: echo, version: v2 }
spec:
containers:
- name: echo
image: ghcr.io/mendhak/http-https-echo:40
ports: [{ containerPort: 8080 }]
env:
- name: HTTP_PORT
value: "8080"
- name: ECHO_INCLUDE_ENV_VARS
value: "1"
- name: VERSION
value: "v2"
---
apiVersion: v1
kind: Service
metadata: { name: echo-v1 }
spec:
selector: { app: echo, version: v1 }
ports: [{ port: 80, targetPort: 8080 }]
---
apiVersion: v1
kind: Service
metadata: { name: echo-v2 }
spec:
selector: { app: echo, version: v2 }
ports: [{ port: 80, targetPort: 8080 }]
kubectl apply -f echo-app.yaml
And the "before" Ingress that the migration will convert. Note the ingress-nginx-specific annotations — these are exactly the kind of cruft that motivates the move to Gateway API:
# legacy-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS"
spec:
ingressClassName: nginx
rules:
- host: echo.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo-v1
port:
number: 80
kubectl apply -f legacy-ingress.yaml
Verify it works:
curl -H "Host: echo.local" http://localhost:8080/ | head -20
You should see a JSON dump that includes "VERSION": "v1". If you instead see default backend - 404, give the ingress controller another 30 seconds — extraPortMappings only routes the request once the LoadBalancer service has assigned the port to the controller pod.
Step 3: Install Gateway API v1.5.1 CRDs
The Gateway API ships its own CRDs separately from any controller. Install the Standard channel (stable, GA APIs):110
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.1/standard-install.yaml
Confirm:
kubectl get crd | grep gateway.networking.k8s.io
Expected output (in any order):
backendtlspolicies.gateway.networking.k8s.io 2026-05-10T12:00:00Z
gatewayclasses.gateway.networking.k8s.io 2026-05-10T12:00:00Z
gateways.gateway.networking.k8s.io 2026-05-10T12:00:00Z
grpcroutes.gateway.networking.k8s.io 2026-05-10T12:00:00Z
httproutes.gateway.networking.k8s.io 2026-05-10T12:00:00Z
referencegrants.gateway.networking.k8s.io 2026-05-10T12:00:00Z
tlsroutes.gateway.networking.k8s.io 2026-05-10T12:00:00Z
TLSRoute is the new arrival in v1.5 — it was promoted from Experimental to Standard alongside ListenerSet, the HTTPRoute CORS filter, Client Certificate Validation, and Certificate Selection for Gateway TLS Origination, with ReferenceGrant also moving to v1 in this release.11 BackendTLSPolicy graduated earlier (v1.4). If you only see six CRDs, you installed an older 1.4 manifest.
If you also need the experimental APIs (e.g., XBackendTrafficPolicy), kubectl apply will reject the manifest because the experimental CRDs exceed the standard request size — use kubectl apply --server-side=true instead.12 We do not need experimental APIs for this tutorial.
Step 4: Install Envoy Gateway v1.7.2 as the controller
Gateway API is a CRD specification; behavior depends on the controller. Envoy Gateway is one of several conformant choices (NGINX Gateway Fabric, Cilium, Istio, Kong, Traefik). It is vendor-neutral, ships an OCI Helm chart, and has a small moving-parts footprint for a tutorial.313
Install the control plane with --skip-crds because we already installed the v1.5.1 Standard channel CRDs in Step 3. The default Envoy Gateway Helm chart still bundles a copy of the Gateway API Experimental channel CRDs (a transition that is in progress upstream), so omitting --skip-crds would overwrite the Standard CRDs you just applied:14
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v1.7.2 \
-n envoy-gateway-system \
--create-namespace \
--skip-crds
kubectl wait --timeout=5m \
-n envoy-gateway-system \
deployment/envoy-gateway \
--for=condition=Available
The Helm chart does not create a GatewayClass for you — that is left to the user so the same controller can be reused under different class names. Apply one explicitly:
# gatewayclass.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
kubectl apply -f gatewayclass.yaml
kubectl get gatewayclass
Expected:
NAME CONTROLLER ACCEPTED AGE
eg gateway.envoyproxy.io/gatewayclass-controller True 10s
Note: you now have two ingress paths in the cluster:
- The legacy
ingress-nginxcontroller bound toIngressClass: nginx, frontingecho-v1via the existingIngress. - The new
GatewayClass: egwaiting for aGatewayandHTTPRouteto reference it.
Each gets its own external endpoint. This is the safety pattern that the official migration guide explicitly recommends — run both, validate the new path with isolated traffic, then cut over.15
Step 5: Convert the Ingress with ingress2gateway 1.0
Install the converter. Either method works:
# Option A — Go install (requires Go 1.22+)
go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0
# Option B — Homebrew (macOS / Linuxbrew)
brew install ingress2gateway
ingress2gateway --version
Convert the live Ingress into Gateway API resources. The tool reads from your kubeconfig context and translates ingress-nginx annotations using its 30+ supported mappings (CORS, rewrite-target, regex matching, backend TLS, and more):2
ingress2gateway print \
--providers=ingress-nginx \
--namespace=default \
> gwapi.yaml
Open gwapi.yaml and you will see something like this (cleaned up for readability):
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: echo-ingress
namespace: default
spec:
gatewayClassName: nginx # <-- you must change this
listeners:
- name: http
port: 80
protocol: HTTP
hostname: echo.local
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: echo-ingress
namespace: default
spec:
parentRefs:
- name: echo-ingress
hostnames:
- echo.local
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplaceFullPath
replaceFullPath: /
- type: CORS
cors:
allowMethods: ["GET", "POST", "OPTIONS"]
backendRefs:
- name: echo-v1
port: 80
weight: 100
Two things to know about the output:
gatewayClassName: nginxis wrong — the converter copiesingressClassNameverbatim. You must change it toeg(or whichever GatewayClass your controller installed) before applying. This is one of the easiest mistakes to make during real migrations because the conversion looks complete.2- The
URLRewritefilter andCORSfilter come directly from the original ingress-nginx annotations. The CORS filter graduated to Standard in Gateway API v1.5, so this is now stable across conformant controllers.11
Edit the file and apply:
sed -i.bak 's/gatewayClassName: nginx/gatewayClassName: eg/' gwapi.yaml
kubectl apply -f gwapi.yaml
Wait for the Gateway to become Programmed=True — this is the gate that tells you the controller has actually wired Envoy to listen on the requested port. Do not delete the legacy Ingress until this condition is True:15
kubectl wait --timeout=2m \
gateway/echo-ingress \
--for=condition=Programmed
Expected:
gateway.gateway.networking.k8s.io/echo-ingress condition met
Step 6: Test the new Gateway path in parallel with the old Ingress
The Envoy Gateway service is a LoadBalancer in envoy-gateway-system. Find its assigned port on the host (kind sets up NodePort ranges, and the controller's service is reachable inside the cluster):
kubectl get svc -n envoy-gateway-system
The service named envoy-default-echo-ingress-... is the data plane. We will hit it directly with kubectl port-forward so we don't need a kind LoadBalancer integration:
GW_SVC=$(kubectl get svc -n envoy-gateway-system \
-l gateway.envoyproxy.io/owning-gateway-name=echo-ingress \
-o jsonpath='{.items[0].metadata.name}')
kubectl port-forward -n envoy-gateway-system "svc/$GW_SVC" 9080:80 &
Test the new Gateway path:
curl -H "Host: echo.local" http://localhost:9080/ | grep VERSION
Expected:
"VERSION": "v1",
Now hit the old Ingress simultaneously — different port, same host header:
curl -H "Host: echo.local" http://localhost:8080/ | grep VERSION
Both return "VERSION": "v1". You now have two independent ingress paths into the same backend, with separate external endpoints. This is the moment to point a small percentage of real traffic (DNS round-robin, an external load balancer, or an internal canary header) at the new path and watch metrics for an hour or a day before continuing.15
Step 7: Add a weighted canary split with HTTPRoute
Here is where Gateway API earns its keep. With ingress-nginx you would need either a separate Ingress per version plus the nginx.ingress.kubernetes.io/canary-weight annotation, or a service mesh. With Gateway API, the HTTPRoute backendRefs field accepts weights natively as a first-class API.16
Edit gwapi.yaml and replace the single backendRef with a weighted split:
# gwapi.yaml — HTTPRoute section only
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: echo-ingress
namespace: default
spec:
parentRefs:
- name: echo-ingress
hostnames:
- echo.local
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: CORS
cors:
allowMethods: ["GET", "POST", "OPTIONS"]
backendRefs:
- name: echo-v1
port: 80
weight: 90
- name: echo-v2
port: 80
weight: 10
Apply and verify the split:
kubectl apply -f gwapi.yaml
for i in $(seq 1 100); do
curl -s -H "Host: echo.local" http://localhost:9080/ \
| grep -oE '"VERSION": *"v[12]"'
done | sort | uniq -c
Expected (approximate — small samples have noise):
90 "VERSION": "v1"
10 "VERSION": "v2"
The split is enforced by Envoy on every request. There is no annotation, no second Ingress, no service mesh sidecar — just a single HTTPRoute whose backendRefs weights add up to whatever you want them to. Bumping v2 to 50/50, then 10/90, then a final cut to 100/0 is just three kubectl apply operations against the same file.
For automated promotion, Flagger integrates natively with Gateway API HTTPRoute resources and works with any conformant controller.17 That is out of scope for this migration walkthrough but is the correct next step once the manual cutover succeeds.
Step 8: Verify and roll back
A canary that regresses needs a single command to undo. Because the migration kept the original Ingress in place, your rollback is a two-step retreat:
# Step 1 — flip the HTTPRoute back to v1 only
kubectl patch httproute echo-ingress \
--type='merge' \
-p '{"spec":{"rules":[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}],"backendRefs":[{"name":"echo-v1","port":80,"weight":100}]}]}}'
# Step 2 — if the Gateway itself is misbehaving, point external traffic
# back at the legacy ingress endpoint (port 8080 in this kind setup,
# or the ingress-nginx LoadBalancer in production)
The "old Ingress is still there" is the entire reason for the parallel-deployment pattern. Do not delete the legacy Ingress until you have a full traffic shift, the Gateway is Programmed=True, and you have monitored production metrics for at least one full traffic cycle (typically 24 hours). The official migration guide explicitly calls this out: delete Ingress resources iteratively, one at a time, verifying after each.15
Step 9: Decommission ingress-nginx
Once the new Gateway has carried 100% of production traffic for a representative window, clean up:
# 1. Delete the legacy Ingress
kubectl delete ingress echo-ingress
# 2. Confirm no other Ingress objects remain in the cluster
kubectl get ingress -A
# 3. Once that returns "No resources found", uninstall ingress-nginx
kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.7/deploy/static/provider/kind/deploy.yaml
If kubectl get ingress -A still shows objects in other namespaces, stop. Repeat the migration for each one before removing the controller — ingress-nginx failing while a single legacy Ingress points at it will black-hole that traffic.
Migration checklist
Use this checklist every time you migrate Ingress to Gateway API in production, not just on kind:
| Step | Command / action | Done? |
|---|---|---|
| 1 | Inventory all Ingress resources: kubectl get ingress -A -o yaml > all-ingresses.yaml | |
| 2 | Audit ingress-nginx annotations: grep nginx.ingress.kubernetes.io all-ingresses.yaml | sort -u | |
| 3 | Confirm every annotation is on the ingress2gateway 1.0 supported list, or has a manual translation plan2 | |
| 4 | Install Gateway API v1.5.1 Standard channel CRDs1 | |
| 5 | Install a conformant controller (Envoy Gateway, NGINX Gateway Fabric, Cilium, Istio, etc.) alongside ingress-nginx | |
| 6 | Run ingress2gateway print --all-namespaces --providers=ingress-nginx > gwapi.yaml2 | |
| 7 | Manually fix gatewayClassName (always wrong by default) | |
| 8 | Apply, then kubectl wait --for=condition=Programmed gateway/<name>15 | |
| 9 | Send canary traffic via DNS, an external LB, or a header rule | |
| 10 | Monitor for at least one full traffic cycle | |
| 11 | Cut over the remaining traffic with HTTPRoute weight changes | |
| 12 | Delete each Ingress one at a time; verify availability between deletions15 | |
| 13 | Uninstall ingress-nginx only after kubectl get ingress -A returns nothing |
Troubleshooting: real errors from the GitHub issue tracker
Error: Forbidden: estimated rule cost exceeds budget when applying CRDs.
This is the symptom of trying to install the experimental channel manifest with a regular kubectl apply. The experimental CRDs ship more validation rules than the default request budget allows. Either install the standard channel (this tutorial's path) or use kubectl apply --server-side=true.12
Error: HTTPRoute is Accepted=True but ResolvedRefs=False.
The Service referenced in backendRefs does not exist or is in a different namespace without a ReferenceGrant. Run kubectl describe httproute <name> and read the ResolvedRefs condition message. The two common causes are typos in the Service name and cross-namespace refs that need an explicit ReferenceGrant (the resource that authorizes cross-namespace references — graduated to v1 / GA in Gateway API v1.5).11
Error: Gateway is Accepted=True but never reaches Programmed=True.
The controller can't allocate the requested listener — usually a port conflict on the data-plane LoadBalancer service or a missing TLS secret for an HTTPS listener. Check kubectl get svc -n envoy-gateway-system for stuck <pending> external IPs, and kubectl logs -n envoy-gateway-system deployment/envoy-gateway for the controller's view.
Error: gatewayClassName: nginx not found after ingress2gateway conversion.
You forgot Step 5's sed. The converter copies the source ingressClassName literally because it cannot know which Gateway controller you actually run. Open gwapi.yaml, change to the GatewayClass name from kubectl get gatewayclass, re-apply.
Warning: weight field rounds requests unevenly at low sample sizes.
This is expected — weights are probabilistic per-request, not a strict round-robin. With weights 90/10, ten requests will not deterministically produce nine v1 + one v2; you might see ten v1 in a row. Sample size matters; over 1,000 requests the ratio converges. If you need deterministic routing, use header-matched rules instead of weights.16
Next steps
Now that the migration runs end-to-end on kind, the production checklist is:
- Wire Flagger or Argo Rollouts to automate canary promotion against the same
HTTPRoute.17 - Add observability to the data plane: Envoy Gateway exposes Prometheus metrics out of the box; the v1.5 stable resources (
BackendTLSPolicy,Client Certificate Validation) extend the same model to mTLS between Gateway and pods.11 - Read the deeper API gateway design context in our API gateway patterns guide before promoting beyond a single cluster.
- For teams still onboarding to Kubernetes itself, our Kubernetes hands-on guide covers the cluster-level concepts that Gateway API builds on.
- If you came from a Docker-first workflow, the Docker vs Kubernetes overview explains where this controller layer sits in the stack.
Teams who migrate Ingress to Gateway API now will be ahead of the curve when the last ingress-nginx security fix expires; teams who wait will be patching a dead controller. Gateway API is no longer the future of Kubernetes networking — as of 2026 it is the present. ingress-nginx is retired, the conformance ecosystem is mature, and ingress2gateway 1.0 makes the conversion mechanical for the common case. The remaining work is the careful operational dance: parallel deployment, gradual cutover, and one Ingress deletion at a time.
Footnotes
-
Kubernetes SIG Network, "Gateway API v1.5: Moving features to Stable", April 21, 2026 (post edited to correct the v1.5.0 release date to February 27, 2026). https://kubernetes.io/blog/2026/04/21/gateway-api-v1-5/ ↩ ↩2 ↩3 ↩4
-
Kubernetes SIG Network, "Announcing Ingress2Gateway 1.0: Your Path to Gateway API", March 20, 2026. https://kubernetes.io/blog/2026/03/20/ingress2gateway-1-0-release/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Envoy Gateway releases (v1.7.2 published April 17, 2026). https://github.com/envoyproxy/gateway/releases ↩ ↩2 ↩3
-
Kubernetes SIG Network, "Ingress NGINX Retirement: What You Need to Know", November 11, 2025. https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/ ↩
-
kind v0.31.0 release page (default node image
kindest/node:v1.35.0). https://github.com/kubernetes-sigs/kind/releases/tag/v0.31.0 ↩ -
kind Quick Start. https://kind.sigs.k8s.io/docs/user/quick-start/ ↩
-
Helm releases (v3.20.2, April 8, 2026). https://github.com/helm/helm/releases ↩
-
Gateway API v1.5.1 release tag. https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.5.1 ↩
-
kind ingress installation guide —
ingress-ready=truelabel is required by the kind-specific ingress-nginx manifest. https://kind.sigs.k8s.io/docs/user/ingress/ ↩ -
Gateway API getting started — installation. https://gateway-api.sigs.k8s.io/guides/getting-started/ ↩
-
Gateway API v1.5 stable promotions: ListenerSet, TLSRoute, HTTPRoute CORS Filter, Client Certificate Validation, Certificate Selection for Gateway TLS Origination, and ReferenceGrant moving to v1. https://kubernetes.io/blog/2026/04/21/gateway-api-v1-5/ ↩ ↩2 ↩3 ↩4
-
Gateway API issue #3256 — "estimated rule cost exceeds budget" with non-server-side apply. https://github.com/kubernetes-sigs/gateway-api/issues/3256 ↩ ↩2
-
Gateway API implementations list. https://gateway-api.sigs.k8s.io/implementations/ ↩
-
Envoy Gateway issue #7238 — "Move away from defaulting from the Gateway API Experimental Channel to the Standard Channel for CRDs". https://github.com/envoyproxy/gateway/issues/7238 ↩
-
Gateway API migration guide — "Migrating from Ingress-NGINX". https://gateway-api.sigs.k8s.io/guides/getting-started/migrating-from-ingress-nginx/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Gateway API HTTP traffic splitting guide — weighted backendRefs. https://gateway-api.sigs.k8s.io/guides/traffic-splitting/ ↩ ↩2
-
"How to Configure Flagger with Gateway API HTTPRoute", March 13, 2026. https://oneuptime.com/blog/post/2026-03-13-how-to-configure-flagger-with-gateway-api-httproute/view ↩ ↩2