Kong - 插件開發


環境:

kong 是用 rpm 方式安裝的。 LuaRocks as it is installed along with Kong

[root@localhost kong-plugin-huidu-master]# luarocks --version
/usr/local/bin/luarocks 3.7.0

[root@localhost kong-plugin-huidu-master]# kong version
2.4.1

[root@localhost kong-plugin-huidu-master]# luarocks path --lr-path
/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua

一、下載Kong插件開發模板

下載官方插件開發模板:

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

kong插件主要有三個文件:

handler.lua 是包含插件邏輯處理相關代碼。 schema.lua 包含插件的配置文件。 rockspec 文件是通過luarock安裝時用的配置文件。
邏輯處理的代碼根據openresty的不同處理階段分成了不同的函數,根據插件的功能只需要在不同的函數中添加自己的業務邏輯

二、kong插件開發實踐

下面是開發一個最簡單的灰度發布使用的流量分發插件的全部流程。
這個插件的功能非常簡單:
根據http request頭中的Authorization的值將流量分發到不同的后端服務器。
插件有兩個配置項:pattern和upstream,如果Authorization的值匹配pattern,那么當前請求會被代理到相應的upstream中。

2.1、代碼開發

給插件起個溫暖的名字,就叫huidu吧,修改模版項目中的目錄名為huidu。

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

修改schema.lua文件,添加插件配置代碼:

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

-- Grab pluginname from module name
local plugin_name = ({...})[1]:match("^kong%.plugins%.([^%.]+)")

local schema = {
  name = plugin_name,
  fields = {
    -- the 'fields' array is the top-level entry with fields defined by Kong
    { consumer = typedefs.no_consumer },  -- this plugin cannot be configured on a consumer (typical for auth plugins)
    { protocols = typedefs.protocols_http },
    { config = {
        -- The 'config' record is the custom part of the plugin schema
        type = "record",
        fields = {
          -- a standard defined field (typedef), with some customizations
          { pattern = {type = "string", required = true, default = "^a" } },
          { upstream = {type = "string", required = true, default = "hello" } } -- adding a constraint for the value
        },
        entity_checks = {
          -- add some validation rules across fields
          -- the following is silly because it is always true, since they are both required
          { at_least_one_of = { "pattern", "upstream" }, },
          -- We specify that both header-names cannot be the same
          { distinct = { "pattern", "upstream"} },
        },
      },
    },
  },
}

return schema

修改handler.lua文件,添加插件處理邏輯:

-- If you're not sure your plugin is executing, uncomment the line below and restart Kong
-- then it will throw an error which indicates the plugin is being loaded at least.

--assert(ngx.get_phase() == "timer", "The world is coming to an end!")


-- Grab pluginname from module name
local plugin_name = ({...})[1]:match("^kong%.plugins%.([^%.]+)")

-- load the base plugin object and create a subclass
local plugin = require("kong.plugins.base_plugin"):extend()

-- constructor
function plugin:new()
  plugin.super.new(self, plugin_name)
  
  -- do initialization here, runs in the 'init_by_lua_block', before worker processes are forked

end

---[[ 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 --]]

-- set the plugin priority, which determines plugin execution order
plugin.PRIORITY = 1000

-- return our plugin object
return plugin

huidu插件的邏輯只需要在access階段執行就可以,可以把多余的注釋和代碼刪掉。

2.4、安裝調試

修改kong.conf文件,添加或者修改下面的配置項。注意 插件名稱和安裝時的名稱一致

插件一般通過 luarocks 來安裝,在插件根目錄下執行:

luarocks make 

此編譯命令依靠文件 rockspec,

ackage = "kong-plugin-huidu"  -- TODO: rename, must match the info in the filename of this rockspec!
                                  -- as a convention; stick to the prefix: `kong-plugin-`
version = "0.1.0-1"               -- TODO: renumber, must match the info in the filename of this rockspec!
-- The version '0.1.0' is the source code version, the trailing '1' is the version of this rockspec.
-- whenever the source version changes, the rockspec should be reset to 1. The rockspec version is only
-- updated (incremented) when this file changes, but the source remains the same.

-- TODO: This is the name to set in the Kong configuration `plugins` setting.
-- Here we extract it from the package name.
local pluginName = package:match("^kong%-plugin%-(.+)$")  -- "myPlugin"

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

description = {
  summary = "Kong is a scalable and customizable API Management Layer built on top of Nginx.",
  homepage = "http://getkong.org",
  license = "Apache 2.0"
}

dependencies = {
}

build = {
  type = "builtin",
  modules = {
    -- TODO: add any additional files that the plugin consists of
    ["kong.plugins."..pluginName..".handler"] = "kong/plugins/"..pluginName.."/handler.lua",
    ["kong.plugins."..pluginName..".schema"] = "kong/plugins/"..pluginName.."/schema.lua",
  }
}
View Code

安裝成功后,插件安裝在了luarocks目錄kong->plugins 。然后重啟kong

kong start -c kong.conf --vv

從Konga可以看到插件安裝成功了:

注意:另外一種安裝方式 直接修改文件方法參考:

所有插件在 /usr/local/share/lua/5.1/kong/constants.lua

插件具體位置在/usr/local/share/lua/5.1/kong/plugins

 

 直接復制插件handler\schema到plugins目錄,然后加到bundle里面,重啟kong即可。

 參考:https://www.freesion.com/article/33481210612/

2.5、測試

使用web管理界面konga來配置插件。創建一個service,然后在service下安裝當前插件

配置項表示以a開頭的全部流量走mocktest,如果沒有匹配或者插件代碼有錯誤,那么流量就走service本身配置的upstream。

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

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

不返回信息

如果插件中有語法錯誤,重啟會失敗,可以查閱日志找問題,日志位置在/usr/local/kong/logs/error.log

 

注意:

kong 插件只要編譯了,就會執行對應的生命周期,不論kong是否添加改插件。 

 

參考:

https://docs.konghq.com/gateway-oss/0.14.x/plugin-development/custom-logic/

https://docs.konghq.com/gateway-oss/0.14.x/pdk/

https://github.com/Kong/kong/blob/master/kong/plugins/tcp-log/handler.lua

https://www.jianshu.com/p/3e726106dca9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM