试用Kong

Kong是一个基于Nginx的API网关和微服务管理平台。它提供了一组高级功能,例如请求路由、负载均衡、认证、监控和分析等,以帮助开发人员更轻松地构建和管理微服务架构。

更确切地说,Kong是一个在Nginx中运行的Lua应用程序,并且可以通过lua-nginx模块实现。Kong不是用这个模块编译Nginx,而是与OpenResty一起分发,OpenResty已经包含了lua-nginx-module。OpenResty不是Nginx的分支,而是一组扩展其功能的模块。

这为可插拔架构奠定了基础,可以在运行时启用和执行Lua脚本(称为“插件”)。 因此,我们认为Kong是微服务架构的典范:它的核心是实现数据库抽象,路由和插件管理。 插件可以存在于单独的代码库中,并且可以在几行代码中注入到请求生命周期的任何位置。

开始

安装docker和docker-compose

1
2
3
4
5
# Install the latest version docker
curl -s https://get.docker.com/ | sh
# Install docker compose
curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

克隆仓库

1
2
git clone https://github.com/Kong/docker-kong
cd docker-kong/compose/

启动

1
2

KONG_DATABASE=postgres docker-compose --profile database up

如果没报错,可以加-d后台运行

我们可以查看下https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml

看看docker里面启动了什么容器

这个Compose文件定义了三个服务:kong-migrations、kong-migrations-up和kong

kong-migrations

kong-migrations服务用于执行Kong数据库迁移的初始化操作。该服务的命令为kong migrations bootstrap,这个服务依赖于一个名为db的服务,表示它需要在db服务启动之后才能启动。此外,它还引用了一个名为kong_postgres_password的密钥,用于访问PostgreSQL数据库。该服务使用了名为kong-net的网络,并在失败时重新启动。

kong migrations bootstrap 命令是Kong在首次数据库初始化时使用的。

  1. 创建所需的数据库表

Kong需要一些核心表来存储配置数据,如kong.apis、kong.consumers等。bootstrap会根据数据库类型(Postgres/Cassandra)来创建并初始化这些核心表。

  1. 创建кong_migrations表

kong_migrations表用于记录已经运行的数据库迁移脚本版本。这Ensure the initial database schema宷一个> 初始化的数据库结构。

  1. 插入初始记录

会插入一些必须的初始数据,如设置表primary key等。

  1. 标记为执行完成

在kong_migrations表中插入一条执行记录,标记bootstrap已经完成。

所以在Kong首次使用一个空数据库时,需要先执行bootstrap建立初始表结构,然后才能使用kong migrations > > up执行后续的数据库升级。

与直接使用up命令不同,bootstrap专门用于初始化一个空数据库。执行成功后,该数据库即可用于启动Kong。

kong-migrations-up

kong-migrations-up服务与kong-migrations服务类似,kong migrations up 和 kong migrations finish 这两个命令是Kong在数据库初始化和升级时使用的。

kong migrations up:

  • 这个命令会运行所有未应用的数据库迁移脚本,以将Kong的数据库schema更新到最新版本。

  • Kong的数据库脚本存放在kong/migrations/目录下,每次Kong版本升级都会添加新的迁移脚本。

  • kong migrations up会按文件名顺序运行新增的迁移脚本,以分阶段地更新数据库结构。

kong migrations finish:

  • 在所有迁移脚本运行完成后,这个命令将会删除kong_migrations表中记录的所有迁移历史。

  • kong_migrations表中存放了已运行迁移脚本的记录,用于判断尚未运行的脚本。

  • finish命令清除历史后,后续再次运行kong migrations up时会从头开始运行所有脚本。

所以这两个命令组合可以完成Kong数据库的初始化更新。

  • kong migrations up带来所有新脚本变更
  • kong migrations finish重置运行历史

每次Kong版本升级都需要运行这两个命令,以更新数据库结构。

kong服务

kong服务才是主要的Kong运行实例,是Kong网关的主要服务。

它使用了与前两个服务相同的Docker镜像,并可以通过环境变量${KONG_USER}指定运行用户,默认为kong。该服务配置了多个环境变量,包括Kong的管理员访问日志、代理访问日志、Kong的监听地址和端口等。它也引用了kong_postgres_password密钥,并使用了相同的网络和重新启动策略。此外,它还暴露了一些端口,包括代理监听端口、管理员监听端口以及Kong的Web管理界面监听端口。这些端口可以通过环境变量进行配置。该服务还定义了一个健康检查,每10秒执行一次kong health命令来检查服务的健康状态。它还将容器设置为只读模式,并挂载了一些卷用于存储Kong的运行数据和配置文件。最后,kong服务还设置了一个名为no-new-privileges的安全选项,用于禁止容器在运行时获取新的特权。

上面文件监听如下:

