Review the Kubernetes Gateway API docs which explain the Gateway API and how it replaces Ingress for routing traffic into a Kubernetes cluster.
Some tool to view, edit, and interact with your K8s objects. Can be...
- OpenLens
- K9s recommended
- Kubectl only
We'll use a mix of these
We're going to use minikube as our local Kubernetes cluster. We're going to do things by hand ✋
Follow the official minikube installation guide for your OS. You'll also need kubectl installed.
minikube startThe Gateway API is not bundled with Kubernetes — you install the CRDs separately. Install the standard channel (which includes Gateway and HTTPRoute):
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/latest/download/standard-install.yamlVerify the CRDs are installed:
kubectl get crd gateways.gateway.networking.k8s.io httproutes.gateway.networking.k8s.ioNGINX Gateway Fabric is the Gateway API implementation we use (it replaces what ingress-nginx used to do). Install it with:
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-gateway-fabric/main/deploy/default/deploy.yamlWait for it to be ready:
kubectl wait --namespace nginx-gateway \
--for=condition=ready pod \
--selector=app.kubernetes.io/name=nginx-gateway \
--timeout=90sVerify a GatewayClass named nginx was created:
kubectl get gatewayclassgit clone <repo-url>
cd applebanana2021- look at the
apple.yamlfile. It's set up to deploy two things, a k8sdeploymentand a k8sservice - apply the
apple.yamlfile using kubectlkubectl apply -f apple.yaml - inspect what was created
kubectl get podskubectl get deploymentskubectl get services
- hit the apple-service by creating a forwarded port
kubectl port-forward service/apple-service 5678:5678this will "take over" your terminal until you ctrl+c to stop it.- open your browser and navigate to
http://localhost:5678orcurl http://localhost:5678
Questions:
- What are the Pod labels for the
applepod? - How many containers are in the
applepod? - What happens if you delete the
applepod? - What content is returned by the
applepod? - What does the
selectorin theservicesection ofapple.yamlsay? - Challenge: change the
appleservice to listen on port 8080 and check it by creating a port forward using kubectl.
Please bookmark kubernetes.io as you will use it frequently. You may also wish to add the CNCF Slack #gateway-api and #kubernetes channels.
kubernetes.io explains the Gateway API
The Gateway API works at TCP/IP layer 7. It is a set of CRDs (Custom Resource Definitions) that define how traffic enters a Kubernetes cluster. The key resources are:
- GatewayClass — defines the type of gateway (provisioned by your infrastructure, e.g. nginx)
- Gateway — represents a deployed gateway instance with one or more listeners (HTTP, HTTPS, etc.)
- HTTPRoute — defines routing rules that map hostnames and paths to backend services
The Gateway API is more expressive and role-oriented than the older Ingress resource, supporting TLS termination, path-based routing, and more — all without controller-specific annotations.
What ingress-nginx was
ingress-nginx was (and still is) a widely-used Ingress controller. It watched for networking.k8s.io/v1 Ingress resources and configured an nginx reverse proxy to route external traffic to services inside the cluster. It worked well for simple cases, but any behavior beyond basic path routing — timeouts, retries, traffic splitting, header manipulation — had to be expressed through nginx-specific annotations like nginx.ingress.kubernetes.io/proxy-read-timeout. That tied your config tightly to one controller. Swap to a different Ingress controller and your annotations silently stop working.
The problem with the Ingress resource
The Ingress resource was intentionally kept minimal by Kubernetes. There was never a standard way to express advanced routing in the spec itself, so every controller invented its own annotation vocabulary. The result: non-portable YAML, inconsistent behavior across environments, and a growing gap between what teams actually needed and what the API provided.
Why Gateway API
| ingress-nginx | Gateway API | |
|---|---|---|
| API group | networking.k8s.io/v1 (core, minimal) |
gateway.networking.k8s.io/v1 (CRD, expressive) |
| Advanced routing | Controller-specific annotations | Native spec fields |
| Portability | Tied to nginx controller | Works with nginx, Istio, Envoy, Cilium, and more |
| Role separation | Single resource owned by app teams | GatewayClass/Gateway for infra, HTTPRoute for apps |
| Status | Effectively frozen | Actively developed, GA in Kubernetes 1.28 |
The Kubernetes community has signaled that Gateway API is the long-term successor to Ingress. Migrating now means writing YAML that is portable across gateway implementations, supported by all major service mesh and CNI projects, and backed by a stable, versioned API.
NOTE: Google Chrome won't allow self-signed certificates. As of writing, Firefox and Safari will both work by adding exceptions. Use Firefox or Safari to load these pages in a web browser.
- create a self-signed TLS cert for laptop.int
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=laptop.int/O=gatewaysvc"
- create an
/etc/hostsentry for laptop.int — get your minikube IP first:minikube ip— copy the output (e.g.192.168.49.2)- add a line to
/etc/hosts:<minikube-ip> laptop.int
- On Mac/Linux:
echo "$(minikube ip) laptop.int" | sudo tee -a /etc/hosts
- add the certificate to the secrets manager in kubernetes
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
- apply
gateway.yamlwhich creates both the Gateway (with TLS termination) and the HTTPRoute- look at the file:
cat gateway.yaml kubectl apply -f gateway.yaml
- look at the file:
- verify what was created
kubectl get gatewaykubectl get httproute
- test with cURL
curl -kL https://laptop.int/appleor open in Safari/Firefox.
kubectl delete -f gateway.yamlkubectl delete -f apple.yamlkubectl delete -f banana.yamlkubectl delete secret tls-secretminikube stop && minikube delete