网关kong及其管理工具konga的初步使用小结

58次阅读

共计 4465 个字符,预计需要花费 12 分钟才能阅读完成。

一、背景

当前微服务网关的技术选型很多。常见的有 springcloud 系的 zuul1,gateway;也可以选择 nginx+lua 方案;或者直接使用 UI 集成度较高的 Kong。

本文记述了如何使用 docker 安装 kong 与 konga(一个开源的 Kong 管理 UI 项目),以及它们的简单使用和一些注意事项。

二、通过 docker 安装 kong(DB 模式)与 konga

2.1 通过 docker 安装 kong(DB 模式)

官方文档:https://docs.konghq.com/install/docker/

2020/07/03 kong 目前的最新版本 2.0.4,在做 websocket 转发时,与 tomcat 版本 9.0.29 有冲突,会导致 websocket 无法正常转发。因此这里我们选择安装 kong 的一个稍微低一点的版本2.0.0

# 如果不指定 subnet,创建的 network 默认使用 172.17 网段,可能会与实际网段发生冲突
docker network create --subnet=12.10.10.0/24 kong-net

# 拉取 postgres:9.6 作为 kong 的数据库
docker run -d --name kong-database \
               --network=kong-net \
               -p 5432:5432 \
               -e "POSTGRES_USER=kong" \
               -e "POSTGRES_DB=kong" \
               -e "POSTGRES_PASSWORD=kong" \
               postgres:9.6

# 拉取 kong:2.0.0 并生成初期数据
docker run --rm \
     --network=kong-net \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_PG_USER=kong" \
     -e "KONG_PG_PASSWORD=kong" \
     -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
     kong:2.0.0 kong migrations bootstrap

# 启动 kong
docker run -d --name kong \
     --network=kong-net \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_PG_USER=kong" \
     -e "KONG_PG_PASSWORD=kong" \
     -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
     -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
     -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
     -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
     -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
     -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
     -p 8000:8000 \
     -p 8443:8443 \
     -p 127.0.0.1:8001:8001 \
     -p 127.0.0.1:8444:8444 \
     kong:2.0.0

# 启动后在宿主机访问 8000 与 8001 端口
curl http://localhost:8000
curl http://localhost:8001

注意,kong 的四个端口作用:

  1. 8000 与 8443 分别用于对 http 和 https 的代理访问;
  2. 8001 与 8444 分别是 http 与 https 的管理 API 访问端口,因为管理 API 不宜对外暴露,所以在挂载端口时,明确了127.0.0.1,即只有宿主机本地能够访问。

2.2 通过 docker 安装 konga

konga 安装直接默认最新版本(目前是 0.14.9)。

# 拉取 pantsel/konga,并创建数据库 konga_db。# 注意这里直接使用刚刚为了 kong 创建的 PG 数据库实例,并使用 kong 的 DB 用户,# 注意这里 postgresql 连接的写法:#  postgresql://< 用户 >:< 密码 >@<PG_Host>:<PG_Port>/<database>

docker run --rm \
 --network=kong-net \
 pantsel/konga -c prepare -a postgres -u postgresql://kong:kong@kong-database:5432/konga_db

# 启动 konga
docker run -p 1337:1337 \
             --network=kong-net \
             -e "DB_ADAPTER=postgres" \
             -e "DB_HOST=kong-database" \
             -e "DB_USER=kong" \
             -e "DB_PASSWORD=kong" \
             -e "DB_DATABASE=konga_db" \
             -e "KONGA_HOOK_TIMEOUT=120000" \
             -e "NODE_ENV=production" \
             --name konga \
             pantsel/konga

konga 从命令行启动后不会退出,但 docker 容器已经正常启动。建议后面通过 portainer 来重启该容器。(portainer 是一个开源的 docker 管理工具,本身直接拉取 docker 运行即可。)

三、首次访问 konga 并配置 kong 管理 API 连接

观察 docker 容器状况,确认 kong-databasekongkonga 三个容器全部成功启动后,访问地址:http://localhost:1337

