CKA Certification Course - Certified Kubernetes Administrator
Networking
2025 Updates Introduction to Gateway API
In this lesson, we introduce the Gateway API, a modern, more flexible approach to managing network routing in Kubernetes. In previous discussions on Ingress, we saw a scenario where two services shared the same Ingress resource:
Imagine a scenario where independent teams or even separate organizations manage different services. For example, one team could be responsible for the web service while another oversees the video service. In such multi-tenant environments, a single Ingress resource — which can be controlled by only one team at a time — may lead to coordination challenges and potential conflicts. In addition, Ingress has limited support for multi-tenancy and parameterized rules.
Note
For basic routing, consider this simple Ingress configuration:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-wear-watch
spec:
rules:
- host: wear.my-online-store.com
http:
paths:
- backend:
serviceName: wear-service
servicePort: 80
- host: watch.my-online-store.com
http:
paths:
- backend:
serviceName: watch-service
servicePort: 80
Another limitation of Ingress is its narrow rule configuration. Ingress only supports HTTP-based requests by matching hosts or paths. It does not natively support protocols such as TCP or UDP, nor does it offer advanced features like traffic splitting, header manipulation, authentication, or rate limiting. These behaviors are usually implemented using controller-specific annotations. For example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-wear-watch
annotations:
wear.my-online-store.com:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
rules:
- host: wear.my-online-store.com
http:
paths:
- path: /foo
backend:
serviceName: wear-service
servicePort: 80
- host: watch.my-online-store.com
http:
paths:
- backend:
serviceName: watch-service
servicePort: 80
The use of annotations, however, creates challenges. Different Ingress implementations (such as NGINX and Traefik) require their own annotation syntax. For instance, configuring CORS might look like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cors-ingress
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://allowed-origin.com"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
# CORS Configuration
traefik.ingress.kubernetes.io/headers.customresponseheaders: |
Access-Control-Allow-Origin: '*'
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Headers: Content-Type,Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
Kubernetes passes these annotations to the controllers without validating them, meaning that similar configurations will only work with the controllers that recognize the given annotations.
This is where Gateway API steps in. Gateway API is an official Kubernetes project designed to improve both layer 4 and layer 7 routing. It represents the next evolution in Kubernetes Ingress, load balancing, and service mesh APIs.
Benefits of Gateway API
One of the key limitations with Ingress is multi-tenancy. Gateway API addresses this by splitting the responsibilities among three objects, each managed by a different persona:
- Infrastructure Providers: They define the GatewayClass, which specifies the underlying network infrastructure (e.g., NGINX, Traefik, or another load balancer).
- Cluster Operators: They create Gateway objects as instances of a GatewayClass.
- Application Developers: They configure HTTPRoutes (or other routes like TCPRoute or gRPCRoute) that attach to the Gateway.
Unlike Ingress, which only supports HTTP routing, Gateway API broadens support to include multiple protocols. Let’s look at how the components are defined.
Defining the GatewayClass
The GatewayClass object specifies the network infrastructure controller:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: example-class
spec:
controllerName: example.com/gateway-controller
Creating a Gateway
Next, define a Gateway that references the GatewayClass and sets up an HTTP listener on port 80:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-class
listeners:
- name: http
protocol: HTTP
port: 80
Configuring an HTTPRoute
Application developers then create an HTTPRoute to define routing rules. In the following example, requests for "www.example.com" with a path prefix of "/login" are directed to the "example-svc" backend on port 8080:
apiVersion: 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
This declarative configuration explicitly defines both matching rules and backend mapping, eliminating the reliance on ambiguous annotations. Additionally, it paves the way for supporting protocols beyond HTTP, such as TCP or gRPC.
Streamlined TLS Termination
Another advantage of Gateway API is its clear and structured approach to TLS configuration. With Ingress, configuring HTTPS typically involves both native TLS settings and controller-specific annotations:
# Ingress configuration for HTTPS using annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-app
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- hosts:
- secure.example.com
secretName: tls-secret
The equivalent configuration in Gateway API is both straightforward and self-contained:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: secure-gateway
spec:
gatewayClassName: example-gc
listeners:
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: tls-secret
allowedRoutes:
kinds:
- kind: HTTPRoute
Here, TLS termination is explicitly defined with certificate references and allowed routes for the listener, eliminating the need for external annotations.
Traffic Splitting for Canary Deployments
Ingress can handle traffic splitting through controller-specific annotations. For example, a canary deployment might be configured as follows:
# Canary deployment configuration with Ingress annotations for NGINX
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80
With Gateway API, traffic splitting is declared directly in the HTTPRoute, making it more transparent:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: split-traffic
spec:
parentRefs:
- name: app-gateway
rules:
- backendRefs:
- name: app-v1
port: 80
weight: 80
- name: app-v2
port: 80
weight: 20
This clear definition of traffic distribution simplifies canary deployments without relying on hidden annotations.
Advanced Configurations: CORS
Managing advanced configurations such as CORS with Ingress often requires multiple annotations. For example, for NGINX:
# CORS configuration for NGINX using annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cors-ingress
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://allowed-origin.com"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
Or for Traefik:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
# CORS Configuration
traefik.ingress.kubernetes.io/headers.customresponseheaders: |
Access-Control-Allow-Origin: '*'
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type,Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
With Gateway API, CORS is configured in a centralized, declarative manner using filters:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: cors-route
spec:
parentRefs:
- name: my-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: Access-Control-Allow-Origin
value: "*"
- name: Access-Control-Allow-Methods
value: "GET, POST, PUT, DELETE, OPTIONS"
- name: Access-Control-Allow-Headers
value: "Content-Type,Authorization"
- name: Access-Control-Allow-Credentials
value: "true"
- name: Access-Control-Max-Age
value: "3600"
backendRefs:
- name: api-service
This configuration works consistently across Gateway API implementations regardless of the underlying controller, ensuring that advanced settings like CORS remain centralized and transparent.
Controller Support and Final Remarks
Today, many controllers have already implemented (or are in the process of implementing) Gateway API. Notable examples include Amazon EKS, Azure Application Gateway for Containers, Contour, Envoy, Google Kubernetes Engine, HAProxy, Istio, Kong, Kuma, NGINX, and others.
That concludes this lesson on the Gateway API. You can now practice working with Gateway API controllers in the accompanying labs. Enjoy the enhanced flexibility and clarity that Gateway API brings to your Kubernetes networking configurations!
Watch Video
Watch video content
Practice Lab
Practice lab