Exposing Applications with GKE Gateway Controller

Juzer Patanwala
Google Cloud - Community
7 min readAug 25, 2023

Google Kubernetes Engine (GKE) is Google Cloud’s managed Kubernetes service, simplifying container deployment and orchestration.In Kubernetes,we deploy applications using deployment manifests (we can also use statefulsets or daemonsets if required) and then expose these deployments using services.But this is not sufficient to expose applications publicly,as even after creating Kubernetes service,we need to further expose these services using either Ingress or Gateway to make them reachable from the internet or our own internal network based on our requirement.Kubernetes Ingress has been widely used till now for exposing our applications outside the cluster but there is a new development in Kubernetes called Gateway which is the next-gen Ingress and will be used considerably more in the future.For a more detailed comparison between Gateway and Ingress you can follow this link. In this article,we will explore how Gateway works in GKE and learn in detail how to implement it in a GKE cluster.

What is GKE Gateway Controller?

The GKE Gateway controller is Google’s implementation of the Gateway API for Cloud Load Balancing. Similar to the GKE Ingress controller, the Gateway controller watches a Kubernetes API for Gateway API resources and reconciles Cloud Load Balancing resources to implement the networking behaviour specified by the Gateway resources. This is just the controller and not the Gateway itself, so we should not get confused between the Gateway Controller and the Gateway.

What is GKE Gateway?

Gateway is a Kubernetes resource which eventually leads to the creation of the Load Balancer in GCP behind which all our applications get attached.When we say that a Gateway was created,actually a Load Balancer gets created in GCP based on the GatewayClass specified

Components of Gateway :

  • GatewayClass : This is the parameter which specifies which type of Load Balancer will get created for our Gateway
  • HTTPRoute : Defines protocol-specific rules for routing requests from a Gateway to Kubernetes services.
  • Policy : Defines a set of implementation-specific characteristics of a Gateway resource. You can attach a policy to a Gateway, a Route, or a Kubernetes Service.These include GCPBackendPolicy, HealthCheckPolicy etc.

Now that we have some basic idea of Gateway in GKE,we can start with the hands-on demo but before creating a Gateway, we need to create a GKE cluster and setup deployments and services in it.

Create GKE cluster and deploy sample applications on it

To create a GKE cluster with gateway API enabled use the following command

  gcloud container clusters create <CLUSTER_NAME> \
--gateway-api=standard \
--cluster-version=<VERSION> \
--location=<CLUSTER_LOCATION>

Create a namespace named app-ns

kubectl create namespace app-ns

Create sample deployment and service manifests and apply it

### deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment-1
namespace: app-ns
spec:
replicas: 1
selector:
matchLabels:
app: app-1
template:
metadata:
labels:
app: app-1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
args:
- /bin/sh
- -c
- echo "This is app1 deployed in app-ns" > /usr/share/nginx/html/index.html && exec nginx -g 'daemon off;'

---
### service.yaml
apiVersion: v1
kind: Service
metadata:
name: app-svc-1
namespace: app-ns
spec:
selector:
app: app-1
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
kubectl apply -f deploy.yaml
kubectl apply -f service.yaml

Now that our sample application is deployed on GKE we can create a Gateway

Create GKE Gateway

Before creating the Gateway, we need to first decide the GatewayClass which we want to use. Based on whether we want to expose our application publicly or privately or whether we have a multi-cluster requirement we can choose the appropriate GatewayClass. You can see the list of available GatewayClass and their capabilities here. For this demo, we want to expose our application to the internet so for that we can use the GatewayClass gke-l7-global-external-managed

Gateway supports cross-namespace routing (which Ingress doesn’t support) in which our Gateway can be in a separate namespace and the services it routes to can be in a different namespace. We will leverage this functionality of Gateway and create the gateway in a separate namespace called gateway-ns.

kubectl create namespace gateway-ns
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: external-gateway
namespace: gateway-ns
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute

On applying this manifest, a Load Balancer gets created in GCP which acts as the Gateway for our cluster

Create HTTPRoute for our service

Now, we can create an HTTPRoute to specify the routing rules for our service. HTTPRoute is the resource in which we can specify any traffic management,routing and URL or path rewrite rules. You can learn more about Traffic Management Capabilities here.

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: app-route
namespace: app-ns
spec:
parentRefs:
- kind: Gateway
name: external-gateway
namespace: gateway-ns
hostnames:
- "demo-app.searceinc.net"
rules:
- backendRefs:
- name: app-svc-1
port: 80