首次访问会让你创建 konga 的管理员账户,然后登录,然后创建到 kong 管理 API 的连接,过程如下:

  1. 创建 gonga 管理员账户
  2. 用管理员账户登录
  3. 创建到 kong 管理 API 的连接(连接地址:http://kong:8001/)
  4. 激活该连接

注意上面第三步,创建到 kong 管理 API 的连接时,因为前面启动 kong 时,8001 端口只挂载在 12.0.0.1:8001 上,因此只有宿主机自己可以访问。这里在 konga 容器内访问 kong 时,就必须通过网络 kong-net 中的容器 ip 或 hostname 访问。因此这里填写的是 kong 容器的 name:kong,而不是宿主机 IP。

四、添加路由规则

此时 konga 的界面还是比较简陋的,功能也不多。dashbord 只能看到一些总体的统计信息,看不到具体每个目标服务的访问量。

如果需要添加其他功能,需要通过 PLUGINS 去一个一个添加,具体尚未研究。

但动态添加路由规则是完全没有问题的。这里主要介绍如何添加路由规则。

kong 添加路由规则主要分为两步:

  1. 添加要访问的目标服务。
  2. 在已经添加的 Sevice 里添加网关接收到的请求的过滤规则,即把什么样的请求转发给该 Service。

4.1 添加目标服务

通过左侧导航菜单SERVICES,添加目标服务ADD NEW SERVICE,一般配置项目如下:

  • Name: 通常写目标服务名。
  • Protocol: http 或 https
  • Host: 目标服务的 Host
  • Port: 目标服务的端口
  • Path: 目标服务访问根路径,没有特殊情况就填写/

注意 Path 不要空着,没有指定 Path 就填上 / 表示服务根目录。

其他项目一般保持默认即可。

4.2 为目标服务添加路由

通过左侧导航菜单SERVICES,点击一个目标服务,选择它的Routes,并点击ADD ROUTE,配置如下:

路由一般配置项:

  • Name : 路由名称。
  • 其他 : 略

路由过滤条件配置项:

  • Hosts : 网关所在服务器有多个域名时,可以根据请求的域名做过滤条件;一般不填。
  • Paths : 一般都是在 Paths 做过滤条件。Kong 通过 PCRE(与 Perl 兼容的正则表达式)支持 paths 字段的正则表达式模式匹配。因此可以同时使用 path 前缀和正则表达式匹配路由。注意每写一个 Path 过滤条件就要回车(一定要回车,不然 konga 认为你没有输入。。。),多个 Path 过滤条件就写多个。
  • Methods : 将 HTTP methods 作为过滤条件,填入 POSTGET 等。
  • Headers : 需要通过 Header 信息作为过滤条件时填写。直接将 header 信息的 属性: 值 填入即可,注意回车。例如:Connection: keep-alive
  • Protocols : 将协议作为过滤条件,http 或 https。
  • 其他 : 略

注意:

  1. Hosts,Paths,Methods 三者最少需要配置一个。
  2. 大部分情况下,我们都是根据 Path 来做转发的过滤条件的,因此不同目标系统如果某些资源访问 Path 相同的话,会导致不同目标服务的路由规则冲突。

关于 Path 冲突,建议如下:

  1. 尽量确保不同的目标服务具有各自统一的资源访问根目录。即每个目标服务都有自己统一且唯一的 Path 前缀。如,某个目标服务的 Path 都是 /service1/*,静态资源用/service1/static/*,API 用/service1/api/* 等等。
  2. 没有统一访问根目录的目标服务,尽量保证各自的路径满足不同的正则表达式。比如 Path 的中间某一层统一为能识别具体服务的字符串。如,某个目标服务的 Path 都满足 /*/service2/*,静态资源用/static/service2/*,API 用/api/service2/* 等等。
  3. 前面两点都不能满足的话,考虑加入其他过滤条件(Hosts,Headers 等),例如,网关有多个域名,当请求用域名 1 访问时,路由到目标服务 1,用域名 2 访问时,路由到目标服务 2。

路由附加操作配置项:

  • Strip Path : 满足条件的请求在转发给目标服务时,是否将 Paths 中匹配的部分从访问路径中去掉。
  • 其他 : 略

五、关于 websocket 的转发

kong 是天生支持 websocket 转发的,关于这一点,可以参考官网的说明:https://docs.konghq.com/2.0.x/proxy/#proxy-websocket-traffic

但当 kong 位于客户端与服务端之间时,kong 的某些版本与服务器的版本可能会有冲突,导致 websocket 转发发生异常。

例如,目前 kong 的最新版本 (2.0.4) 作为网关,如果目标服务是 tomcat 的 9.0.29 版本,那么会发生以下现象:

  • 客户端在试图连接 websocket 时,发生 Error during WebSocket handshake: 'Upgrade' header is missing 错误。
  • 位于 kong 后面的服务端 tomcat 能够接收到转发的 websocket 连接请求并成功建立连接,但紧接着就会发生 java.io.EOFException 异常,导致连接被关闭。

具体原因在 kong 的 issue #5714 (https://github.com/Kong/kong/issues/5714) 中有讨论,该 issue 已被关闭但实际上问题并未解决。。。倒是其中一个回答提到,如果将 kong 版本回退到 2.0.0 则该问题不会发生。

正文完
 0