KONG APIのメトリクス情報をPrometheusのexporterで取得

KongはOSSのAPI Gatewayツールです。リクエスト処理の振り分け管理や認証管理など複数のAPIへのアクセスを管理するために便利な機能を豊富に持っています。

今回は、このKongのメトリクス情報をPrometheusのExporterを使って収集する方法を紹介します。

Kongは公式からプラグインが公開されているので簡単に設定できます。

[公式ドキュメント](https://docs.konghq.com/hub/kong-inc/prometheus/)


## pluginの有効化

prometheusプラグインを有効化して使えるように設定します。prometheusプラグインはKONGのglobalプラグインとして設定もしくはKong上で管理されている特定のサービスに対して設定することが可能です。

KONGの管理用APIのURLに対して以下のようにPOSTリクエストを送付することで有効化されます。

```:globalに設定する方法

$ curl -XPOST http://localhost:8001/plugins -d "name=prometheus" -d "enabled=true" | jq
{
  "created_at": 1571917769,
  "consumer": null,
  "id": "7fb0ec16-da58-4816-a8a6-ad6caf3f2069",
  "service": null,
  "name": "prometheus",
  "config": {},
  "route": null,
  "run_on": "first",
  "tags": null,
  "protocols": [
    "http",
    "https"
  ],
  "enabled": true
}
```

```:個別のサービスのみ有効化する方法
$ curl -XPOST http://localhost:8001/services/<サービス名>/plugins -d "name=prometheus" | jq
{
  "created_at": 1571930853,
  "consumer": null,
  "id": "b9273dac-b35c-4865-be04-3f5774296b53",
  "service": {
    "id": "6aa2debf-ac42-4ff2-970c-56a8d38333a7"
  },
  "name": "prometheus",
  "config": {},
  "route": null,
  "run_on": "first",
  "tags": null,
  "protocols": [
    "http",
    "https"
  ],
  "enabled": true
}
```

## メトリクスの取得を試す

プラグインを有効化するだけで、後はKongの管理用APIに/metricsのパスが公開されるので、以下のようにメトリクス情報が取得できます。

以下は、globalに有効化した場合の例です。
service毎のメトリクスがすべて取れていることがわかります。

```
$ curl -XGET http://localhost:8001/metrics
# HELP kong_bandwidth Total bandwidth in bytes consumed per service in Kong
# TYPE kong_bandwidth counter
kong_bandwidth{type="egress",service="core-api"} 228785
kong_bandwidth{type="egress",service="login"} 1074
kong_bandwidth{type="egress",service="logout"} 3754
kong_bandwidth{type="ingress",service="core-api"} 66784
kong_bandwidth{type="ingress",service="login"} 883
kong_bandwidth{type="ingress",service="logout"} 5048
# HELP kong_datastore_reachable Datastore reachable from Kong, 0 is unreachable
# TYPE kong_datastore_reachable gauge
kong_datastore_reachable 1
# HELP kong_http_status HTTP status codes per service in Kong
# TYPE kong_http_status counter
kong_http_status{code="200",service="core-api"} 108
kong_http_status{code="200",service="login"} 2
kong_http_status{code="200",service="logout"} 2
kong_http_status{code="500",service="logout"} 6
# HELP kong_latency Latency added by Kong, total request time and upstream latency for each service in Kong
# TYPE kong_latency histogram
kong_latency_bucket{type="kong",service="core-api",le="00001.0"} 84
kong_latency_bucket{type="kong",service="core-api",le="00002.0"} 100
kong_latency_bucket{type="kong",service="core-api",le="00005.0"} 104
・・・略
kong_latency_bucket{type="kong",service="core-api",le="+Inf"} 108
kong_latency_bucket{type="kong",service="login",le="00001.0"} 1
kong_latency_bucket{type="kong",service="login",le="00002.0"} 1
kong_latency_bucket{type="kong",service="login",le="00005.0"} 1
kong_latency_bucket{type="kong",service="login",le="00007.0"} 1
・・・略
kong_latency_bucket{type="kong",service="login",le="+Inf"} 2
kong_latency_bucket{type="kong",service="logout",le="00001.0"} 8
kong_latency_bucket{type="kong",service="logout",le="00002.0"} 8
kong_latency_bucket{type="kong",service="logout",le="00005.0"} 8
・・・略
kong_latency_bucket{type="kong",service="logout",le="+Inf"} 8
kong_latency_bucket{type="request",service="core-api",le="00001.0"} 42
kong_latency_bucket{type="request",service="core-api",le="00002.0"} 49
・・・略
kong_latency_bucket{type="request",service="core-api",le="+Inf"} 108
kong_latency_bucket{type="request",service="login",le="00001.0"} 1
kong_latency_bucket{type="request",service="login",le="00002.0"} 1
・・・略
kong_latency_bucket{type="request",service="login",le="+Inf"} 2
kong_latency_bucket{type="request",service="logout",le="00001.0"} 1
kong_latency_bucket{type="request",service="logout",le="00002.0"} 1
・・・略
kong_latency_bucket{type="request",service="logout",le="+Inf"} 8
kong_latency_bucket{type="upstream",service="core-api",le="00005.0"} 1
kong_latency_bucket{type="upstream",service="core-api",le="00007.0"} 1
・・・略
kong_latency_bucket{type="upstream",service="core-api",le="60000.0"} 54
kong_latency_bucket{type="upstream",service="core-api",le="+Inf"} 54
kong_latency_bucket{type="upstream",service="login",le="00070.0"} 1
・・・略
kong_latency_bucket{type="upstream",service="login",le="+Inf"} 1
kong_latency_bucket{type="upstream",service="logout",le="00020.0"} 1
kong_latency_bucket{type="upstream",service="logout",le="00025.0"} 1
・・・略
kong_latency_bucket{type="upstream",service="logout",le="+Inf"} 6
kong_latency_count{type="kong",service="core-api"} 108
kong_latency_count{type="kong",service="login"} 2
kong_latency_count{type="kong",service="logout"} 8
kong_latency_count{type="request",service="core-api"} 108
kong_latency_count{type="request",service="login"} 2
kong_latency_count{type="request",service="logout"} 8
kong_latency_count{type="upstream",service="core-api"} 54
kong_latency_count{type="upstream",service="login"} 1
kong_latency_count{type="upstream",service="logout"} 6
kong_latency_sum{type="kong",service="core-api"} 133
kong_latency_sum{type="kong",service="login"} 36
kong_latency_sum{type="kong",service="logout"} 7
kong_latency_sum{type="request",service="core-api"} 20993
kong_latency_sum{type="request",service="login"} 107
kong_latency_sum{type="request",service="logout"} 3699
kong_latency_sum{type="upstream",service="core-api"} 20817
kong_latency_sum{type="upstream",service="login"} 69
kong_latency_sum{type="upstream",service="logout"} 3392
# HELP kong_nginx_http_current_connections Number of HTTP connections
# TYPE kong_nginx_http_current_connections gauge
kong_nginx_http_current_connections{state="accepted"} 21
kong_nginx_http_current_connections{state="active"} 6
kong_nginx_http_current_connections{state="handled"} 21
kong_nginx_http_current_connections{state="reading"} 0
kong_nginx_http_current_connections{state="total"} 328
kong_nginx_http_current_connections{state="waiting"} 5
kong_nginx_http_current_connections{state="writing"} 1
# HELP kong_nginx_metric_errors_total Number of nginx-lua-prometheus errors
# TYPE kong_nginx_metric_errors_total counter
kong_nginx_metric_errors_total 0
```


## サポートされているメトリクス一覧

以下のようなメトリクスが取れるようです。

|メトリック名|ラベル|値の型|概要|
|:----------|:----------|:----------|:----------|
|kong_bandwidth|{type="egress",service="<サービス名>"}|Counter|出力パケットバイト数総量|
|kong_bandwidth|{type="ingress",service="<サービス名>"}|Counter|入力パケットバイト数総量|
|kong_datastore_reachable|-|Gauge|Kong用データストア(cassandra,postgresql)との接続状況(0がNG,1がOK)|
|kong_http_status|{code="<ステータスコード>",service="<サービス名>"}|Counter|ステータスコード別のアクセス件数|
|kong_latency_bucket|{type="kong",service="<サービス名>",le="<上限値>"}|Histogram|Kongがリクエストを受けてプラグインの処理をして振り分けを行う処理時間がleで指定した時間以内だった件数。|
|kong_latency_bucket|{type="upstream",service="<サービス名>",le="<上限値>"}|Histogram|Kongがリクエストをupstream先に投げて結果を受信するまでの処理時間がleで指定した時間以内だった件数。|
|kong_latency_bucket|{type="request",service="<サービス名>",le="<上限値>"}|Histogram|Kongがリクエストをupstream先に投げて結果を受信するまでの処理時間がleで指定した時間以内だった件数。|
|kong_latency_count|{type=<カウント対象の処理箇所タイプ>,service="<サービス名>"|Histogram|該当のタイプのリクエストの受信件数合計|
|kong_latency_sum|{type=<カウント対象の処理箇所タイプ>,service="<サービス名>"|Histogram|該当のタイプのリクエストのレイテンシ合計時間|
|kong_nginx_http_current_connections|{state="<接続ステータス名>"}|Gauge|該当の接続ステータスのコネクション数|
|kong_nginx_metric_errors_total|-|Counter|Prometheus exporterのエラー件数|


## まとめ

プラグイン有効化するだけで簡単に取得可能で、個別のサービス毎の情報やレイテンシの時間毎の件数など幅広く取れるので活用できそうです。Kongの管理API用のエンドポイント経由でメトリクス収集することになるのでエンドポイントへのアクセス制限などは要注意かと思います。