In this we specify which gateway we want this HTTPRoute to reference to through the field spec.parentRefs[0].kind ,spec.parentRefs[0].namespace and spec.parentRefs[0].name

In the backendRefs field we can mention the service name to which the traffic will be routed to for the specified hostname.

Now, let’s go one step ahead and add another service to our cluster and configure path-based routing in the HTTPRoute manifest

For deploying the second service,use the same manifests we used for app-deployment-1 and just add 2 as the suffix everywhere.I am not showing that process for the sake of time. So we will now have a deployment named app-deployment-2 , a service named app-svc-2 in the namespace app-ns

Configure Path-Based Routing in HTTPRoute

We will now configure path-based routing in the HTTPRoute so that for the path /app1 the traffic will be directed to the service app-svc-1 and for the path /app2 the traffic will be directed to the service app-svc-2 .

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: app-route
namespace: app-ns
spec:
parentRefs:
- name: external-gateway
namespace: gateway-ns
hostnames:
- "demo-app.searceinc.net"
rules:
- matches:
- path:
type: PathPrefix
value: /app1
backendRefs:
- name: app-svc-1
port: 80
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
- matches:
- path:
value: /app2
backendRefs:
- name: app-svc-2
port: 80
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /

In the above manifest, we have also added a block for URL Redirect which redirects the path from /app1 and /app2 to / since the nginx server doesn’t have any service running on the path /app1 or /app2 so it would give an error if we don’t provide a path redirect to the path / on which our service runs by default.

/app1 path is directed to the app1 service
/app1 path is directed to app1 service
/app2 path is directed to app2 service

Next, we will configure HTTP to HTTPS redirect for our gateway

Configure HTTP to HTTPS redirect

We will add an HTTP(s) Listener to our gateway and configure the previously created HTTP Listener to only route to a redirect HTTPRoute which we will create in the gateway-ns namespace. Thus,any HTTP request is routed to to the HTTP Listener which routes the request to the redirect HTTPRoute. The Redirect HTTPRoute is configured to redirect the HTTP traffic to the HTTP(s) Listener of the gateway. The HTTPRoute of the namespace app-ns is attached to the HTTP(s) Listener of the gateway so the traffic is directed from the HTTP(s) Listener to the routes present in app-ns namespace.

The below diagram clearly depicts how the traffic will flow

Add the following manifest to create a redirect HTTPRoute

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: redirect-route
namespace: gateway-ns
spec:
parentRefs:
- name: external-gateway
namespace: gateway-ns
sectionName: http
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301

After applying this manifest, we can make the necessary changes to our gateway manifest to configure the HTTP and HTTP(s) Listeners.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: external-gateway
namespace: gateway-ns
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
kinds:
- kind: HTTPRoute
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
allowedRoutes:
kinds:
- kind: HTTPRoute
namespaces:
from: All
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: demo-app-searceinc-cert

For HTTP(s) to work you would require to create or upload your domain’s SSL certificate to GCP Certificate Manager and add the name of the certificate to the manifest in the field tls.mode.options.networking.gke.io/pre-shared-certs .

app1 with HTTP(s)
app2 with HTTP(s)
Note :- In the above images we can see a warning of Not Secure since the 
certificate I have used is a self-signed certificate

Thus, both are apps are working with HTTP-to-HTTP(s) redirect.

Limitations

Every service has some limitations and since Gateway is a relatively new service it has got some limitations as well which should be known before you opt for using it in your application.

You can check out a detailed list of Gateway Limitations and Issues here.

Conclusion

Hence, we have successfully created Gateway in GKE and exposed services publicly behind the Gateway. We learnt how to create manifests for Gateway and HTTPRoute, add path-based routing to HTTPRoute and create an HTTP-to-HTTP(s) redirect using different HTTP and HTTP(s) listeners on our gateway.
That’s all for this article. Hope you’ve enjoyed reading it.

Thank You!

--

--

Juzer Patanwala
Google Cloud - Community

Cloud Engineer @ Searce Inc || Technical Content Writer || Technology and Automation Enthusiast