All technological notes.
Gateway API & GatewayClassGateway API \& GatewayClass
Gateway API
logical load balancerGatewayClass:
Gateway.gateways with common configuration.GatewayClass:
controller that implements the class.Gateway:
HTTPRoute:
Gateway listener to a representation of backend network endpoints.Service.GRPCRoute:
Gateway listener to a representation of backend network endpoints.Service.
| Feature | Service | Ingress | Gateway API |
|---|---|---|---|
| Primary Goal | Basic connectivity & load balancing between pods. | Routing external HTTP(S) traffic into the cluster. | Advanced, role-oriented traffic management (L4 & L7). |
| OSI Layer | Layer 4 (TCP/UDP). | Layer 7 (HTTP/HTTPS only). | Layers 4 and 7 (HTTP, TCP, gRPC, etc.). |
| Config Style | Single resource (Service). | Single resource + custom Annotations. | Modular (GatewayClass, Gateway, Routes). |
| Persona | App Developer. | App Developer (often oversteps). | Infra Admin + Cluster Op + App Developer. |
| Traffic Splitting | No (all pods get equal share). | Limited (requires vendor annotations). | Built-in (e.g., 90% to v1, 10% to v2). |
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
namespace: example-namespace
spec:
gatewayClassName: example-class
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "www.example.com"
allowedRoutes:
namespaces:
from: Same
listeners.allowedRoutes.namespaces.from:
All: Routes in all namespaces may be used by this Gateway.Selector: Routes in namespaces selected by the selector may be used by this Gateway.
from:selectorSame: Only Routes in the same namespace may be used by this Gateway.| Command | Description |
|---|---|
kubectl get gtw |
Shows the Address and Programmed status. |
kubectl get gtw -A |
Lists all gateways across all namespaces. |
kubectl describe gtw NAME |
Critical for debugging. Shows why a gateway is stuck in “Pending.” |
kubectl edit gtw NAME |
Imperatively change ports (e.g., changing 8080 to 9090) on the fly. |
kubectl wait --for=condition=programmed gtw/NAME |
Useful in scripts to wait until the proxy is ready before sending traffic. |
Gateway Class
controller that implements the class.A Gateway must reference a GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: demo-class
spec:
# specify the controller name
controllerName: example.com/gateway-controller
| Command | Description |
|---|---|
kubectl get gc |
Lists all available classes and their controller names. |
kubectl describe gc NAME |
Checks the Status to see if the controller has “Accepted” the class. |
kubectl delete gc NAME |
Removes the class definition (will break Gateways relying on it). |
kubectl get gc -o yaml |
Quickest way to see the controllerName string needed for new classes. |
HTTPRoute
Gateway listener to backend network endpoints.HTTPRoute may result in configuring additional traffic routes in a cloud load balancer or in-cluster proxy server.Service backend, an implementation may represent the backend network endpoint as a Service IP or the backing EndpointSlices of the Service.
the request flow for a Gateway implemented as a reverse proxy is:
client starts to prepare an HTTP request for the URL http://www.example.comclient’s DNS resolver queries for the destination name and learns a mapping to one or more IP addresses associated with the Gateway.client sends a request to the Gateway IP address; the reverse proxy receives the HTTP request and uses the Host: header to match a configuration that was derived from the Gateway and attached HTTPRoute.reverse proxy can perform request header and/or path matching based on match rules of the HTTPRoute.reverse proxy can modify the request; for example, to add or remove headers, based on filter rules of the HTTPRoute.reverse proxy forwards the request to one or more backendsapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-httproute
spec:
parentRefs:
- name: example-gateway
hostnames:
- "www.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /login
backendRefs:
- name: example-svc
port: 8080
| Command | Description |
|---|---|
kubectl get httproute |
|
kubectl describe httproute |
GRPCRoute
Gateway listener to backend network endpoints.GRPCRoute may result in configuring additional traffic routes in a cloud load balancer or in-cluster proxy server.Service backend, an implementation may represent the backend network endpoint as a Service IP or the backing EndpointSlices of the Service.Gateway example-gateway with the host set to svc.example.com directed to the service example-svc on port 50051apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: example-grpcroute
spec:
parentRefs:
- name: example-gateway
hostnames:
- "svc.example.com"
rules:
- backendRefs:
- name: example-svc
port: 50051
com.example.User.Login method to svc.example.com will be forwarded.apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: example-grpcroute
spec:
parentRefs:
- name: example-gateway
hostnames:
- "svc.example.com"
rules:
- matches:
- method:
service: com.example
method: Login
backendRefs:
- name: foo-svc
port: 50051
envoy# Install the Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
# customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
# Install Envoy Gateway (the controller)
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml
# customresourcedefinition.apiextensions.k8s.io/backendtlspolicies.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io configured
# customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io configured
# customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io configured
# customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io configured
# customresourcedefinition.apiextensions.k8s.io/tcproutes.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/tlsroutes.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/udproutes.gateway.networking.k8s.io created
# customresourcedefinition.apiextensions.k8s.io/backendtrafficpolicies.gateway.envoyproxy.io created
# customresourcedefinition.apiextensions.k8s.io/clienttrafficpolicies.gateway.envoyproxy.io created
# customresourcedefinition.apiextensions.k8s.io/envoypatchpolicies.gateway.envoyproxy.io created
# customresourcedefinition.apiextensions.k8s.io/envoyproxies.gateway.envoyproxy.io created
# customresourcedefinition.apiextensions.k8s.io/securitypolicies.gateway.envoyproxy.io created
# namespace/envoy-gateway-system created
# serviceaccount/envoy-gateway created
# configmap/envoy-gateway-config created
# clusterrole.rbac.authorization.k8s.io/eg-gateway-helm-envoy-gateway-role created
# clusterrolebinding.rbac.authorization.k8s.io/eg-gateway-helm-envoy-gateway-rolebinding created
# role.rbac.authorization.k8s.io/eg-gateway-helm-infra-manager created
# role.rbac.authorization.k8s.io/eg-gateway-helm-leader-election-role created
# rolebinding.rbac.authorization.k8s.io/eg-gateway-helm-infra-manager created
# rolebinding.rbac.authorization.k8s.io/eg-gateway-helm-leader-election-rolebinding created
# service/envoy-gateway-metrics-service created
# service/envoy-gateway created
# deployment.apps/envoy-gateway created
# serviceaccount/eg-gateway-helm-certgen created
# role.rbac.authorization.k8s.io/eg-gateway-helm-certgen created
# rolebinding.rbac.authorization.k8s.io/eg-gateway-helm-certgen created
# job.batch/eg-gateway-helm-certgen created
# confirm
kubectl get pods -n envoy-gateway-system
# NAME READY STATUS RESTARTS AGE
# envoy-gateway-655f47c4c5-nxntr 1/1 Running 0 22m
# demo-gw-gc.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
kubectl apply -f demo-gw-gc.yaml
# gatewayclass.gateway.networking.k8s.io/envoy created
# confirm
kubectl get gc
# NAME CONTROLLER ACCEPTED AGE
# envoy gateway.envoyproxy.io/gatewayclass-controller True 14s
kubectl describe gc envoy
# Name: envoy
# Namespace:
# Labels: <none>
# Annotations: <none>
# API Version: gateway.networking.k8s.io/v1
# Kind: GatewayClass
# Metadata:
# Creation Timestamp: 2026-01-05T23:02:20Z
# Finalizers:
# gateway-exists-finalizer.gateway.networking.k8s.io
# Generation: 1
# Resource Version: 3157914
# UID: 2b42919b-9d4d-4825-97db-04f6aa78a357
# Spec:
# Controller Name: gateway.envoyproxy.io/gatewayclass-controller
# Status:
# Conditions:
# Last Transition Time: 2026-01-05T23:02:21Z
# Message: Valid GatewayClass
# Observed Generation: 1
# Reason: Accepted
# Status: True
# Type: Accepted
# Events: <none>
# demo-gwapi-deploy-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 8080
targetPort: 80
kubectl apply -f demo-gwapi-deploy-svc.yaml
# deployment.apps/nginx-app created
# service/nginx-service created
# confirm
kubectl get deploy
# NAME READY UP-TO-DATE AVAILABLE AGE
# nginx-app 2/2 2 2 2m34s
kubectl get svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# nginx-service ClusterIP 10.111.49.12 <none> 8080/TCP 13m
# demo-gwapi.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
namespace: default
spec:
gatewayClassName: envoy # specify controller
listeners:
- name: http
protocol: HTTP
port: 8080
allowedRoutes:
namespaces:
from: Same
kubectl apply -f demo-gwapi.yaml
# gateway.gateway.networking.k8s.io/nginx-gateway created
# confirm
kubectl get gtw
# NAME CLASS ADDRESS PROGRAMMED AGE
# nginx-gateway envoy Unknown 74s
kubectl describe gtw nginx-gateway
# Name: nginx-gateway
# Namespace: default
# Labels: <none>
# Annotations: <none>
# API Version: gateway.networking.k8s.io/v1
# Kind: Gateway
# Metadata:
# Creation Timestamp: 2026-01-05T22:42:25Z
# Generation: 2
# Resource Version: 3156987
# UID: 87a88038-6610-4eef-94a8-651b7c869890
# Spec:
# Gateway Class Name: envoy
# Listeners:
# Allowed Routes:
# Namespaces:
# From: Same
# Name: http
# Port: 8080
# Protocol: HTTP
# Status:
# Conditions:
# Last Transition Time: 1970-01-01T00:00:00Z
# Message: Waiting for controller
# Reason: Pending
# Status: Unknown
# Type: Accepted
# Last Transition Time: 1970-01-01T00:00:00Z
# Message: Waiting for controller
# Reason: Pending
# Status: Unknown
# Type: Programmed
# Events: <none>
# demo-gw-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route
namespace: default
spec:
parentRefs:
- name: nginx-gateway # specify gtw
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: nginx-service # specify svc
port: 8080
kubectl apply -f demo-gw-httproute.yaml
# httproute.gateway.networking.k8s.io/nginx-route created
kubectl get httproutes
# NAME HOSTNAMES AGE
# nginx-route 55s
kubectl describe httproutes
# Name: nginx-route
# Namespace: default
# Labels: <none>
# Annotations: <none>
# API Version: gateway.networking.k8s.io/v1
# Kind: HTTPRoute
# Metadata:
# Creation Timestamp: 2026-01-05T22:46:27Z
# Generation: 3
# Resource Version: 3157317
# UID: bde701f2-54f7-4017-922d-9a47ed217ffd
# Spec:
# Parent Refs:
# Group: gateway.networking.k8s.io
# Kind: Gateway
# Name: nginx-gateway
# Rules:
# Backend Refs:
# Group:
# Kind: Service
# Name: nginx-service
# Port: 8080
# Weight: 1
# Matches:
# Path:
# Type: PathPrefix
# Value: /
# Events: <none>
# wait for gw programmed = true
kubectl get gtw
# NAME CLASS ADDRESS PROGRAMMED AGE
# nginx-gateway envoy 127.0.0.1 True 20m
# confirm
curl http://localhost:8080
# <!DOCTYPE html>
# <html>
# <head>
# <title>Welcome to nginx!</title>
# <style>
# html { color-scheme: light dark; }
# body { width: 35em; margin: 0 auto;
# font-family: Tahoma, Verdana, Arial, sans-serif; }
# </style>
# </head>
# <body>
# <h1>Welcome to nginx!</h1>
# <p>If you see this page, the nginx web server is successfully installed and
# working. Further configuration is required.</p>
# <p>For online documentation and support please refer to
# <a href="http://nginx.org/">nginx.org</a>.<br/>
# Commercial support is available at
# <a href="http://nginx.com/">nginx.com</a>.</p>
# <p><em>Thank you for using nginx.</em></p>
# </body>
# </html>
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-web
spec:
gatewayClassName: example
listeners:
- protocol: HTTP
port: 80
name: prod-web-gw
allowedRoutes:
namespaces:
from: Same