通常コンテナ環境でKong Gatewayのカスタムプラグインを作る場合、Kong Gatewayのイメージをベースイメージとしてdocker buildでコンテナイメージを再作成する。
ただし、Kubernetes環境でかつ少量のLuaでプラグインを作成する場合はConfigMap
かSecret
で代用することも出来る。
今回の記事はこちらの公式手順を参考にConfigMap
でカスタムプラグインを実装する方法を確認した時のメモとなる。
プラグインの作成
ここではお試しとして以下の仕様のプラグインを作成する。
- リクエストを受け取ると一定時間sleepする
- sleep時間は外部からパラメータで指定することが出来る
- なるべくどのプラグインよりも早く動く
ファイル構造は公式に従って以下の構造とする。
/sleep
├── handler.lua 処理本体
└── schema.lua パラメータ設定(スキーマ)
なお、ファイル構造については公式で指定があり、この2つは必須となる。
中身は以下のように作った
local RequestSleep = {
PRIORITY = 10000,
VERSION = "0.0.1",
}
function RequestSleep:access(conf)
ngx.log(ngx.NOTICE, "plugin.access called")
for k, v in pairs(conf) do
ngx.log(ngx.NOTICE, "conf[" .. tostring(k) .. "] = " .. tostring(v))
end
local sleep_time = conf.sleep_time
if sleep_time and sleep_time > 0 then
ngx.log(ngx.NOTICE, "Sleeping for " .. sleep_time .. " seconds")
ngx.sleep(sleep_time)
ngx.log(ngx.NOTICE, "Woke up after sleeping for " .. sleep_time .. " seconds")
else
ngx.log(ngx.NOTICE, "No valid sleep_time provided, proceeding without sleep")
end
end
return RequestSleep
コードについて少し補足する。
優先度(PRIORITY
)はPlugin Ordering Referenceよりexit-transformerより高い優先度である10000とした。これでほとんどのプラグインよりは早く動く。
:access
についてはこちらにあるようにリクエストをupstream(転送先サービス)に転送する前に引っ掛けて処理するためのものとなる。
ngx
についてはlua-nginx-moduleであり、Kongはnginxで動いているので特に呼び出しとかしなくても使えるようになっている。
処理としては最初にconf
の中身を表示し、パラメータチェックをした後にsleepするようにしている。
内部の動きを確認するためにngx.log
を呼びまくっているが、シンプルにするならlog系は全て削除してOK。
schema.luaは以下。
return {
name = "sleep",
fields = {
{ config = {
type = "record",
fields = {
{ sleep_time = { type = "integer", default = 0, }, },
},
}, },
}
}
schema.luaの仕様はこちらを参照いただくとしてここでは詳細は特に触れない。
sleep_timeというパラメータを整数型で定義しているだけである。
プラグインのインストール
以下の手順で行う。
-
ConfigMap
の作成 - Kong Gatewayにプラグイン(
ConfigMap
)を認識させる
最初にConfigMap
を作成する。展開先はKong Gatewayと同じNamespaceにする。
kubectl create cm kong-plugin-sleep --from-file=./sleep -n kong
次にKong Gatewayをデプロイし直す。
env.plugins
に作成したプラグイン名を追加し、plugins.configMaps
に作成したConfigMap
からプラグインを認識するよう設定を追加する。
:(省略)
env:
plugins: bundled,openid-connect,sleep
:(省略)
plugins:
configMaps:
- name: kong-plugin-sleep
pluginName: sleep
編集したvalues.yamlを使ってupdateし設定を反映する。
helm upgrade -i kong kong/kong --namespace kong --values kong-values.yaml --wait --debug
設定が反映されるとKong ManagerのPlugin検索から作成したPluginが見えるようになる。
動作確認
前回「Kong Gatewayの通信の遅延箇所をJaegerで確認する」という記事の中でnginxをユーザサービスに見立ててJaegerでトレーシングを行ったが、同じ環境にこのプラグインを適用し、以下を確認してみたい。
- カスタムプラグインの仕様通り遅延が起こせるか
- 発生した遅延をJaegerで確認できるか
Kong Managerにアクセスし、左サイドバーのRoutes
-><nginxのRoute>
を選択し、Plugins
からNew Plugin
を選択する。
sleep
で検索してカスタムプラグインを選択し、以下の設定を行って保存する。
-
Protocols
:http, https -
Sleep Time
:5
これで設定は完了となる。
コマンドを叩いて遅延が効くか確認する。時間を測るためにtimeコマンドを使って実行する。
time curl -X GET -k -i https://nginx.hogehoge.info
結果は以下のようになった。
real 0m5.589s
user 0m0.010s
sys 0m0.013s
プラグインによる5秒の遅延が効いているようだ。
Jaegerのトレースを見てみる。
作成したカスタムプラグインが最初に動き、かつここだけで5秒かかっていることが確認できた。
最後にログも見てみる。
$ kubectl logs -n kong kong-kong-5d667684f8-vxlzw -c proxy | grep notice
:(省略)
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:10: conf[__key__] = plugins:sleep:da7eea27-3de1-552b-8f18-c038a617fc6e::::d83c6514-b5ed-462a-86e1-f3c8c577a324, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:10: conf[__seq__] = 13, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:10: conf[route_id] = da7eea27-3de1-552b-8f18-c038a617fc6e, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:10: conf[__plugin_id] = 5601f1ab-939b-4810-9c36-bf9793a250f9, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:10: conf[sleep_time] = 5, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:14 [notice] 2437#0: *3169 [lua] handler.lua:16: Sleeping for 5 seconds, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
2024/05/28 00:07:19 [notice] 2437#0: *3169 [lua] handler.lua:18: Woke up after sleeping for 5 seconds, client: 192.168.59.131, server: kong, request: "GET / HTTP/1.1", host: "nginx.hogehoge.info", request_id: "6636b272c181be016d61490e1c34a106"
意図したログが表示されていること、デバッグ情報として入力した値(sleep_time)やRouteのIDなども拾えることなどが確認できた。
所感
docker buildをやってしまうとKong GatewayのVersion Up毎にイメージの作り直しが発生するが、このやり方であればイメージの作り直しが不要なのでメンテが楽である。
ただLuaのパッケージを追加したいとかもう少し複雑なことをしたい場合はあまり向いていなさそうなので、用途が限られる点は気をつけておきたい。