The Gateway API
How GatewayClass, Gateway and HTTPRoute share the work of an Ingress, and how to write matches and traffic splits.
Key ideas in this lesson · tap one for a simple explanation
What you will be able to do
- Say which team owns GatewayClass, Gateway and HTTPRoute, and how a route attaches to a listener.
- Write an HTTPRoute with hostnames, path matches and weighted backends, and check it with kubectl.
- Turn an Ingress into a Gateway plus an HTTPRoute, including TLS.
The is the newer way to let web traffic into a cluster. It does the job of an , with more features, and splits the work over three objects. The exam topic is Use the Gateway API to manage Ingress traffic. A typical task: create a Gateway and an HTTPRoute, split traffic between two versions, or turn an Ingress into Gateway API objects.
It is all , because there is no kubectl create gateway. So you need a clear picture of the three objects, and a fast way to look up their fields.
Why it exists
An Ingress puts everything in one object: the entry point, TLS and every route. Anything beyond host and path, such as redirects or traffic splits, went into annotations. Each controller had its own annotations, so they did not work across controllers. The Gateway API (gateway.networking.k8s.io/v1) splits the object by team, and puts those features into the spec itself.
Three objects, three owners
GatewayClass
which controller runs the Gateways
nw-edge
Gateway
listeners: ports and hostnames
edge
HTTPRoute
rules: host and path to a Service
store
Service
your app's Pods
store-v1
Each object names the one before it: the Gateway names its class, and the route names its Gateway in parentRefs.
Like an Ingress, none of this moves any traffic by itself:
- A controller does the work. It reads the objects and runs the actual proxy.
- This lab installs the Gateway API but no controller. Your objects are checked and saved, but their status stays at Waiting for controller, and no traffic flows.
- On the exam, a controller is installed, and the grader can send real requests.
These commands show what is installed, and which fields each kind has:
kubectl get crd | grep gateway.networking.k8s.io
kubectl api-resources --api-group=gateway.networking.k8s.io
kubectl get gatewayclass # which controllers exist (exam: usually one)
kubectl get gateway,httproute -A
# The CRDs carry full schemas, so kubectl explain works offline and is faster than the docs
kubectl explain gateway.spec.listeners
kubectl explain httproute.spec.rules.backendRefs
kubectl explain httproute.spec.rules.filters --recursive | lessGatewayClass and Gateway
The Gateway is the entry point. Each listener on it is one port and protocol, and optionally one hostname. This one has two listeners: HTTP on port 80, and HTTPS on port 443 for one host.
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nw-edge
spec:
controllerName: example.com/gateway-controller # must match the installed controller; immutable
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: edge
namespace: nw-gw
spec:
gatewayClassName: nw-edge
listeners:
- name: http # routes can target one listener with parentRefs[].sectionName
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Same # the default; All, or Selector with a label selector
- name: https
protocol: HTTPS
port: 443
hostname: "store.nw.local" # optional; routes must share a hostname with the listener
tls:
mode: Terminate # the default for HTTPS
certificateRefs:
- kind: Secret
name: store-tls # kubernetes.io/tls Secret in the Gateway's namespaceallowedRoutes says which routes may attach to a listener. The default, from: Same, allows only routes in the Gateway's own namespace. To let routes from other namespaces attach, use from: All, or from: Selector with a namespace .
HTTPRoute
The HTTPRoute holds the routing rules. This one sends store.nw.local/store to two versions of an app: 80% to store-v1 and 20% to store-v2. That is a traffic split, often used to try a new version on a few users first.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: store
namespace: nw-gw
spec:
parentRefs:
- name: edge # the Gateway; add sectionName: http to pin one listener
hostnames:
- store.nw.local
rules:
- matches:
- path:
type: PathPrefix # Exact, PathPrefix, or RegularExpression (controller-dependent)
value: /store
backendRefs:
- name: store-v1 # a Service in the route's namespace
port: 80 # Service port; required for Services
weight: 80
- name: store-v2
port: 80
weight: 20 # weights are relative: 4 and 1 would split the same way- matches: a request needs to match only one entry of the list. Inside one entry, every field (
path,headers,method, …) must match. A rule with nomatchescatches every path. - backendRefs:
weightis 1 when you leave it out, and a weight of 0 sends nothing. A Service in another namespace also needs a ReferenceGrant there: an object that allows the reference. - Which rule wins: the most specific match. For example, an
Exactpath beats a prefix, and a longer prefix beats a shorter one.
Filters
A filter changes a request on its way through. The most common one is a redirect, for example from an old path to a new one:
rules:
- matches:
- path: { type: PathPrefix, value: /old-shop }
filters:
- type: RequestRedirect # answers the client itself; no backendRefs allowed in this rule
requestRedirect:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /store
statusCode: 301Other filters work the same way. URLRewrite changes the path on its way to the backend. RequestHeaderModifier and ResponseHeaderModifier edit headers. RequestMirror copies each request to a second backend. kubectl explain httproute.spec.rules.filters lists all their fields.
From Ingress to Gateway API
Every Ingress field has a place in the Gateway API. Use this table when a task asks you to move an Ingress over:
In the official docs· open on exam day too
- Gateway API (kubernetes.io concept page)search: gateway api
- HTTPRoute guidesearch: http routing
- Traffic splittingsearch: traffic splitting
- Migrating from Ingresssearch: migrating from ingress
A Gateway with a weighted HTTPRoute
nw-edge whose controller name is example.com/gateway-controller. In namespace nw-gw, create a Gateway named edge of that class with one listener named http for protocol HTTP on port 80 that accepts routes from its own namespace only. Then create an HTTPRoute named store attached to edge for hostname store.nw.local. Requests whose path starts with /store must be split so that 80% go to Service store-v1 and 20% to Service store-v2, both on port 80. (The Services exist; their Pods and a Gateway controller are not needed for this task.)Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-1/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-1/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-1/cleanup | bash
Migrate an Ingress to the Gateway API
legacy in namespace nw-gw2 must be replaced by Gateway API objects. Using the existing GatewayClass nw-lab, create a Gateway named legacy-gw in nw-gw2 with a listener named https on port 443 using protocol HTTPS for hostname legacy.nw.local, terminating TLS with the Secret the Ingress uses. Then create an HTTPRoute named legacy attached to that Gateway that reproduces the Ingress's host and path routing exactly. Leave the Ingress in place.Cluster:kubectl config use-context kind-cka
- 1
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-2/setup | bash - 2
Solve it in your terminal
Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under
/tmp/cka/. - 3
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-2/verify | bashGot FAIL? Read which check failed, fix it, run it again. - 4
Clean up (optional)
curl -fsSL https://codewithmuh.com/labs/cka/t/nw-gw-2/cleanup | bash
Finished this lesson?
0 of 2 tasks passed. Your readiness counts tasks, so run them before you move on.