What you should know about the Kubernetes Gateway API

Anthony Critelli
ITNEXT
Published in
8 min readNov 1, 2023

--

Photo by Waldemar on Unsplash

The Kubernetes Gateway API just reached General Availability (GA), and it aims to evolve the process of exposing your cluster’s services to the outside world. This includes a more standard, robust set of API resources for managing exposed services. So, what should you know about this wonderful new API?

In this article, I’ll walk through the Gateway API resources and show how they are related, using Istio as an example. You’ll gain an understanding of how the pieces of Gateway API fit together to deliver traffic to a backend service.

Background

Allowing the outside world to communicate with services inside a Kubernetes cluster is one of the most basic tasks that an administrator must perform. Services provide this functionality in a limited sense at the IP layer, but they lack the ability to route traffic based on application-layer data, such as a DNS hostname or HTTP path. Kubernetes provides the Ingress API to enable application-layer routing.

However, the Ingress API has some limitations. The ingress2gateway announcement does a great job explaining these, and I believe two points really stand out:

  1. Ingress focuses on HTTP traffic, leaving users to find other solutions for UDP, TCP, or other protocols.
  2. Ingress resources mix infrastructure and application configuration, making it difficult to implement fine-grained role-based access control (RBAC).

The second point is the most obvious to users who are already familiar with Ingress. In the modern world of platform engineering, providing robust RBAC is a critical step for any cluster administrator. Being able to separate out permissions for infrastructure components (load balancers, configurations, etc.) from traffic routing rules (path matches, header matches, forwarding rules, etc.) allows for clearer permissions boundaries.

In this article, I’ll walk you through how the Gateway API divides these resources, and how they are ultimately tied together to route traffic.

Setting up a Test Environment

This article uses a test environment running Istio and a sample workload to inspect and understand the various Gateway API resources. If you would like to follow along, then you can mirror this environment.

I am using K3S, but any Kubernetes cluster should work. If you choose to use K3s, then install it without Traefik enabled:

$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --disable=traefik" sh -

First, deploy the Gateway API Custom Resource Definitions (CRDs) and install Istio using the official documentation:

# Install the CRDs
$ kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.8.0" | kubectl apply -f -; }
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 Istio
$ istioctl install --set profile=minimal -y
✔ Istio core installed
✔ Istiod installed
✔ Installation complete
Made this installation the default for injection and validation.

Next, create a simple workload, such as an Nginx Deployment and expose it via a Service:

# Deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:latest
name: nginx
# Service.yaml
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: ClusterIP
$ kubectl apply -f Deployment.yaml
deployment.apps/nginx created
$ kubectl apply -f Service.yaml
service/nginx created

This is all the infrastructure you need to start understanding the Gateway API.

Understanding Gateway API Resources

There are three resources that you must understand to work with the Gateway API:

  • GatewayClass
  • Gateway
  • Route resources, such as HTTPRoute or GRPCRoute. The GA release only includes HTTPRoute in the v1 channel.

Traditionally, these resources were mixed together at various levels in either the standard Ingress API or in CRDs provided by custom vendor load balancers and routing utilities. By breaking the resources down into individual components, the Gateway API enables separation of concerns and robust, fine-grained access control.

Let’s walk through each of these resources to understand how they are related.

Understanding the GatewayClass Resource

The GatewayClass resource serves the same purpose as an IngressClass in the existing Ingress API, and it is similar to a StorageClass in the Storage API. It defines a class of Gateways that can be created. Typically, this resource is provided by your infrastructure platform, such as EKS or GKE. It may also be provided by a third-party Ingress Controller, such as Istio or Nginx. Istio includes two GatewayClasses:

$ kubectl get gatewayclass
NAME CONTROLLER ACCEPTED AGE
istio-remote istio.io/unmanaged-gateway True 19h
istio istio.io/gateway-controller True 19h

The spec field provides information about the controller that implements the GatewayClass functionality. This defines a controller used by the entire cluster, and GatewayClasses are cluster-scoped resources that apply across namespaces.

$ kubectl get gatewayclass istio -o yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
creationTimestamp: "2023-10-30T02:15:11Z"
generation: 1
name: istio
resourceVersion: "636"
uid: dea0bb44-5f1b-4d23-8f7f-c34f70b4603c
spec:
controllerName: istio.io/gateway-controller
description: The default Istio GatewayClass
status:
conditions:
- lastTransitionTime: "2023-10-30T02:15:11Z"
message: Handled by Istio controller
observedGeneration: 1
reason: Accepted
status: "True"
type: Accepted

A GatewayClass may also specify parameters that must be passed to the controller. This enables upstream projects to further customize the configuration exposed to cluster administrators. Fundamentally, the GatewayClass allows a cluster administrator to focus on exposing their traffic to the outside world without worrying about implementation specifics, such as how a load balancer is created on the underlying infrastructure.

