From Service to Gateway API: Where the Problem Came From
- date
- category
- Networking
- also in
- Containers
- reading
- 1 min / 284 words
At first, the problem was simple:
I have a Service
I want to reach it from outside the cluster
Service type: LoadBalancer fits that model.
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 8080
That is a good API if you are thinking about a port and a backend.
HTTP quickly adds questions that Service does not try to answer:
which host?
which path?
where does TLS terminate?
what about redirects?
what about rewrites?
what about timeouts?
That is why Ingress appeared.
Ingress named only part of the problem
The simplest Ingress looks reasonable.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
The contract is clear:
example.com/
-> Service web:80
The problem starts with the next requirement.
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
Formally, we are still looking at Ingress.
In practice, we are looking at ingress-nginx configuration.
Annotations were a signal
Annotations were not random mess.
They were a way to add features that Ingress could not express.
Production needed:
redirects
rewrites
timeouts
body limits
header manipulation
canary traffic
custom authorization
The Ingress specification was smaller than the real problem.
Controllers filled that gap in their own ways.
That worked until you needed to change controllers or standardize a cluster.
Then the portable Kubernetes resource turned out to contain a non-portable part:
nginx.ingress.kubernetes.io/*
Gateway API splits the roles
Gateway API is not one new proxy.
It is a resource model that separates things previously packed into Ingress.
GatewayClass
|
v
Gateway
|
v
HTTPRoute
|
v
Service
GatewayClass says which controller and which kind of infrastructure will handle Gateways.
Gateway says where traffic enters: port, protocol, host, TLS, allowed routes.
HTTPRoute says how HTTP traffic reaches services.
That matters more than the YAML shape itself.
Ingress mixed a platform decision and an application route into one resource.
Gateway API tries to separate those decisions.
The platform can manage:
GatewayClass
Gateway
listeners
TLS defaults
allowed namespaces
The application can manage:
hostnames
paths
headers
backendRefs
traffic splitting
What really changes
This is not about:
Ingress is old
Gateway API is new
It is about Ingress having too little language.
Gateway API adds names for things that already existed in clusters:
who provides the load balancer
where TLS terminates
who may attach a route to a listener
which team controls application routing
which behavior is standard
which behavior depends on an implementation
It does not remove the need to understand the controller.
But it moves more of the contract out of annotations and into the API.