Configure Gateway API

Gateway API is an official Kubernetes project focused on L4 and L7 routing in Kubernetes. This project represents the next generation of Kubernetes Ingress, Load Balancing, and Service Mesh APIs. From the outset, it has been designed to be generic, expressive, and role-oriented. (Official documentation)

On this runbook we’ll show you how to configure the basics to start using Gateway API with StackGres.

Important: In case your Kubernetes cluster, does not have a LoadBalancer implementation, we recommend installing one so the Gateway resource has an Address associated with it. We recommend using MetalLB.

Gateway API components

There are four main components to configure the Gateway API:

  1. Gateway Controller: A gateway controller is software that manages the infrastructure associated with routing traffic across contexts using Gateway API, analogous to the earlier ingress controller concept. Gateway controllers often, but not always, run in the cluster where they’re managing infrastructure.

There are various controller you can use for your infrastructure, check the list here.

For the demo purpose we will use the Envoy Gateway.

  1. GatewayClass: Is a cluster-scoped resource. There must be at least one GatewayClass defined in order to be able to have functional Gateways.

  2. Gateways: A Gateway describes how traffic can be translated to Services within the cluster. That is, it defines a request for a way to translate traffic from somewhere that does not know about Kubernetes to somewhere that does.

It defines a request for a specific load balancer config that implements the GatewayClass’ configuration and behaviour contract. The resource may be created by an operator directly, or may be created by a controller handling a GatewayClass.

  1. Routes: Route resources define protocol-specific rules for mapping requests from a Gateway to Kubernetes Services.

We will show you how to create a TCPRoute to handle Postgres traffic. You can check the different types of Routes here

SGCluster

In order to focus on the Gateway API configuration we will assume that you already have your SGCluster up and running. Check the StackGres Demo Quickstart to create your cluster. The demo cluster used here was created on GKE.

Demo SGCluster:

❯ kubectl get sgclusters.stackgres.io -n my-db 
NAME    VERSION   INSTANCES   PROFILE   DISK
my-db   16.2      1           size-s    10Gi

SGCluster service:

 kubectl get services -n my-db -l stackgres.io/cluster=true
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
my-db          ClusterIP   10.63.219.145   <none>        5432/TCP,5433/TCP   61m
my-db-config   ClusterIP   None            <none>        <none>              61m

Configure Gateway API

1. Install the Gateway API Controler:

Even though GKE already provides a Gateway API controller, we’ll use the Envoy controller.

Install it executing the next command:

helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace

Note: For custom requirements check the official documentation

2. Create the GatewayClass

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF

Check the object created:

❯ kubectl get gatewayclasses.gateway.networking.k8s.io 
NAME   CONTROLLER                                      ACCEPTED   AGE
eg     gateway.envoyproxy.io/gatewayclass-controller   True       86m

3. Create the Gateway

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: tcp-gateway
  namespace: my-db
spec:
  gatewayClassName: eg
  listeners:
  - name: pg-gateway
    protocol: TCP
    port: 5432
    allowedRoutes:
      kinds:
      - kind: TCPRoute
EOF

Check the object created:

❯ kubectl get gateways.gateway.networking.k8s.io -n my-db 
NAME          CLASS   ADDRESS        PROGRAMMED   AGE
tcp-gateway   eg      34.89.14.197   True         72m

Note that we are using the namespace my-db because only the GatewayClass is cluster-scoped.

The IP address might take a few minutes to be assigned. This is the public IP that you need to use as the service endpoint.

4. Create the TCPRoute

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: my-db-route
  namespace: my-db
spec:
  parentRefs:
  - name: tcp-gateway
    sectionName: pg-gateway
  rules:
  - backendRefs:
    - name: my-db
      port: 5432
EOF
  • Check the sectionName field in the parentRefs. This correspond directly with the name in the listeners in the Gateway
  • The backendRefs correspond to the database service.

Check Postgres connection

Once you configured the Gateway API, the last thing is to check if you have connection to your database cluster:

We got the superuser passsword with the next command:

PASSWORD=$(kubectl get secret -n my-db my-db --template '{{ printf "%s" (index .data "superuser-password" | base64decode) }}')
echo "user: postgres"
echo "password: $PASSWORD"

output:

user: postgres
password: 7a83-4f62-4c71-815

Now we can test the connection to the cluster:

❯ psql -h 34.89.14.197 -p 5432 -U postgres -d postgres
Password for user postgres: 
psql (16.3 (Ubuntu 16.3-1.pgdg22.04+1), server 16.2 (OnGres 16.2-build-6.31))
Type "help" for help.

postgres=# 

Next steps

  • The above example was intended to show you the basic configuration of the Gateway API. If you want to expose your database, make sure to configure a secure connection to it.

  • Check the security documentation for the Envoy Gateway here