title: API网关之Kong #标题tags: #标签
date: 2021-12-12 22:13:00
categories: API网关 # 分类

kong介绍

kong是一款基于OpenResty(Niginx+Lua模块)编写的高可用、易扩展的,由Mashape公司开源的API Gateway项目,kong是基于Nginx和Apache Cassandra或PostgreSQL构建的,能提供易于使用的RESTful API来操作和配置API管理系统,所以它可以水平扩展多个kong服务器,通过前置的负载均衡配置把请求均匀的分发到各个Server,以此来应对大批量的网络请求。

参考资料:

kong的工作架构如下:

API网关之Kong - 图1

kong主要有三个组件:

  • Kong server:基于nginx的服务器,用来接收API请求;
  • Apache Cassandra/PostgreSQL:用来存储操作数据;
  • Kong dashboard:官方推荐UI管理工具,当然,也可以用restfull方式管理admin api,或者konga。

kong采用插件机制进行功能定制,插件集(可以是0或N个)在API请求响应循环的生命周期中被执行。插件使用Lua编写,目前已有几个基础功能:HTTP基本认证、秘钥认证、CORS(Cross-Origin Resource Sharing,跨域资源共享)、TCP、UDP、文件日志、API请求限流、请求转发以及nginx监控。

kong网关架构

API网关之Kong - 图2

1、kong核心基于OpenResty构建,实现了请求/响应的Lua处理化;
2、kong插件拦截请求/响应;
3、kong restful管理API提供了API/API消费者/插件的管理;
4、数据中心用于存储kong集群节点、API、消费者、插件等信息,目前提供了PostgreSQL和Cassandra支持;
5、kong集群中的节点通过gossip协议自动发现其他节点,当通过一个kong节点的管理API进行一些变更时也会通知其他节点。每个kong节点的配置信息是会缓存的,如插件,那么当在某一个Kong节点修改了插件配置时,需要通知其他节点配置的变更。

CentOS 7 安装kong网关

安装postgresql

请参考博文部署postgresql 12.3进行部署,直至可以访问到数据库:

API网关之Kong - 图3

当部署完成后,还需要做一些修改。

修改postgresql的访问权限
  1. $ vim /apps/usr/postgres/data/pg_hba.conf # 将下面改为你环境中的网段,以便可以远程登录到postgresql
  2. host all all 192.168.20.0/24 md5
  3. # 切换至postgresql的启动用户,以便重启数据库生效
  4. $ su - postgres
  5. $ pg_ctl restart # 重启数据库

创建kong用户及库
  1. # 创建kong系统用户,不允许登录到系统
  2. $ useradd -s /sbin/nologin kong
  3. # 创建用户及数据库并授权
  4. $ psql -U postgres # 登录到数据库中
  5. $ create user kong with password '123.com';
  6. $ create database kong owner kong;
  7. $ grant all privileges on database kong to kong;
  8. $ \q # 退出数据库

安装kong

  1. $ curl -Lo kong-2.6.0.rpm $(rpm --eval "https://download.konghq.com/gateway-2.x-centos-7/Packages/k/kong-2.6.0.el7.amd64.rpm")
  2. $ yum -y install kong-2.6.0.rpm
  3. $ cd /etc/kong
  4. mv kong.conf.default kong.conf
  5. vim /etc/kong/kong.conf # 定义连接数据库的基本参数,如IP、端口、用户名、密码、库
  6. pg_host = 192.168.20.10
  7. pg_port = 5432
  8. pg_timeout = 5000
  9. pg_user = kong
  10. pg_password = 123.com
  11. pg_database = kong
  12. # 同步数据库
  13. $ kong migrations bootstrap -c /etc/kong/kong.conf

同步数据库成功后,输出如下:

API网关之Kong - 图4

通过Navicat登录到数据库,可以看到下面这些表:

API网关之Kong - 图5

