使用Docker和Traefik来部署Kong API网关和Konga

最近一段时间接触到了Kong API网关。这个产品使用上特别地方便,但是网上的相关的内容虽多但是大多部署都是重复官方文档的内容,有很多我需要实现的功能找不到很好的教程。
我需要实现的功能包括

  • 使用https加密Kong Admin API
  • 实现http到https的自动转接
  • SSL证书的自动部署和更新
  • 部署Konga(第三方的Kong Admin API的图形管理界面)
  • Admin API可以通过服务器直接调用以防Konga出问题

在尝试很多中不同组合之后还是发现使用Traefik作为reverse proxy的方式可以实现上述功能,特记录下来供大家参考。如果您知道其他的正确配置kong的方法,请您不吝赐教。
配置Kong我需要使用file provider来设置,如果您还不清楚Traefik的file provider如何使用,请您参考我的这篇文章。也因为使用的file provider,所以本文不适用我的默认配置,我会把所有的文件内容列出来。

首先我们把需要的文件创建好。

1
2
3
4
5
6
touch docker-compose.yml
mkdir data && mkdir kong && mkdir data/configurations
touch kong/docker-compose.yml && touch kong/kong.env
touch data/traefik.yml && touch data/acme.json
touch data/configurations/dynamic.yml
chmod 600 data/acme.json

接下来就开始填每个文件的内容。

部署Traefik

~/docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '3.7'

services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
# Add folder with dynamic configuration yml
- ./data/configurations:/configurations
networks:
- proxy

networks:
proxy:
external: true

~/data/traefik.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
api:
dashboard: true

entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure

websecure:
address: :443
http:
middlewares:
- secureHeaders@file
tls:
certResolver: letsencrypt

providers:
file:
filename: /configurations/dynamic.yml

certificatesResolvers:
letsencrypt:
acme:
email: admin@yourdomain
keyType: EC384
httpChallenge:
entryPoint: web

~/data/configurations/dynamic.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# Dynamic configuration
http:
routers:
dashboard:
service: api@internal
middlewares:
- "user-auth"
rule: "Host(`dash.yourdomain`)"
kong:
service: kong-service
middlewares:
rule: "Host(`kong.yourdomain`)"
konga:
service: konga-service
middlewares:
rule: "Host(`konga.yourdomain`)"
middlewares:
secureHeaders:
headers:
sslRedirect: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000

# UserName : admin
# Password : qwer1234
user-auth:
basicAuth:
users:
- "admin:$apr1$tm53ra6x$FntXd6jcvxYM/YH0P2hcc1"
services:
kong-service:
loadBalancer:
servers:
- url: "http://ip-address-of-kong:8000"
konga-service:
loadBalancer:
servers:
- url: "http://ip-address-of-konga:1337"
tls:
options:
default:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
minVersion: VersionTLS12

这就是我们运行Traefik所需要的三个文件。替换上我们的域名之后我们输入docker-compose up -d,等traefik的container运行之后,我们可以通过dash.yourdomain来打开Traefik的面板。

部署Kong以及Konga

~/kong/docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
version: '2.1'

services:
#######################################
# Postgres: Kong Database
#######################################
kong-database:
image: postgres:9.6-alpine
container_name: kong-db
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD: kong
networks:
- default
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 10s
timeout: 5s
retries: 5
restart: on-failure

#######################################
# Kong database migration
#######################################
kong-migrations:
image: kong:latest
command: kong migrations bootstrap
depends_on:
kong-database:
condition: service_healthy
env_file:
- ./kong.env
networks:
- default
restart: on-failure

#######################################
# Kong: The API Gateway
#######################################
kong:
image: kong:latest
container_name: kong-api
depends_on:
kong-database:
condition: service_healthy
env_file:
- kong.env
networks:
- default
- proxy
ports:
- "127.0.0.1:8001:8001"
healthcheck:
test: ["CMD", "kong", "health"]
interval: 10s
timeout: 10s
retries: 10
restart: on-failure

#######################################
# Konga database migration
#######################################
konga-prepare:
image: pantsel/konga
command: "-c prepare -a postgres -u postgresql://kong:kong@kong-db:5432/konga_db"
networks:
- default
restart: on-failure
depends_on:
kong-database:
condition: service_healthy

#######################################
# Konga: GUI of KONG Admin API
#######################################
konga:
image: pantsel/konga
env_file:
- kong.env
networks:
- default
- proxy
restart: on-failure
depends_on:
kong-database:
condition: service_healthy

networks:
proxy:
external: true

这个文件有几个点我需要提及。

  • 你可以不为konga创建database。如果选择不用database,上面配置中的konga-prepare可以省略但是你需要创建一个persistent volume来放konga的数据。
    1
    2
    volumes:
    - konga-data:/app/kongadata
    当然无论如何你都会在log里面看到以下提示。
    1
    2
    3
    4
    5
    konga_1 | The default `sails-disk` adapter is not designed for use as a production database;
    konga_1 | (it stores the entire contents of your database in memory)
    konga_1 | Instead, please use another adapter; e.g. sails-postgresql or sails-mongo.
    konga_1 | For more info, see: http://sailsjs.org/documentation/concepts/deployment
    konga_1 | To hide this warning message, enable `sails.config.orm.skipProductionWarnings`.
    对于我这样的洁癖患者,我还是乖乖地在现成Kong的postgresql container里面添加一个数据库就好。这也是我没用选择用Cassandra作为数据库的另外一个原因。
  • 选择9.6版的postgres alpine image。这是因为Konga不支持最新版的postgresql,来源是官方github的这个帖子,并且我想减少体积
  • konga-prepare的作用和kong-migrations一样,就是database migration
  • 我把所有用到的environment variable都放到了kong.env这个文件里面。

    ~/kong/kong.env

    1
    2
    3
    4
    5
    6
    7
    8
    9
    KONG_DATABASE=postgres
    KONG_PG_HOST=kong-db
    KONG_PG_USER=kong
    KONG_PG_PASSWORD=kong
    KONG_PG_DATABASE=kong
    KONG_ADMIN_LISTEN=0.0.0.0:8001

    TOKEN_SECRET=someSecret12345
    NODE_ENV=production
    这两个文件准备好之后,我们进到~/kong/这个文件夹里面,运行docker-compose up -d就会自动把需要的postgresqlkong以及konga的container创建好。

    添加Kong和Konga的设置到Traefik

    在container创建好了之后,我们需要使用docker inspect <container_id>的方式来获取kong和konga container的ip地址,然后在~/data/configurations/dynamic.yml里面把对应的ip地址写好即可。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    services:
    kong-service:
    loadBalancer:
    servers:
    - url: "http://ip-address-of-kong:8000"
    konga-service:
    loadBalancer:
    servers:
    - url: "http://ip-address-of-konga:1337"

如果不知道怎么设置的朋友,请参考我之前file provider的文章以及视频。等我有时间我也会把本文视频化这样就更直观了。如果你有不明白的地方,请给我留言。

咱们下次再见