Gateway API with GKE

Biju Kunjummen
3 min readAug 15, 2023

So I have a service running in a Kubernetes cluster

and I desire to expose this service to the world. There are a host of ways to do this today:

The focus of this post is a new way to do this which is using Kubernetes Gateway API, which enhances the previous approaches with a more expressive spec and with a role-based separation of responsibilities:

sourced from https://gateway-api.sigs.k8s.io/

There are a few new resource types that Gateway API introduces, each resource type managed by different roles in an organization.

A demo best clarifies these, so here it goes.

Demo Application

The codebase of the demo application is here. It is a state of the art helloworld service which returns a json response when a “/greetings” path is accessed.

I deployed this application to a Google Kubernetes Engine(GKE) based Autopilot cluster, the specs are here

Now, assuming that the pods and the service has started up cleanly, let’s start with the Gateway:

Gateway Class and Gateway

Gateway class is provided by the Infrastructure provider, in this instance Google Cloud provides the following Gateway Classes:

gke-l7-global-external-managed — Global external Application Load Balancer

gke-l7-regional-external-managed — Regional external Application Load Balancer

gke-l7-rilb — Internal Application Load Balancer(s)

And so on..

In my case I wish to expose an external HTTP endpoint, so a Cluster operator provisioning a Gateway would use a spec which looks like this:

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-http
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: http
protocol: HTTP
port: 80

with the gatewayClassName pointing to the appropriate Gateway class name.

HttpRoute

So now that a Gateway is in place, it can route the calls to the service based on different rules:

  • host name
  • URL path
  • Http headers

In my case, I want a simple routing based on “/greetings” path prefix and such a HttpRoute spec looks something like this:

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: helloworld-go-external
spec:
parentRefs:
- kind: Gateway
name: external-http
rules:
- matches:
- path:
type: PathPrefix
value: /greetings
backendRefs:
- name: helloworld-go-service
port: 8080

A few things to note here, see how there is a reference to the gateway through “parentRefs” and the rule matches on a path prefix of “/greetings”, and if it matches routes the request to the service.

That’s all there is to it, once these pieces are in place GKE should create a loadbalancer ip, route calls to “http://IP/greetings” to my service.

One small wrinkle that I saw was that the Loadbalancer NEGS pointing to the GKE pods were not in a healthy state, this is because by default a healthcheck is sent to the root path “/” which I did not have for my application, to fix this I needed to define a HealthCheckPolicy resource which looks like this:

apiVersion: networking.gke.io/v1
kind: HealthCheckPolicy
metadata:
name: helloworld-go-healthcheck
spec:
default:
config:
type: HTTP
httpHealthCheck:
port: 8080
requestPath: /greetings/health
targetRef:
group: ""
kind: Service
name: helloworld-go-service

Conclusion

Gateway API with Gateway, HttpRoute resources is a much more expressive resource and keeps the duties separated by roles. As a cluster admin I can expose a loadbalancer to my cluster and as a developer all I have to do is to create the HttpRoutes to direct the traffic to my service.

--

--

Biju Kunjummen

Sharing knowledge about Java, Cloud and general software engineering practices