启动kong
  1. $ kong start -c /etc/kong/kong.conf # 启动kong
  2. $ kong stop # 停止命令
  3. $ kong reload # 重新加载kong
  4. $ curl http://127.0.0.1:8000 # 访问kong
  5. {"message":"no Route matched with those values"}
  6. # 输出上面的信息,是因为我们现在还没有注册服务
  7. # 请求 Admin 端口
  8. # 注意,考虑到安全性,Admin 端口默认只允许本机访问。
  9. $ curl http://127.0.0.1:8001
  10. {"plugins":{"enabled_in_cluster":[],"available_on_server":{... // 省略

kong端口作用
service port 作用
Proxy 8000 接收客户端的 HTTP 请求,并转发到后端的 Upstream
Proxy 8443 接收客户端的 HTTPS 请求,并转发到后端的 Upstream
Admin 8001 接收管理员的 HTTP 请求,进行 Kong 的管理
Admin 8444 接收管理员的 HTTPS 请求,进行 Kong 的管理

docker安装kong

安装docker

  1. # 设置 yum repository
  2. $ yum install -y yum-utils \
  3. device-mapper-persistent-data \
  4. lvm2
  5. yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  6. # 安装 docker
  7. $ yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
  8. # 修改 docker 镜像下载源
  9. $ [ -d /etc/docker ] || mkdir /etc/docker
  10. echo "{\"registry-mirrors\": [\"https://registry.cn-hangzhou.aliyuncs.com\",\"https://4grd6p3s.mirror.aliyuncs.com\"]}" >> /etc/docker/daemon.json
  11. # 修改docker的根目录(默认根目录为:/var/lib/docker),根据需要来确定是否要修改
  12. # 修改根目录,只是在启动命令后增加“--graph=/data/lib/docker”
  13. $ vim /usr/lib/systemd/system/docker.service # 跳转到14行,修改如下
  14. ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --graph=/data/lib/docker
  15. # 启动docker
  16. $ systemctl enable docker && systemctl start docker
  17. # 确认 docker 版本
  18. $ docker version

如果嫌弃默认的源比较慢,请自行修改docker镜像源。

创建docker网络

  1. $ docker network create kong-net

搭建数据库环境

Kong 目前使用Cassandra(Facebook开源的分布式的NoSQL数据库) 或者PostgreSql,你可以执行以下命令中的一个来选择你的Database。请注意定义网络--network=kong-net

下面两款数据库,二选一即可。

1、Cassandra容器:

  1. docker run -d --name kong-database \
  2. --network=kong-net \
  3. -p 9042:9042 \
  4. --restart always \
  5. cassandra:3

2、PostgreSQL容器:

  1. # 先别执行哦,看下去再说
  2. docker run -d --name kong-databasev \
  3. --network=kong-net \
  4. -p 5432:5432 \
  5. -e "POSTGRES_USER=kong" \
  6. -e "POSTGRES_DB=kong" \
  7. postgres:9.6 \

这里有个小问题。如果你使用的是PostgreSQL,想挂载卷持久化数据到宿主机。通过 -v 命令是不好用的。这里推荐你使用 docker volume create 命令来创建一个挂载。

  1. $ docker volume create kong-volume

然后上面的PostgreSQL就可以通过-v kong-volume:/var/lib/postgresql/data进行挂载了。

  1. $ docker run -d --name kong-database \
  2. --network=kong-net \
  3. -p 5432:5432 \
  4. -v kong-volume:/var/lib/postgresql/data \
  5. -e "POSTGRES_USER=kong" \
  6. -e "POSTGRES_DB=kong" \
  7. -e "POSTGRES_PASSWORD=kong" \
  8. --restart always \
  9. postgres:9.6

初始化数据库

我们使用 docker run --rm 来初始化数据库,该命令执行后会退出容器而保留内部的数据卷(volume)。

  1. docker run --rm \
  2. --network=kong-net \
  3. -e "KONG_DATABASE=postgres" \
  4. -e "KONG_PG_HOST=kong-database" \
  5. -e "KONG_PG_PASSWORD=kong" \
  6. -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  7. --restart always \
  8. kong:latest kong migrations bootstrap

navicat登录到数据库中可以看到如下表信息:

API网关之Kong - 图6

启动Kong容器

完成初始化或者迁移数据库后,我们就可以启动一个连接到数据库容器的Kong容器,请务必保证你的数据库容器启动状态,同时检查所有的环境参数 -e 是否是你定义的环境。

  1. docker run -d --name kong \
  2. --network=kong-net \
  3. -e "KONG_DATABASE=postgres" \
  4. -e "KONG_PG_HOST=kong-database" \
  5. -e "KONG_PG_PASSWORD=kong" \
  6. -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
  7. -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
  8. -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
  9. -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
  10. -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
  11. -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
  12. -p 8000:8000 \
  13. -p 8443:8443 \
  14. -p 8001:8001 \
  15. -p 8444:8444 \
  16. --restart always \
  17. kong:latest

验证

可通过 curl -i http://127.0.0.1:8001/或者浏览器调用 http://192.168.20.10:8001/ 来验证Kong Admin 是否联通 。

API网关之Kong - 图7

安装konga

由于konga现在已经不更新了,可能有些地方不兼容2.x的kong,不管了,感兴趣的可以装上看看,另外,由于konga的安装需要依赖其他东西,国内不容易下载,所以建议konga使用docker来运行。

Konga 主要是用 AngularJS 写的,运行于nodejs服务端。具有以下特性:

  • 管理所有Kong Admin API对象。
  • 支持从远程源(数据库,文件,API等)导入使用者。
  • 管理多个Kong节点。使用快照备份,还原和迁移Kong节点。
  • 使用运行状况检查监视节点和API状态。
  • 支持电子邮件和闲置通知。
  • 支持多用户。
  • 易于数据库集成(MySQL,postgresSQL,MongoDB,SQL Server)。

启动Konga数据库容器

如果机器没有安装docker,请按照上面的docker安装kong中,去安装docker环境。

  1. # 创建kong-net网络
  2. $ docker network create kong-net
  3. # 创建持久化卷
  4. $ docker volume create konga-postgresql
  5. # 运行konga所用的postgresql数据库
  6. $ docker run -d --name konga-database \
  7. --network=kong-net \
  8. -p 5433:5432 \
  9. -v konga-postgresql:/var/lib/postgresql/data \
  10. -e "POSTGRES_USER=konga" \
  11. -e "POSTGRES_DB=konga" \
  12. -e "POSTGRES_PASSWORD=konga" \
  13. --restart always \
  14. postgres:9.6

初始化Postgresql数据库

  1. $ docker run --rm --network=kong-net \
  2. pantsel/konga:latest \
  3. -c prepare -a postgres \
  4. -u postgres://konga:konga@konga-database:5432/konga
  5. -c: 执行的命令,这里我们执行的是prepare
  6. -a: adapter 简写 ,值可以是postgres 或者mysql
  7. -u: db url 数据库连接全称

看到如下输出,则表明初始化数据库成功:

API网关之Kong - 图8

Konga 还有一些可配置的环境参数:

变量 描述 默认值
HOST 将被Konga的服务器绑定的IP地址 - ‘0.0.0.0’
PORT 将被Konga的服务器使用的端口 - 1337
NODE_ENV 环境 production,development development
SSL_KEY_PATH 如果您想使用SSL,这将是.key文件的绝对路径。 必须同时设置SSL_KEY_PATHSSL_CRT_PATH - null
SSL_CRT_PATH 如果您想使用SSL,这将是.crt文件的绝对路径。 必须同时设置SSL_KEY_PATHSSL_CRT_PATH - null
KONGA_HOOK_TIMEOUT 在指定时间(ms)中,Konga等待启动任务完成后才退出进程的时间。 - 60000
DB_ADAPTER Konga将使用的数据库。 如果没有设置,将使用localDisk db。 mongo,mysql,postgres -
DB_URI 完整的db连接字符串。 取决于“DB_ADAPTER”。 如果设置了该参数,则不需要其他DB相关的变量。 - -
DB_HOST 如果没有指定’ DB_URI ‘,这就是数据库主机。 取决于“DB_ADAPTER”。 - localhost
DB_PORT 如果没有指定’ DB_URI ‘,这是数据库端口。 取决于“DB_ADAPTER”。 - DB default.
DB_USER 如果没有指定’ DB_URI ‘,这就是数据库用户。 取决于“DB_ADAPTER”。 - -
DB_PASSWORD 如果没有指定’ DB_URI ‘,这是数据库用户的密码。 取决于“DB_ADAPTER”。 - -
DB_DATABASE 如果没有指定’ DB_URI ‘,这是Konga的db的名称。 取决于“DB_ADAPTER”。 - konga_database
DB_PG_SCHEMA 如果使用postgres作为数据库,这是将使用的模式。 - public
KONGA_LOG_LEVEL 日志级别 silly,debug,info,warn,error debug on dev environment & warn on prod.
TOKEN_SECRET 将用于签署Konga发行的JWT代币的秘密 - -
NO_AUTH 运行Konga而不需要认证 true/false -
BASE_URL 定义加载Konga的基本URL或相对路径。 例:[www.example.com/konga] (http://www.example.com/konga) -
KONGA_SEED_USER_DATA_SOURCE_FILE 在第一次运行时的默认用户。 Docs. -
KONGA_SEED_KONG_NODE_DATA_SOURCE_FILE 在第一次运行时种子默认的Kong Admin API连接 Docs -

启动konga

  1. $ docker run -d -p 1337:1337 \
  2. --network kong-net \
  3. -e "DB_ADAPTER=postgres" \
  4. -e "DB_URI=postgres://konga:konga@konga-database:5432/konga" \
  5. -e "NODE_ENV=production" \
  6. -e "DB_PASSWORD=konga" \
  7. --name konga \
  8. --restart always \
  9. pantsel/konga

运行成功后,即可通过容器所在的宿主机的1337端口,登录到konga,如下:

API网关之Kong - 图9

首次登录需要注册一个管理员用户,如下:

API网关之Kong - 图10

登录后,需要先设置你的kong 管理接口的访问路径以及连接的名字,由于kong的管理接口默认只监听本机回环地址,所以需要先修改kong的管理端口监听地址,如下:

  1. $ vim /etc/kong/kong.conf
  2. admin_listen = 0.0.0.0:8001 reuseport backlog=16384, 0.0.0.0:8444 http2 ssl reuseport backlog=16384
  3. # 重启kong,以便生效
  4. $ kong stop && kong start -c /etc/kong/kong.conf

API网关之Kong - 图11

登录后,基本就是一些点点点的操作了,这里不做什么介绍。后续的操作,也是直接操作kong的API管理接口的。

API网关之Kong - 图12

kong快速开始

动态负载均衡实现

下面是一个简单的nginx负载均衡配置示例:

  1. upstream product-upstream {
  2. server 192.168.65.190:8866 weight=100;
  3. server 192.168.65.190:8867 weight=100;
  4. }
  5. server {
  6. listen 80;
  7. location /pms/ {
  8. proxy_pass http://product-upstream;
  9. }
  10. }
Kong 组件 说明
route route 对应路由,它负责匹配实际的请求,映射到 service 中 ,(对应nginx配置文件中的 location /pms/ )
service service 对应服务,可以直接指向一个 API 服务节点( host 参数设置为 ip + port),也可以指定一个 upstream实现负载均衡。简单来说,服务用于映射被转发的后端API 的节点集合。(对应nginx配置文件中的 proxy_pass http://product-upstream; )
upstream upstream 对应一组 API 节点,实现负载均衡(对应nginx配置文件中的 product-upstream { } )
target target 对应一个 API 节点(对应nginx配置文件中的 server 192.168.65.190:8866 weight=100;)

其工作流程图如下:

API网关之Kong - 图13

创建upstream
  1. # 创建一个名为ljz-product-upstream的upstream
  2. $ curl -X POST http://127.0.0.1:8001/upstreams --data "name=ljz-product-upstream"

创建targets

用 Kong Admin API /upstreams/{upstream}/targets ,创建 ljz-product-upstream 服务对应的 2 个 target。注意, {upstream} 路径参数为实际的 upstream 的名字。

两个target的接口自行配置,这里不展开配置。

  1. # 192.168.20.6:80 对应的 target
  2. $ curl -X POST http://127.0.0.1:8001/upstreams/ljz-product-upstream/targets --data "target=192.168.20.6:80" --data "weight=100"
  3. # 192.168.20.7:80 对应的 target
  4. $ curl -X POST http://127.0.0.1:8001/upstreams/ljz-product-upstream/targets --data "target=192.168.20.7:80" --data "weight=100"

创建service
  1. curl -X POST http://127.0.0.1:8001/services --data "name=ljz-product" --data "host=ljz-product-upstream" --data "path=/"

创建route
  1. curl -X POST http://127.0.0.1:8001/services/ljz-product/routes --data "name=ljz-product-route" --data "paths[]=/pms/"

访问测试
  1. $ for i in {1..2};do curl http://192.168.20.10:8000/pms/;done
  2. 192.168.20.6
  3. 192.168.20.7

kong的插件

kong提供了很多免费插件供我们使用,比如:基于Basic Auth和JWT的身份认证、限流配置、黑白名单等等:

API网关之Kong - 图14

这里不一一介绍了,如果需要可以结合如下资料进行配置: