最近在做 Kong 相关插件的开发,之前在本地使用 Docker 跑 Kong 的方式来进行。这次想尝试一下直接在 Linux 开发机上安装 Kong,然后在本地通过 VSCode 的 Remote Development 连到服务器上进行开发。本文介绍 Linux 环境下 Kong 插件开发、使用 LuaRocks 来安装插件。这种方式相对容器跑 Kong 的方式,日志查看更加方便,插件开发过程中需要不断修改,修改之后也好重新加载。
为了方便,本文中 Kong 周边的服务如数据库、管理 UI 仍然采用 Docker 方式安装。

Linux 安装 Kong

安装数据库

选择 PostgreSQL 数据库。使用 Docker 来跑一个 PostgreSQL 数据库。

docker run -d --name kong-database \
               -p 5432:5432 \
               -e "POSTGRES_USER=kong" \
               -e "POSTGRES_DB=kong" \
               -e "POSTGRES_PASSWORD=kong" \
               postgres:9.6

安装 Kong

在官网根据自己的发行版选择合适的安装指南,比如我是用的 Debian。直接根据 https://docs.konghq.com/install/debian/ 进行安装。
安装成功之后默认是没有启动的。

准备配置文件

可以参考 /etc/kong/kong.conf.default 配置文件模板,根据需要将一些只进行修改。
/home/bizz/kong/kong.conf

prefix = /home/bizz/var/kong/       # Working directory. Equivalent to Nginx's
proxy_access_log = /home/bizz/var/log/kong_access.log       # Path for proxy port request access
proxy_error_log = /home/bizz/var/log/kong_error.log         # Path for proxy port request error
admin_access_log = /home/bizz/var/log/kong_admin_access.log # Path for Admin API request access
admin_error_log = /home/bizz/var/log/kong_admin_error.log         # Path for Admin API request error
admin_listen = 127.0.0.1:8001     # Address and port on which Kong will expose
database = postgres             # Determines which of PostgreSQL or Cassandra
pg_host = localhost          # The PostgreSQL host to connect to.
pg_port = 5432                  # The port to connect to.
pg_user = kong                  # The username to authenticate if required.
pg_password = kong            # The password to authenticate if required.
pg_database = kong              # The database name to connect to.

初始化数据库

kong migrations bootstrap /home/bizz/kong/kong.conf

启动Kong

kong start -c /home/bizz/kong/kong.conf
curl http://localhost:8001 可以验证是否安装成功。

安装 Konga

管理 Kong 可以直接使用 Admin API,也有基于 Admin API 实现 GUI 管理工具。
Konga 的一个比较活跃的第三方开源 GUI 工具。由于需要存储添加的一些 Kong 节点的配置,所以需要提供一个数据库,可以选择 MySQL 或者 PostgreSQL。
同样需要先对数据库进行初始化。

# docker run --rm pantsel/konga:latest -c prepare -a {{adapter}} -u {{connection-uri}}
docker run --rm pantsel/konga:latest -c prepare -a mysql -u mysql://db_uer:passwd@mysql_host/konga_test

因为需要连接宿主上的 Kong 管理端口,这里采用 host 模式的网络。

docker run -p 1337:1337 
--net=host 
-e "TOKEN_SECRET=testtesst" 
-e "DB_ADAPTER=mysql" 
-e "DB_URI=mysql://db_uer:passwd@mysql_host/konga_test" 
-e "NODE_ENV=production" 
--name konga 
pantsel/konga

安装成功之后即可在上面添加 Kong 节点进行管理。

Kong 插件

Kong 是基于 OpenResty 的,在 Nginx 中集成了 Lua 脚本的功能。我们可以编写符合 Kong 约定的 Lua 模块,从而与请求/响应对象或流交互,以实现任意逻辑。

VSCode 远程开发

因为我们需要将插件安装到跑在远端 Linux 上,虽然我们可以通过本地写完然后通过 scp 或者 rsync 之类的工具同步过去,但是在开发中避免不了频繁修改,每次修改都去同步一下文件的方式感觉有点 lowlow 的。VSCode 19 年开始就提供了远程开发的插件,因此这种方式还算比较优雅。
因为原先我本地就可以直接 ssh 到远程服务器,因此配置过程比较简单。详细流程可以参考 Remote Development using SSH
image.png

image.png