Provisioning a Gateway

A Gateway represents the instantiation of load balancer services in the infrastructure provider. This may represent an actual cloud load balancer that is provisioned to handle traffic. It may also represent a virtual configuration in an existing load balancer. The implementation is abstracted away from the Gateway by the GatewayClass. A cluster operator focuses on defining the necessary Gateway resources for their consumers instead of worrying about the implementation specifics that are handled by the GatewayClass.

A Gateway references a GatewayClass in its spec. The example below uses the istio class and defines a single listener that responds to HTTP requests for *.example.com on port 8080:

# Gateway.yaml
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: tutorial-gw
namespace: default
spec:
gatewayClassName: istio
listeners:
- name: default
hostname: "*.example.com"
port: 8080
protocol: HTTP
allowedRoutes:
namespaces:
from: All

In the case of Istio, creating a Gateway also provisions a corresponding Deployment and Service to handle traffic. The controller for the GatewayClass handles provisioning the necessary infrastructure or configuration needed for the Gateway:

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
tutorial-gw-istio-65bfccf7c-45c4w 1/1 Running 2 (6m31s ago) 18h

$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tutorial-gw-istio LoadBalancer 10.43.126.90 192.168.122.10 15021:31348/TCP,8080:31728/TCP 18h

Notice that no routing rules are defined in the Gateway. Gateways represent the provisioning of infrastructure. This separation is crucial to enabling robust RBAC. The access control model allows cluster administrators to configure available Gateways for their consumers to reference in their routing resources, without needing to expose access to the infrastructure configuration itself.

Creating Routes

The existing Ingress API only supports HTTP and HTTPS services, which is a limitation in environments that must accommodate arbitrary protocols. The new Gateway API aims to be more protocol agnostic, providing generic support for a variety of inbound traffic types. The HTTPRoute, TCPRoute, TLSRoute, GRPCRoute, and others specify the actual routing of traffic in the context of a particular Gateway. The GA release of the Gateway API only includes the HTTPRoute resource in the standard v1 channel, but you can expect expanded protocol support in future releases. The truly adventurous can also investigate the resources exposed in the experimental channel.

An HTTPRoute resource specifies a connection to the Gateway used to expose the service and a list of rules to route traffic to the appropriate backend. The example below attaches the HTTPRoute to the tutorial-gw Gateway and specifies a single rule to route all traffic to the nginx Service:

---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: tutorial-route
namespace: default
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: tutorial-gw
rules:
- backendRefs:
- group: ""
kind: Service
name: nginx
port: 80
weight: 1
matches:
- path:
type: PathPrefix
value: /
$ kubectl apply -f HTTPRoute.yaml
httproute.gateway.networking.k8s.io/tutorial-route created
$ kubectl get httproute
NAME HOSTNAMES AGE
tutorial-route 6s

This is a simple example that provides basic routing based on a PathPrefix. The HTTPRoute resource has many other parameters for more advanced use cases.

Putting It All Together

The Gateway API splits apart many resources that have traditionally been contained in a single resource definition. It can be confusing to follow the connections between all of these resources, so a visual representation is invaluable when reasoning about these relationships:

Relationships between Gateway API resources

To recap:

  • A GatewayClass defines the available types of Gateways that can be deployed. It is typically exposed by an infrastructure provider. In this example, Istio defines a GatewayClass
  • A Gateway is an instantiation of load balancing infrastructure. This may be an actual load balancer that is deployed in a cloud environment, or it may be some configuration executed against an existing load balancer. Either way, this is abstracted from the cluster administrator by simply referencing the desired GatewayClass.
  • An HTTPRoute (or any other supported Route resource) defines the actual rules for handling traffic. These routes are attached to a specific Gateway, and they ultimately make decisions about traffic forwarding.

With all of this configuration in place, you can finally make a test request to the service. Since the sample Gateway is configured to listen for HTTP requests to *.example.com on port 8080, your request must set the appropriate Host header and port:

$ curl -H "Host: www.example.com" 192.168.122.10:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

And just like that, you have successfully configured your first set of resources using the new Gateway API!

Wrapping Up

At first glance, this new API may seem daunting. Networking is one of the most complicated aspects of Kubernetes administration. Breaking an already complex concept like load balancing into many individual pieces can be confusing. However, this additional configuration complexity promises concrete benefits. By separating each concern, the Kubernetes RBAC model can be applied to each individual resource at a highly granular level. Additionally, the Gateway API will be a more extensible and protocol-agnostic load balancing API for infrastructure providers to build on.

While it isn’t replacing the existing Ingress API, the Gateway API is now in GA. Be sure to understand the benefits that it offers for your environment, and be prepared to implement the Gateway API when it makes sense for your workloads. Expect to see continued vendor support for this exciting new networking API, and stay tuned for more announcements on the official Kubernetes blog.

--

--