开心编程
首发于开心编程
kong 网关插件快速开发指南

kong 网关插件快速开发指南

近期基于kong网关开发了几个小插件,感觉非常方便,而且流程简单明了。

kong插件项目概要

下载官方插件项目开发模版

git clone https://github.com/Kong/kong-plugin.git

目录结构如下:

$ tree
.
├── LICENSE
├── README.md
├── kong
│   └── plugins
│       └── myplugin
│           ├── handler.lua
│           └── schema.lua
├── kong-plugin-myplugin-0.1.0-1.rockspec
└── spec
    └── myplugin
        └── 01-access_spec.lua
5 directories, 6 files

kong插件主要有三个文件:

handler.lua 是包含插件逻辑处理相关代码。 schema.lua 包含插件的配置文件。 rockspec 文件是通过luarock安装时用的配置文件。

逻辑处理的代码根据openresty的不同处理阶段分成了不同的函数,根据插件的功能只需要在不同的函数中添加自己的业务逻辑。

kong插件项目实践

下面是开发一个最简单的灰度发布使用的流量分发插件的全部流程。

这个插件的功能非常简单:

根据http request头中的Authorization的值将流量分发到不同的后端服务器。

插件有两个配置项:pattern和upstream,如果Authorization的值匹配pattern,那么当前请求会被代理到相应的upstream中。

OK,开始!

代码开发

给插件起个温暖的名字,就叫huidu吧,修改模版项目中的目录名为huidu。

mv kong-plugin kong-plugin-huidu
cd kong-plugin-huidu/kong/plugins
mv myplugin huidu

修改schema.lua文件,添加插件配置代码。

local Errors = require "kong.dao.errors"

return {
  no_consumer = false, 
  -- 添加插件的配置项
  fields = {
    -- Describe your plugin's configuration's schema here.
    pattern = {type = "string", required = true},
    upstream = {type = "string", required = true}
  },
  -- 对输入的配置项进行合法性检查。
  self_check = function(schema, plugin_t, dao, is_updating)
    -- perform any custom verification
    local pattern = plugin_t.pattern
    if #pattern == 0 then
      return false, Errors.schema("pattern must not be null")
    end

    if pattern:sub(1, 1) ~= '^' then
      return false, Errors.schema("pattern must start with ^")
    end

    local upstream = plugin_t.upstream
    if #upstream == 0 then
      return false, Errors.schema("upstream must not be null")
    end

    return true
  end,
}

修改handler.lua文件,添加插件处理逻辑。

---[[ runs in the 'access_by_lua_block'
function plugin:access(plugin_conf)
  plugin.super.access(self)

  -- your custom code here
  local pattern = plugin_conf.pattern
  local token = kong.request.get_header("authorization")
  if token == nil then
    return 
  end
  -- 忽略大小写
  local matched = ngx.re.match(token, pattern, "joi")
  if matched then
    -- 设置upstream
    local ok, err = kong.service.set_upstream(plugin_conf.upstream)
    if not ok then
        kong.log.err(err)
        return
    end
    -- 匹配成功添加特定头部方便监控
    ngx.req.set_header("X-Kong-" .. plugin_name .. "-upstream", plugin_conf.upstream)
    ngx.req.set_header("X-Kong-" .. plugin_name .. "-pattern", plugin_conf.pattern)
  end    

end --]]

huidu插件的逻辑只需要在access阶段执行就可以,可以把多余的注释和代码删掉。

Done!

安装调试

假设kong的本地开发环境已经搭建好了,在调试阶段插件的安装采用手动指定目录的方式安装。

修改kong.conf文件,添加或者修改下面的配置项。

# bundled 表示kong内置的所有插件
plugins = bundled,huidu
# 添加huidu插件目录绝对路径
lua_package_path = /Users/youfu/kong-plugin-huidu/?.lua;./?.lua;./?/init.lua;;

修改完成后保存启动kong

kong start -c kong.conf --vv

在启动的输出日志中可以看到加载了刚刚配置的huidu插件。

使用web管理界面konga来配置插件。创建一个service,然后在service下安装当前插件。

安装后插件的配置如下:

{
  "created_at": 1544686913000,
  "config": {
    "upstream": "mocktest",
    "pattern": "^a"
  },
  "id": "87712e00-9ae8-49c0-9436-0d4d431d8523",
  "name": "huidu",
  "service_id": "a6dae27a-5f1a-478d-a0a1-f86475f0be7a",
  "enabled": true
}

配置项表示以a开头的全部流量走mocktest,如果没有匹配或者插件代码有错误,那么流量就走service本身配置的upstream。

其中mocktest配置的target为 mockbin.org:80

配置后的数据会保存在kong的后端数据库的plugins表中。

测试一把!

请求匹配的情况

curl -X GET 'http://127.0.0.1:8000/request?foo=bar&foo=baz' -H 'authorization: ApwPYjA8J1c9CVaFIBVkRyYV57k2bXfHFH9Jojs8HN2FfyEn39MzV1afG9'

响应如下:

{
  "headers": {
    "host": "mockbin.org”,
    ...
    "authorization": "ApwPYjA8J1c9CVaFIBVkRyYV57k2bXfHFH9Jojs8HN2FfyEn39MzV1afG9",
    "x-kong-huidu-upstream": "mocktest",
    "x-kong-huidu-pattern": "^a",
    "x-request-id": "e8a4eb07-66c4-434e-aa17-c5815c66820f",
  }
  ...
}

请求不匹配的情况

curl -X GET 'http://127.0.0.1:8000/request?foo=bar&foo=baz' -H 'authorization: XApwPYjA8J1c9CVaFIBVkRyYV57k2bXfHFH9Jojs8HN2FfyEn39MzV1afG9'

响应如下:

{"message":"failure to get a peer from the ring-balancer"}

可以看到插件已经生效。

正式环境部署

正式环境通过 luarocks 来部署。

编辑kong-plugin-huidu-0.1.0-1.rockspec文件,修改下面几个配置

package = "kong-plugin-huidu”
source = {
  url = "https://github.com/chenyoufu/kong-plugin-huidu.git",
  tag = "0.1.0"
}

下面是本地mac上安装的情况

$ luarocks make —-verbose

...
kong-plugin-huidu 0.1.0-1 is now installed in /usr/local/opt/kong (license: Apache 2.0)

mac 下安装完成后lua代码会安装到

/usr/local/opt/kong/share/lua/5.1/kong/plugins/huidu

linux会安装到这个目录下

/usr/local/share/lua/5.1/kong/plugins/huidu

这样就不需要在kong.conf中配置绝对路径了。

安装完成后需要运行kong restart命令才能生效。

后记

这个示例插件不涉及数据库以及其他复杂的操作,属于最简单的类型,建议在开发之前还是要通读官方的插件开发文档和kong本身自带的插件库的源代码。

基于这个流程基本上简单的功能的插件可以做到一天一个。

不建议网关的插件功能逻辑太复杂,简单够用就行。

当前示例插件代码 github.com/chenyoufu/ko

官方插件开发文档 docs.konghq.com/0.14.x/

编辑于 2018-12-14

文章被以下专栏收录