在左下角的状态栏可以看到已经连接到远程机器了,我们直接在我远端的家目录下创建 kong-plugins 目录。
image.png

插件开发

我们开发一个简单的插件 Demo,对每个请求添加一个 uuid 叫 my-uuid,添加的 header 我们可以自己在插件的配置中定义(Kong 实际已经自带了一个类似的插件,这里为了演示,我们自己实现一个)。

文件结构

根据插件类型不同,分为 2 种。

  • 基本插件结构

    simple-plugin
    ├── handler.lua
    └── schema.lua
    • handler.lua 插件的核心,可以定义一些在请求的各个声明周期运行的函数。
    • schema.lua 插件的一些配置信息。比如可以配置哪些字段,默认值,校验之类的。
  • 高级插件结构

如果需要更加深度的和 kong 进行集成,比如在 kong 的数据库中有自己的表,在 Admin API 中有自己的管理断点等等。还有一些其他可以定义的文件。

complete-plugin
├── api.lua
├── daos.lua
├── handler.lua
├── migrations
│   ├── cassandra.lua
│   └── postgres.lua
└── schema.lua

我们的插件比较简单,只要定义 handler.lua 和 schema.lua。

自定义插件

handler.lua

local uuid = require "kong.tools.utils".uuid

local MyUUIDHandler = {}

MyUUIDHandler.PRIORITY = 1
MyUUIDHandler.VERSION = "0.1.0"


function MyUUIDHandler:access(conf)
  -- Set header for upstream
  local trace_id = kong.request.get_header(conf.header_name)
  if not trace_id or trace_id == "" then
    -- Generate the header value
    trace_id = uuid()
    if trace_id then
      kong.service.request.set_header(conf.header_name, trace_id)
    end
  end

  kong.ctx.plugin.trace_id = trace_id
end


function MyUUIDHandler:header_filter(conf)
  local trace_id = kong.ctx.plugin.trace_id or
                         kong.request.get_header(conf.header_name)

  if not trace_id or trace_id == "" then
    trace_id = uuid()
  end

  kong.response.set_header(conf.header_name, trace_id)
end


return MyUUIDHandler

schema.lua

local typedefs = require "kong.db.schema.typedefs"

return {
    name = "my-uuid",
    fields = {
        { 
            consumer = typedefs.no_consumer 
        },
        {
            config = {
                type = "record",
                fields = {
                    { header_name = { type = "string", required = true }, },
                },
            },
        },
    },
}

插件安装

推荐使用Lua模块的包管理器 LuaRocks, 即使我们不需要将包上传到 LuaRocks 官方源也可以使用其来管理插件。

使用 luarocks 安装插件

创建一个rockspec文件,用来指定包的内容,包含了哪些文件以及版本。
kong-plugin-my-uuid-0.1.0-1.rockspec

package = "kong-plugin-my-uuid"

version = "0.1.0-1" 
local pluginName = package:match("^kong%-plugin%-(.+)$")

supported_platforms = {"linux", "macosx"}
source = {
  url = "https://gitxxxxxx.com/xxxx/kong-plugins",
  tag = "0.1.0"
}

description = {
  summary = "Add uuid in request/response header"
}

dependencies = {}

build = {
  type = "builtin",
  modules = {
    ["kong.plugins."..pluginName..".handler"] = pluginName.."/handler.lua",
    ["kong.plugins."..pluginName..".schema"] = pluginName.."/schema.lua",
  }
}

使用 luarocks make 指定插件包的 spec 文件,本地安装。
image.png

加载插件

将自定义插件的名称添加到 Kong 配置文件中的插件参数中,重新启动 Kong。
image.png

启用插件

首先我们新建一个API 服务叫 mockbin,上游地址是 http://mockbin.org/bin/xxxxx-79b5-4eb9-9558-c3bc57b7bf48。网关上绑定其路由为 /mockbin/v1
这样我们访问 http://${网关 IP}:${端口}/mockbin/v1 就可以直接被代理到上游的服务 http://mockbin.org//bin/xxxxx-79b5-4eb9-9558-c3bc57b7bf48 上。
my-uuid 插件绑定到该服务中,并且设置 uuid 的 header 名称为 my-trace-id
image.png

请求网关地址 http://${网关 IP}:${端口}/mockbin/v1/instances
image.png


Guixian
6 声望1 粉丝

引用和评论

0 条评论