Introduction of Different Kong Deployment Methods With Docker

I’ve written several posts about using Kong plugins in the past few months. It is until recently, one of my viewers asked me if I could cover different deployment methods that I realised this could be the most important topic that I should be covering first.

Generally speaking, Kong can be installed on VM, docker and Kubernetes. Although the platforms are different, deployment concepts are the same. You can install Kong in the classic way with postgres database, DBless or in Hybrid mode.

In this post I will be exploring all these deployment methods. You should be able to use provided commands to start Kong.

Let’s get started.

Prerequisites:

You must have Docker installed.

Classic Deployment with Postgres

This could be the most common way of using Kong. Users use Admin API to create kong entities and store them in database. The environment variables I use are pretty self-explanatory. You can find references of these variables on this doc.

Create Docker Network

We will put all our containers in a network called kong-net.

1
docker network create kong-net

Create Postgres container

This will spin up a postgres container called kong-db and create database kong, user kong and user password kong.

1
2
3
4
5
6
docker run --detach --name kong-db \
--network kong-net \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_PASSWORD=kong" \
postgres:12-alpine

Database Bootstrap

Before starting Kong, you need to bootstrap the database, meaning kong needs to create some tables in the database before it starts.

1
2
3
4
5
6
7
8
docker run --rm --name kong-migrations \
--network kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-db" \
-e "KONG_PG_DATABASE=kong" \
-e "KONG_PG_USER=kong" \
-e "KONG_PG_PASSWORD=kong" \
kong:2.5-ubuntu kong migrations bootstrap

Start Kong container

Once the database is bootstrapped, we can start kong. I am using port 8000 for proxy and 8001 for Admin API here.

1
2
3
4
5
6
7
8
9
10
11
docker run --detach --name kong \
--network kong-net \
-p "8000-8001:8000-8001" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-db" \
-e "KONG_PG_DATABASE=kong" \
-e "KONG_PG_USER=kong" \
-e "KONG_PG_PASSWORD=kong" \
kong:2.5-ubuntu

Docker Compose file

If you prefer using a single file, you can download my docker compose file from GitHub with below command.

1
wget https://git.io/JWliZ -nv -O docker-compose.yaml

DBless Deployment

This deployment method as its name suggests runs without a database. All properties (service, route, plugins etc) are loaded in memory. Users can design and write their declarative configuration and then have all their configs ready when Kong starts. For more information, please refer to official doc.

Config file

Let’s prepare a simple configuration file. Please save below content to kong.yaml.

On this config I’ve got

  • One service that use httpbin as the upstream server.
  • One route that will match requests at /demo
  • Key authentication plugin enabled on service.
  • One consumer with apikey demo-key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
_format_version: "2.1"
_transform: true

services:
- name: demo-service
url: http://httpbin.org/anything
plugins:
- name: key-auth
routes:
- name: demo-route
paths:
- /demo

consumers:
- username: demo-user
keyauth_credentials:
- key: demo-key

Pre-load Config

To start Kong with all the configurations, we need to mount above config file inside Kong container and use KONG_DECLARATIVE_CONFIG environment variable to tell kong where to find it. I also enabled port 8000 for proxy and 8001 for admin api.

1
2
3
4
5
6
7
8
docker run --rm --detach --name kong \
-p "8000-8001:8000-8001" \
-v "$(pwd)/kong.yaml:/config/kong.yaml" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
-e "KONG_DATABASE=off" \
-e "KONG_DECLARATIVE_CONFIG=/config/kong.yaml" \
kong:2.5-ubuntu

Use /config endpoint

We can also load new configurations to Kong containers via admin api /config endpoint. Below curl command pushes configuration to Kong. The drawback of using this method is that configs won’t survive after a restart. IMO we can use /config endpoint for testing and mount the file when we are ready to use Kong.

1
curl -X POST http://localhost:8001/config -F [email protected]

Hybrid Deployment

This deployment method combines the benefits of using both traditional and dbless methods. Users store their configurations in database and their proxy nodes can be easily start and scale without the need of connecting to the database. For more information, please refer to official doc.

Create Docker Network

1
docker network create kong-net

Create Certificate and Key

Connection between control plane and data planes is always protected with Mutual TLS (mTLS) encryption. We are going to generate a certificate pair for that purpose.

First we create a folder in current directory to store our cluster certificates.

1
mkdir cert

Then we generate certificate and key.

Note that I am using shared mode here which means both control plane and data planes are using the same certificate. You must use kong_clustering as the common name of the certificate in this mode.

1
2
3
openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp384r1) \
-keyout cert/cluster.key -out cert/cluster.crt \
-days 1095 -subj "/CN=kong_clustering"

Create Postgres container

Same as the traditional method, we need to start a Postgres container to store configurations.

1
2
3
4
5
6
docker run --detach --name kong-db \
--network kong-net \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_PASSWORD=kong" \
postgres:12-alpine

Database Bootstrap

We also need to bootstrap database.

1
2
3
4
5
6
7
8
docker run --rm --name kong-migrations \
--network kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-db" \
-e "KONG_PG_DATABASE=kong" \
-e "KONG_PG_USER=kong" \
-e "KONG_PG_PASSWORD=kong" \
kong:2.5-ubuntu kong migrations bootstrap

Start control plane

After bootstrapping the database, we can start our control plane. We should be able to use Admin API at port 80001 to create Kong entities now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker run --detach --name kong-cp \
--network kong-net \
-v "${PWD}/cert/:/cert" \
-p "8001:8001" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_ROLE=control_plane" \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-db" \
-e "KONG_PG_DATABASE=kong" \
-e "KONG_PG_USER=kong" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_CLUSTER_CERT=/cert/cluster.crt" \
-e "KONG_CLUSTER_CERT_KEY=/cert/cluster.key" \
-e "KONG_PROXY_LISTEN=off" \
-e "KONG_STREAM_LISTEN=off" \
kong:2.5-ubuntu

Start data plane

Use below to start your data plane. Once the connection is made, Control plane pushes configuration to data plane automatically. You should be able to access your api service via port 8000.

1
2
3
4
5
6
7
8
9
10
11
docker run --detach --name kong-dp \
--network kong-net \
-v "${PWD}/cert/:/cert" \
-p "8000:8000" \
-e "KONG_ADMIN_LISTEN=off" \
-e "KONG_ROLE=data_plane" \
-e "KONG_DATABASE=off" \
-e "KONG_CLUSTER_CERT=/cert/cluster.crt" \
-e "KONG_CLUSTER_CERT_KEY=/cert/cluster.key" \
-e "KONG_CLUSTER_CONTROL_PLANE=kong-cp:8005" \
kong:2.5-ubuntu

Docker Compose file

If you prefer using a single file, you can download my docker compose file from GitHub with below command.

1
wget https://git.io/JW88B -nv -O docker-compose.yaml

That’s all I want to cover in this post. I will make a video to demonstrate each deployment method to help you understand how to use them. In my next post I will talk about these three deployment methods on Kubernetes via Helm.