1
2
3
4
5
0.0.0.0:8000
127.0.0.1:8001
127.0.0.1:8002
0.0.0.0:8443
127.0.0.1:8444
1
2
3
4
5
6
# netstat -antp | grep docker-proxy
tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 28466/docker-proxy
tcp 0 0 127.0.0.1:8444 0.0.0.0:* LISTEN 28385/docker-proxy
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 28639/docker-proxy
tcp 0 0 127.0.0.1:8001 0.0.0.0:* LISTEN 28602/docker-proxy
tcp 0 0 127.0.0.1:8002 0.0.0.0:* LISTEN 28550/docker-proxy

8000 就是Kong的转发流量的端口
8001 使用 Admin API 或通过 decK 配置 Kong
8002 访问 Kong 的管理 Web UI ( Kong Manager)

https://docs.konghq.com/gateway/latest/get-started/services-and-routes/

其实假如将监听改为0.0.0.0会更加方便实践,在生产环境应该不建议这么做了

api测试用例

用python flask写了简单的api示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cat app.py 
from flask import Flask, jsonify

app = Flask(__name__)

# 假设这是一个存储在数据库中的用户数据列表
users = [
{'id': 1, 'name': 'Alice'},
{'id': 2, 'name': 'Bob'},
{'id': 3, 'name': 'Charlie'}
]

@app.route('/users/<int:user_id>')
def get_user(user_id):
for user in users:
if user['id'] == user_id:
return jsonify({'id': user['id'], 'name': user['name']})
return jsonify({'error': 'User not found'})

if __name__ == '__main__':
app.run(host="0.0.0.0", port=808)

测试没问题:

1
2
root@ubuntu:~# curl http://192.168.145.131:808/users/1
{"id":1,"name":"Alice"}

配置转发

  1. 新建服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@ubuntu2004:~/python-api# curl -i -s -X POST http://localhost:8001/services \
> --data name=flask-api \
> --data url='http://192.168.145.131:808'
HTTP/1.1 201 Created
Date: Sun, 05 Nov 2023 12:28:36 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 375
X-Kong-Admin-Latency: 4054
Server: kong/3.4.2

{"enabled":true,"write_timeout":60000,"tls_verify":null,"tls_verify_depth":null,"retries":5,"protocol":"http","updated_at":1699187312,"port":808,"client_certificate":null,"tags":null,"path":null,"id":"3bb09dda-db8a-4587-bd0f-9cd9607f636d","connect_timeout":60000,"read_timeout":60000,"ca_certificates":null,"host":"192.168.145.131","created_at":1699187312,"name":"flask-api"}
  1. 创建路由

/flasktest的的流量定向到之前创建的 flask-api 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@ubuntu2004:~/python-api# curl -i -X POST http://localhost:8001/services/flask-api/routes \
> --data 'paths[]=/flasktest' \
> --data name=flask-route
HTTP/1.1 201 Created
Date: Sun, 05 Nov 2023 12:33:41 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Content-Length: 488
X-Kong-Admin-Latency: 16
Server: kong/3.4.2

{"path_handling":"v0","https_redirect_status_code":426,"methods":null,"sources":null,"destinations":null,"created_at":1699187621,"protocols":["http","https"],"regex_priority":0,"service":{"id":"3bb09dda-db8a-4587-bd0f-9cd9607f636d"},"headers":null,"tags":null,"snis":null,"preserve_host":false,"paths":["/flasktest"],"id":"ec442942-4857-44c1-8462-0aca41717cf2","strip_path":true,"updated_at":1699187621,"hosts":null,"request_buffering":true,"response_buffering":true,"name":"flask-route"}

现在我们访问,就可以了

1
2
root@ubuntu2004:~/python-api# curl http://192.168.145.131:8000/flasktest/users/1
{"id":1,"name":"Alice"}

当然也可以在8002端口的web界面进行设置

复杂均衡

  1. 创建upstream
1
2
curl -X POST http://localhost:8001/upstreams \
--data name=example_upstream
  1. 创建负载均衡目标
1
2
3
4
curl -X POST http://localhost:8001/upstreams/example_upstream/targets \
--data target='mockbin.org:80'
curl -X POST http://localhost:8001/upstreams/example_upstream/targets \
--data target='httpbin.org:80'
  1. Update the service 更新服务
1
2
curl -X PATCH http://localhost:8001/services/example_service \
--data host='example_upstream'
  1. 验证

多次访问查看host的变化在mockbin和httpbin 之间更改就是配置成功了(注:mock路径是之前官方文档创建的路由)

1
curl -s http://localhost:8000/mock/headers |grep -i -A1 '"host"'

插件

插件那里有一些安全插件、流量控制的东西,这种东西自己搞可能就比较费劲了

当然还有代理缓存

参考

https://github.com/Kong/kong

https://docs.konghq.com/gateway/latest/get-started/services-and-routes/

打赏专区