Kong Gatewayを操作するためのAdmin APIはLuaのフレームワークであるLapisで実装されており、Lapisの作りに従ってAdmin APIにAPIエンドポイントを追加することが出来る。
エンドポイントの追加はカスタムプラグインの追加と同じ要領で追加できるので、実際にやってみる。
エンドポイントの基礎
Kongはkong.plugins.<plugin_name>.api
にエンドポイントの定義があれば検出して読み込む。
そのため、エンドポイントを追加する際はカスタムプラグインの要領でプラグインを追加し、その中にapi.lua
を用意して読み込ませることになる。
api.lua
の基本構造は以下となる。(Add endpoints to the Admin APIより抜粋)
return {
["<path>"] = {
schema = <schema>,
methods = {
before = function(self) ... end,
on_error = function(self) ... end,
GET = function(self) ... end,
PUT = function(self) ... end,
...
}
},
...
}
<path>
部分はAPIへのアクセスパスであり、例えば["/my_endpoint"]
と指定すると<Admin APIのURL>/my_endpoint
でアクセス出来るようになる。
パスの中に:consumers
のようにコロンを含んだ値がある場合、これは動的に変更する部分でアクセス時にself.params.<:を除いた名前>
に格納される(参考:Routes&URL Patterns)。
UUIDなど外部から変数を渡したい時に利用できる。
schema
についてはKongのエンティティのスキーマを指定し、フィールドの解析などに利用する。エンティティのスキーマはkong.db.<エンティティ名>.schema
のような形で指定する。
methods
の中は実際にAPIを呼び出した際の処理を記述する。
-
before
:前処理的なものを行うための呼び出し。全ての関数の前に実行される(指定は任意) -
on_error
:他の関数がエラーとなった時にエラーをハンドルする関数。指定しない場合はKongのデフォルトのエラーハンドリングが行われる。 -
GET等
:HTTPメソッドごとの処理を記述する。
ちなみにapi.lua
を持ってるKongの公式プラグインは数が少ないが、実装する際の参考になるので参考までにリンクを貼っておく。
検証
APIエンドポイントを含むプラグインのファイル構造についてはAdvanced plugin modulesに説明がある。
ファイル構造の説明に従うと以下のファイルが必要となる。
kong/plugins/<プラグイン名>/
├── api.lua
├── handler.lua
└── schema.lua
以降、それぞれのファイルを作成して検証する。
api.lua
ここでは以下の仕様のAPIエンドポイントをお試しで作ってみる。
-
/my_endpoint
- GETでアクセスすると接続元と接続先のIPと内部で持ってる文字列を返す
-
/my_endpoint/<任意の文字列>
- POSTでアクセスするとパスで指定した任意の文字列を返す
実装は以下のような感じ。
return {
["/my_endpoint"] = {
GET = function(self)
local client_ip = kong.client.get_ip()
local server_ip = ngx.var.server_addr
local msg = "Hello from Kong"
return kong.response.exit(200, {
message = msg,
ip = {
client_ip = client_ip,
server_ip = server_ip,
}
})
end,
},
["/my_endpoint/:my_endpoint"] = {
POST = function(self)
local msg = "params: " .. self.params.my_endpoint
return kong.response.exit(200, {
message = msg
})
end,
},
}
KongのPDKは問題なく呼び出せるので、IPの取得やレスポンスを返す時に利用している。
handler.luaとschema.luaの作成
handler.lua
とschema.lua
については今回はプラグインではないので、中身がないものを適当に用意しておけばOK。
local CustomEndpoints = {
PRIORITY = 1000,
VERSION = "1.0.0",
}
return CustomEndpoints
return {
name = "custom-endpoints",
fields = {
{ config = {
type = "record",
fields = {}
}}
}
}
導入
ここではKubernetes上のKong Gatewayに導入する。
なお検証環境はHybridモードで展開しているが、APIのエンドポイント追加はAdmin APIがいるControl Planeにのみ影響するため、作成したカスタムプラグインの導入はControl PlaneのみでOK。
またカスタムプラグインの導入方法はここではConfigMap
を利用する。
最初にConfigMap
を作成する。3つのluaファイルは./custom-endpoints
に置いているものとする。
kubectl create cm kong-plugin-endpoint \
--from-file=./custom-endpoints/ \
-n kong \
--dry-run=client -o yaml \
| kubectl apply -f -
次にControl PlaneのHelmのvalues.yaml
に以下を追記し、エンドポイントを追加したプラグインを読み込むようにする。
env:
plugins: bundled,custom-endpoints
plugins:
configMaps:
- name: kong-plugin-endpoints
pluginName: custom-endpoints
修正したvalues.yaml
を使ってControl Planeを再デプロイする。
helm upgrade -i kong-aws-cp kong/kong -f ./values.yaml -n kong --wait --debug
以上で追加したAPIエンドポイントが有効化された。
なお、カスタムプラグインと異なり、特にプラグインを有効化せずともエンドポイントは有効化されているので、プラグイン導入直後からアクセス出来るようになっている。
最初に/my_endpoint
の方にGETでアクセスしてみる。
$ curl -sX GET https://adminapi.mydomain.info/my_endpoint | jq .
{
"message": "Hello from Kong",
"ip": {
"client_ip": "192.168.34.31",
"server_ip": "192.168.53.23"
}
意図したレスポンスが取得できた。
次に/my_endpoint/<任意の文字列>
へのPOSTも確認する。
$ curl -sX POST https://adminapi.mydomain.info/my_endpoint/hoge | jq .
{
"message": "params: hoge"
}
こちらも確認できた。
まとめ
カスタムプラグインと同じ感覚でエンドポイントを追加できた。
カスタムプラグイン作成時に独自のエンドポイントを持たせて機能追加したい場合などには有用だと思う。
特にカスタムエンティティなどを実装し始めると使い道も増えそうなので、カスタムプラグイン実装時には覚えておくとよさそう。