Introduction
I was motivated to move away from a databaseless Kong ingress setup to a maintained Postgres database. As the cloud provider is DO, Casandra as a database was not an option unless Casandra is installed on a droplet, which is always a good option but more work when it comes to maintenance. Anyhow, Kong strongly recommends Postgres over Casandra. By moving to a database setup, I could remove all the additional Kubernetes YAML manifests for plugins, consumer keys, consumers, and so on. Furthermore, I can now use Konga to easily update any services, routes, consumers, plugins, etc from a nice GUI. More on Konga later.
Preparation and Installation
I generally write my code for deployment and destruction with Makefiles. However, for simplicity we will stick to command lines.
The following commands are used to install Kong on a cluster. Helm 3 is required along with kubectl
.
kubectl apply -f PostgresSecret.yaml
helm repo add kong https://charts.konghq.com
helm repo update
helm install ingress-kong kong/kong \
--set ingressController.installCRDs=false,\
postgresql.enabled=false,\
env.database=postgres,\
env.pg_user.valueFrom.secretKeyRef.key=username,\
env.pg_user.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_password.valueFrom.secretKeyRef.key=password,\
env.pg_password.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_host.valueFrom.secretKeyRef.key=host,\
env.pg_host.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_port=25060,\
env.pg_database.valueFrom.secretKeyRef.key=database,\
env.pg_database.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_ssl=true
Let’s go over the above commands. First, I wrote a manifest PostgresSecret.yaml
that contains a secret:
---
apiVersion: v1
kind: Secret
metadata:
name: kong-database-secret
namespace: default
type: Opaque
data:
username: <bas64 encoded string>
password: <bas64 encoded string>
host: <bas64 encoded string>
database: <bas64 encoded string>
The <bas64 encoded string>
can be generated by echo 'some string' | basee64
. kubectl apply -f PostgresSecret.yaml
simply updates/creates
the secret in a cluster. The subsequent commands are related to Helm and the installation of a specific repo and the update of all repos. Finally,
helm install ingress-kong kong/kong \
--set ingressController.installCRDs=false,\
postgresql.enabled=false,\
env.database=postgres,\
env.pg_user.valueFrom.secretKeyRef.key=username,\
env.pg_user.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_password.valueFrom.secretKeyRef.key=password,\
env.pg_password.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_host.valueFrom.secretKeyRef.key=host,\
env.pg_host.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_port=25060,\
env.pg_database.valueFrom.secretKeyRef.key=database,\
env.pg_database.valueFrom.secretKeyRef.name=kong-database-secret,\
env.pg_ssl=true
is executed. Here, we are simply installing Kong with the release name ingress-kong with several environmental variables set.
As we want to dynamically pull information from our secret we must include valueFrom.secretKeyRef.key
and valueFrom.secretKeyRef.name
. Of
course, we do not require a secret, and we could literally hardcode all the database information in the command.
As an interface to Kong, a pretty GUI, I installed Konga via docker-compose
locally:
version: '3.8'
services:
# run once
konga-prepare:
image: pantsel/konga:next
command: "-c prepare -a postgres -u postgresql://user:password@server:25060/konga?sslmode=require&ssl=true"
restart: on-failure
konga:
image: pantsel/konga:next
restart: unless-stopped
environment:
DB_ADAPTER: 'postgres'
DB_HOST: 'server'
DB_DATABASE: 'konga'
DB_USER: 'user'
DB_PASSWORD: 'password'
DB_PORT: 25060
DB_SSL: 1
NODE_TLS_REJECT_UNAUTHORIZED: 0 # may not be needed
TOKEN_SECRET: 'token'
NODE_ENV: 'production'
ports:
- "1337:1337"
depends_on: # comment out after first run
- konga-prepare
dockerhost:
image: qoomon/docker-host
container_name: dockerhost
cap_add:
- NET_ADMIN
- NET_RAW
restart: on-failure
docker-compose up
will allow you to access Konga from localhost:1337
but only after konga-prepare
runs
and installs the new database. I use dockerhost
for access to my host. This will make sense in a bit. Note,
make sure to include the correct database information in the docker-compose.yaml
above.
With docker-compose
running we need to create a port-forward to our Kong admin interface on port 8444 (ssl). This can
easily be achieved with the following (assuming namespace was left as default):
kubectl port-forward $(kubectl get pod -l app.kubernetes.io/instance=ingress-kong -o jsonpath='{.items[0].metadata.name}') 8444:8444
With the port-forward to your cluster made we now can go to localhost:1337
and create a new admin account. Once done,
we need to create a new connection to our Kong and this is where dockerhost
is applied. As a new connection, we need
to use https://dockerhost:8444
. This should create a successful connection to your Kong instance. Now create your consumers,
add your plugins, create your routes and services, etc. Have fun! You could always deploy Konga, but I avoid this for security reasons.
Final Words
I have quickly detailed how to get Kong with a dedicated database installed and configured via Konga and Docker Compose.
There really is not any challenge here. However, if you do have an issue with initializing your database you can
always check your pod kubectl logs ingress-kong-kong-init-migrations-<somestring> -c wait-for-postgres
.