Exploring API Gateways: Kong Setup

The beauty of software architecture is the myriad of strategies

Lucas Vargas Noronha
Better Programming

--

Photo by Keith Hardy on Unsplash

One technology that I feel will help me create better architectures is an API Gateway.

I had avoided microservices architectures, but I watched Continuous Delivery's video, and independently deployable services made my eyes light up.

The beauty of software architecture is the myriad of strategies. Imagine a design that you could de-couple your organization at the development level. I am going for it.

One technology that I believe will help me design better architecture (not only microservices) is an API Gateway. It will help me tie the underlying containers up and identify shared functionalities. I will cover it in later posts. For now, I will present my starting point.

After some researches, I decided to use Kong as my learning tool, mostly because of custom Golang plugins, and I can run it locally.

Overview

Container Diagram

The Kong API Gateway will be deployed inside a Kubernetes cluster and configured using the declarative approach. I will sync the local configuration file with a Pod containing a decK container that will communicate with the Kong Admin API.

Kubernetes

I opted for Kubernetes just for the personal challenge. Using Docker Compose is probably easier and faster.

I chose Kind to create the cluster because it is faster, and I can keep everything in a single Docker Network, even the Postgres database.

Ports 8000 and 8443 will be exposed to interact with the Kong Proxy and test our microservices architecture.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: kong-in-kubernetes
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 32080
hostPort: 8000
- containerPort: 32443
hostPort: 8443

Finally: kind create cluster --config kind.yaml

Postgres database for Kong

It seems fair to use Kong with Postgres, but I did not want to deploy a database inside Kubernetes (regretting my choices), too much work and complexity.

An easier way is to deploy a Postgres database inside kind's network and reference it using an ExternalName Service.

Docker Compose:

services:
database:
image: postgres
ports:
- 5432:5432
networks:
- kind

environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD: kong
networks:
kind:
external: true
name: kind

Postgres ExternalName Service:

apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: ExternalName
externalName: database

Running everything:

docker-compose up -dkubectl apply -f postgres/svc.yaml

Kong

With all set, we can focus on the API Gateway. The easiest way to deploy Kong in Kubernetes is using the Helm Chart, and I will break down some essential values in the Chart.

Environment Variables

env:
database: postgres
pg_host: database
pg_user: kong
pg_password: kong
pg_database: kong
declarative_config: /opt/kong/kong.yaml

Every variable in the env section will be transformed to uppercase and prefixed by KONG_. Our goal is to instruct Kong to use the Postgres database, the reason why env.pg_host is set to database , the Postgres' service name in kind's network.

Kong Admin API

We will configure Kong with decK that needs to communicate with the Kong Admin API. But we do not want to expose this API outside Kubernetes. That is why we will use a ClusterIP Service:

admin:
enabled: true
type: ClusterIP

http:
enabled: true

Exposing Kong Proxy

By the end of the day, we need to test our API Gateway, and it needs to be exposed out of the Docker Network. In Kind's configuration, the kind's container bound the container's ports 32080 and 32443 to 8000 and 8443, respectively. These will be the NodePorts:

proxy:  
enabled: true
type: NodePort
http:
nodePort: 32080

tls:
nodePort: 32443

Deploying Kong

Everything in order, we can run:

helm repo add kong https://charts.konghq.com

helm repo update

helm install -n kong --create-namespace api-gateway kong/kong --set ingressController.installCRDs=false --values kong/values.yaml

Declarative Configuration

Before iterating over Kong's features, our last step is to configure the API Gateway. I prefer declarative approaches, but this requires syncing a local file. Sadly, I complicated my life with Kubernetes, but I came up with a solution.

Using kubectl cp and decK, I created a script that:

  1. Spawns a Pod with decK
  2. Copies a local kong.yaml file to decK's container
  3. Runs the sync command in decK
  4. Deletes the Pod
#!/bin/bashkubectl run -n kong --wait --restart=Never deck --image=kong/deck --command -- sleep 3600
kubectl wait -n kong --for=condition=ready pods/deck
kubectl cp ./kong/kong.yaml kong/deck:/tmp/kong.yaml
kubectl exec -n kong deck -- deck sync --kong-addr=http://api-gateway-kong-admin:8001 -s /tmp/kong.yaml
kubectl delete -n kong pods/deck

decK communicates with Kong API using the service created by the admin section in the Chart values file.

Now we are ready to go.

Next Steps

This is a how-to article but a starting point: Kubernetes cluster with Kong API Gateway ready to iterate over microservices designs.

You can check the complete environment in my GitHub Repository:

https://github.com/vargasmesh/Kong-in-Kubernetes.

Now, I will set sail for this microworld and see what we can learn from it.

--

--