Kong Gateway を触ってみる

## この記事の目的

[公式ドキュメント](https://docs.konghq.com/gateway/3.5.x/)に沿って Kong Gateway の動作確認を行ったので，こちらの記事に残します．

:::note info
こちらの記事を参考にして Kong Gateway (OSS) および Kong Gateway (Free) の環境を構築することができます．
:::

## 構成

![Kong-Architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/2885e256-7f1e-c27c-1054-db774bb1c95c.png)

## Kong が提供するサービスの紹介

### [Kong Gateway](https://docs.konghq.com/gateway/latest/)

![Kong.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/3d8c06af-54d0-ecab-1c2a-82566d3492a1.png)

> Kong Gateway is a lightweight, fast, and flexible cloud-native API gateway. An API gateway is a reverse proxy that lets you manage, configure, and route requests to your APIs.

Kong Gateway はクラウドネイティブな API ゲートウェイです．
[Kong](https://konghq.com/company/about-us) の中心的なサービスであり，以下を支援する機能が提供されています．

- ワークフロー，GitOps の活用
- マイクロサービス化，分散アーキテクチャの実現
- API 開発エコシステムの提供
- API 関連の異常・脅威の検知補助
- API とサービスの保護

Kong Gateway を利用する方法は **1. Kong Konnect**, **2. Self-managed** の 2 パターンあります．

**1. [Kong Konnect](https://docs.konghq.com/konnect/)**

Kong Konnect は [Kong による有料の SaaS サービス](https://konghq.com/pricing)で Plus と Enterprise の 2 種類のプランから選択して利用できます．

Plus では Konnect プラットフォームを提供して API ゲートウェイを素早く準備するだけでなく，カスタマイズ可能な API 開発ポータルやプラグイン拡張，監視基盤などが利用できます．

Enterprise は Plus に加えてテクニカルサポートやボリュームディスカウントなどが入ります．

**2. Self-managed**

Self-managed では Kong Gateway (OSS), Kong Gateway (Free/Enterprise) から選択することになります． 

Kong Gateway (OSS) は [Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE)，Kong Gateway (Free/Enterprise) は [Kong Software License Agreement](https://kong-mwe-web-assets.s3-accelerate.amazonaws.com/wp-content/uploads/2021/04/Kong-Software-License-Agreement-20-April-2021.pdf) で運用されます．

![Kong-Gateway-Includes.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/1f261de7-f4a0-2332-e52e-20df2e4ebb39.png)

Kong Gateway (OSS) では API ゲートウェイとオープンソースのプラグインの利用が可能です．
[Admin API](https://docs.konghq.com/gateway/latest/#kong-admin-api) (API), [Kong Manager OSS](https://docs.konghq.com/gateway/3.5.x/kong-manager-oss/) (GUI), [decK](https://docs.konghq.com/deck/latest/) (CLI) で管理することができます．

Kong Gateway (Free) ではワークスペースを集中管理機能や監視機能が拡張された [Kong Manager](https://docs.konghq.com/gateway/3.5.x/kong-manager/) を提供しています．

Kong Gateway (Enterprise) ではさらに [RBAC 機能](https://docs.konghq.com/gateway/3.5.x/admin-api/rbac/reference/)やエンタープライズ用プラグイン等を提供しています．

それぞれで利用できるプラグインは以下のページから検索することができます．

https://docs.konghq.com/hub/

### [Kong Mesh](https://docs.konghq.com/mesh/latest/)

Kong Mesh は

- コントロールプレーンを提供する OSS の [Kuma](https://kuma.io/) 
- データプレーンプロキシを提供する OSS の [Envoy](https://www.envoyproxy.io/) 
 
を拡張したエンタープライズ向けのサービスメッシュを提供します．[^KONG/KONG-MESH]

[^KONG/KONG-MESH]: https://docs.konghq.com/mesh/2.5.x/introduction/how-kong-mesh-works/

![Kong-Mesh-Architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/dd685d3a-02a8-c5bc-7841-617668cbc085.png)

(本記事では利用しませんが，後日別記事で触れるかもしれません...)

### [Insomnia](https://insomnia.rest/)

Insomnia は API の開発や自動テスト/デバッグを支援するデスクトップアプリケーションの OSS です．
[OpenAPI](https://www.openapis.org/) や独自のテストスイートが利用されています．

[Kong が提供する有償プラン](https://insomnia.rest/pricing)を利用すると，アクセス制御などを提供してチームでの Insomnia 活用に役立てることができます．

(本記事では利用しませんが，後日別記事で触れるかもしれません...)

## 動作確認環境

動作確認を行った環境情報を以下に示します．

| Name | Version |
|----|----|
| Windows 10 | 22H2 |
| Ubuntu (WSL2) | 20.04 LTS |
| Docker | 20.10.17 |
| Docker Compose | v2.10.2 |
| Kong Gateway (OSS) | 3.5.0 |
| Kong Gateway (Free) | 3.5.0.2 |
| decK | v1.29.2 |
| PostgreSQL | 16.1-bullseye |
| Prometheus | v2.48.1 |

## Kong Gateway の起動

Kong Gateway と PostgreSQL を 1 台ずつ立ち上げます．

本記事では Kong Gateway (OSS) を使用していきますが，コンテナイメージを変更することで Kong Gateway (Free) を試すことができます．

| Kong Gateway (OSS) | Kong Gateway (Free) |
|----|----|
| [kong:3.5.0](https://hub.docker.com/layers/library/kong/3.5.0/images/sha256-e5d979f74ee2b865582d8cefce70846f2f4e21608d35c7231fe05e1e6282736d?context=explore) | [kong/kong-gateway:3.5.0.2](https://hub.docker.com/layers/kong/kong-gateway/3.5.0.2/images/sha256-208c23d88fa9f563a907dbb29c629c10c6183637898b34cbbafef779ff0965f2?context=explore) |

[公式ドキュメント](https://docs.konghq.com/gateway/latest/install/docker/)に従って，Docker を利用して起動します．
ただし，ドキュメントのコマンドのまま進めると Kong Gateway から PostgreSQL へ接続できないエラーとなります．

https://github.com/Kong/kong/issues/4363

対処方法として

- [コンテナリンク](https://docs.docker.jp/engine/userguide/networking/default_network/dockerlinks.html)を使う
- Docker ネットワークと環境変数を共有する

のいずれかで対応します．

```shell: コンテナリンクを使う場合
# DB 起動
docker run -d --name kong-database \
 -p 5432:5432 \
 -e "POSTGRES_USER=kong" \
 -e "POSTGRES_DB=kong" \
 -e "POSTGRES_PASSWORD=kongpass" \
 postgres:16.1-bullseye

# DB 設定
docker run --rm \
 --link kong-database:kong-database \
 -e "KONG_DATABASE=postgres" \
 -e "KONG_PG_HOST=kong-database" \
 -e "KONG_PG_PASSWORD=kongpass" \
 -e "KONG_PASSWORD=test" \
 kong:3.5.0 kong migrations bootstrap

# Kong Gateway 起動
docker run -d --name kong-gateway \
 --link kong-database:kong-database \
 -e "KONG_DATABASE=postgres" \
 -e "KONG_PG_HOST=kong-database" \
 -e "KONG_PG_USER=kong" \
 -e "KONG_PG_PASSWORD=kongpass" \
 -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
 -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
 -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
 -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
 -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
 -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \
 -p 8000:8000 \
 -p 8001:8001 \
 -p 8002:8002 \
 -p 8005:8005 \
 -p 8006:8006 \
 -p 8443:8443 \
 -p 8444:8444 \
 -p 8445:8445 \
 kong:3.5.0
```

OSS および Free で利用するデフォルトポート番号は以下の通りです．[^KONG/DEFAULT-PORT]
HTTPS を利用するには証明書を準備して設定を行う必要があります．[^KONG/TLS]

[^KONG/DEFAULT-PORT]: https://docs.konghq.com/gateway/3.5.x/production/networking/default-ports/
[^KONG/TLS]: https://docs.konghq.com/gateway/3.5.x/production/networking/configure-postgres-tls/

| Port Number | Service/Purpose |
|----|----|
| :8000 | リクエスト待ち受け (HTTP) |
| :8001 | Admin API (HTTP) |
| :8002 | Kong Manager GUI (HTTP) |
| :8005 | Hybrid Mode での通信 |
| :8006 | Hybrid Mode での通信 |
| :8443 | リクエスト待ち受け (HTTPS) |
| :8444 | Admin API (HTTPS) |
| :8445 | ong Manager GUI (HTTPS) |

Docker ネットワークと環境変数を共有する方法としては，[公式の docker-compose.yml](https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml) を参考にして自作して利用するのが良いと思います．
```KONG_PG_HOST``` の値は ```[リポジトリ名]-[DB コンテナ名]``` を参照して適切に設定する必要があります．

本記事では以下の ```docker-compose.yml``` を使った構成を前提とします．

```shell: Docker ネットワークと環境変数を共有する場合
# docker-compose.yml を作成
mkdir -p $HOME/codes/GitHub/kong && cd $_ && \
vim docker-compose.yml
```

```yaml: docker-copose.yml
version: '3'

x-kong-config:
  &kong-env
  KONG_DATABASE: postgres
  KONG_PG_DATABASE: kong
  KONG_PG_HOST: kong-db-postgres-1
  KONG_PG_PASSWORD: kongpass
  KONG_PG_USER: kong

networks:
  kong-net:
    external: false

services:
  kong-migrations:
    image: kong:3.5.0
    command: kong migrations bootstrap
    profiles: [ "database" ]
    depends_on:
      - db-postgres
    environment:
      <<: *kong-env
    networks:
      - kong-net
    restart: on-failure

  kong:
    image: kong:3.5.0
    profiles: [ "gateway" ]
    environment:
      <<: *kong-env
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
      KONG_ADMIN_GUI_LISTEN: 0.0.0.0:8002
    networks:
      - kong-net
    ports:
      - "8000:8000"
      - "8001:8001"
      - "8002:8002"
      - "8005:8005"
      - "8006:8006"
      - "8443:8443"
      - "8444:8444"
      - "8445:8445"
    restart: on-failure:5

  db-postgres:
    image: postgres:16.1-bullseye
    profiles: [ "database" ]
    environment:
      POSTGRES_DB: kong
      POSTGRES_USER: kong
      POSTGRES_PASSWORD: kongpass
    restart: on-failure
    stdin_open: true
    tty: true
    networks:
      - kong-net
```

```shell: DB と Kong を順番に起動
docker compose --profile database up -d
docker compose --profile gateway up -d
```

起動確認として [Admin API](https://docs.konghq.com/gateway/latest/admin-api/) が提供する ```/services``` エンドポイントにリクエストを送って正常にレスポンスが返ることを確認します．

```shell
curl -i -X GET --url http://localhost:8001/services
> HTTP/1.1 200 OK
> Date: ...
```

また http://localhost:8002 で 管理 GUI に接続できます．
![Kong-Manager-Top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/8c973bc2-7137-1d9f-a9c5-08a55c2d7b88.png)

Kong Gateway では利用ユーザを定義する [```Consumer```](https://docs.konghq.com/gateway/latest/admin-api/#consumer-object) があります．

```Consumer``` を作成してプラグインを設定していくことで，API を利用するユーザごとに挙動を変えることができます．
```Consumer``` は全 ```Service``` 横断で作成されます．

```/consumers``` エンドポイントに ```POST``` をすることで ```Consumer``` を登録できます．

```shell: Consumer の追加
curl -X POST http://localhost:8001/consumers/ \
 --data username=foo
```

管理 GUI でも ```Consumer``` を管理できます．

http://localhost:8002/consumers
![Kong-Consumer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/21c4df88-fd6a-2b99-0ce4-98686bcfb3d5.png)

## [Kong Gateway を Hybrid Mode で起動](https://docs.konghq.com/gateway/latest/production/deployment-topologies/hybrid-mode/)

「データベースを外だしして冗長化できないかな」と考えていたところ調べてみると，Hybrid Mode という構成が提供されていました．

この構成ではコントロールプレーン (CP) にのみデータベースを付随させ，データプレーン (DP) からも参照できるようにします．

![Kong-Hybrid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/8c38e170-adb6-8bbd-8c79-b974c9bb1cb0.png)

こちらは別の記事にて動作確認を行おうと思いますので，乞うご期待．

## [任意のリクエストをプロキシ](https://docs.konghq.com/gateway/3.5.x/get-started/services-and-routes/)

Kong Gateway では上流の API を指定する ```Service``` とルーティングを決める ```Route``` の設定によってリクエストをプロキシする設定を行います．

![Kong-Route-Service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/b83e6024-50be-9b0a-e092-6757698fe0a8.png)

1. ```Service``` の作成
1. ```Route``` の作成
1. Kong Gateway へリクエスト

```/services``` エンドポイントに ```POST``` をすることで ```Service``` を登録できます．
例として [World Time API](https://worldtimeapi.org) を登録します．

```shell: Service 名と上流 API エンドポイントを登録
curl -i -s -X POST http://localhost:8001/services \
 --data name=example_service \
 --data url='http://worldtimeapi.org'
```

```/services/{service name or id}/routes``` エンドポイントに ```POST``` をすることで ```Route``` を登録できます．
例として ```/mock``` に送られたリクエストをルーティングします．

```shell: Route 名とルーティング条件を登録
curl -i -X POST http://localhost:8001/services/example_service/routes \
 --data 'paths[]=/mock' \
 --data name=example_route
```

Kong Gateway に対してリクエストを送ることで上流 API からのレスポンスを取得します．
以下のコマンドでは Kong Gateway を介して ```curl http://worldtimeapi.org/api/timezone/Asia/Tokyo | jq``` を行ったことになります．

```shell: Kong Gateway でプロキシ
curl -X GET http://localhost:8000/mock/api/timezone/Asia/Tokyo | jq
> {
>   "abbreviation": "JST",
>   "client_ip": "xxx.xxx.xxx.xxx",
>   "datetime": "2023-12-25T18:57:54.162186+09:00",
>   "day_of_week": 1,
>   "day_of_year": 359,
>   "dst": false,
>   "dst_from": null,
>   "dst_offset": 0,
>   "dst_until": null,
>   "raw_offset": 32400,
>   "timezone": "Asia/Tokyo",
>   "unixtime": 1703498274,
>   "utc_datetime": "2023-12-25T09:57:54.162186+00:00",
>   "utc_offset": "+09:00",
>   "week_number": 52
> }
```

登録済みの ```Service``` および ```Route``` を確認・修正・削除するには次のコマンドを利用します．

```shell
# 設定済みの Service をすべて表示
curl -X GET http://localhost:8001/services | jq
# 特定の Service の設定を，Service 名または Service IDを指定して確認
curl -X GET http://localhost:8001/services/{service name or id} | jq
# 特定の Service の設定を修正
curl --request PATCH --url localhost:8001/services/{service name or id} --data xxx

# 特定の Service に設定済みの Route をすべて表示
curl -X GET http://localhost:8001/services/{service name or id}/routes | jq
# 特定の Service に設定済みの特定の Route の設定を，Route 名または Route IDを指定して確認
curl -X GET http://localhost:8001/services/{service name or id}/routes/{route name or id} | jq
# 特定の Route の設定を修正
curl --request PATCH --url localhost:8001/services/{service name or id}/routes/{route name or id} --data xxx
```

管理 GUI でも ```Service``` および ```Route``` を管理できます．

http://localhost:8002/services
![Kong-Gateway-Service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/d22457f1-43af-425a-0d6d-feb9b5c26dfd.png)

http://localhost:8002/routes
![Kong-Gateway-Route.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/2632ef87-4498-a686-eaa2-2d0e1cd52d59.png)

## [ロードバランシング](https://docs.konghq.com/gateway/3.5.x/get-started/key-authentication/)

Kong Gateway では ```upstream``` として複数のターゲットを登録し，ターゲットを登録した ```upstream``` を ```Service``` に登録することでロードバランシングを実現します．

![Kong-Load-Balancing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/01199084-644a-19d1-44bc-c209c7a0c4cb.png)

```shell: 複数ターゲットへロードバランシングできるように Service を更新
# upstream 作成
curl -X POST http://localhost:8001/upstreams \
 --data name=example_upstream

# upstream にターゲットを登録
curl -X POST http://localhost:8001/upstreams/example_upstream/targets \
 --data target='httpbun.com:80'
curl -X POST http://localhost:8001/upstreams/example_upstream/targets \
 --data target='httpbin.org:80'

# Service に upstream を登録 (Service を更新)
curl -X PATCH http://localhost:8001/services/example_service \
 --data host='example_upstream'
```

以上で http://localhost:8000/mock に接続すると httpbun.com:80 と httpbin.org:80 に分散して接続されるようになります．

以降では再び World Time API を利用したいため，ターゲットを設定しなおします．
ここでは管理 GUI を使って httpbun.com:80 と httpbin.org:80 のターゲットを削除し，worldtimeapi.org:80 のターゲットを追加しておきます．

http://localhost:8002/upstreams
![Kong-Upstream.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/ed58fc7f-c99f-aea5-813c-1e468038b727.png)

## [リクエストの流量制御](https://docs.konghq.com/gateway/3.5.x/get-started/rate-limiting/)

[Rate Limiting プラグイン](https://docs.konghq.com/hub/kong-inc/rate-limiting/)を利用することで Kong Gateway を通過するリクエストの流量制御を行うことができます．

```shell: Rate Limiting プラグインを有効化
# Kong Gateway 全体で Rate Limiting プラグインを有効化
curl -i -X POST http://localhost:8001/plugins \
 --data name=rate-limiting \
 --data config.minute=5 \
 --data config.policy=local

# 特定の Service で Rate Limiting プラグインを有効化
curl -X POST http://localhost:8001/services/{service name or id}/plugins \
 --data "name=rate-limiting" \
 --data config.minute=5 \
 --data config.policy=local

# 特定の Route で Rate Limiting プラグインを有効化
curl -X POST http://localhost:8001/routes/{route name or id}/plugins \
 --data "name=rate-limiting" \
 --data config.minute=5 \
 --data config.policy=local

# 特定の Consumer で Rate Limiting プラグインを有効化
curl -X POST http://localhost:8001/plugins \
 --data "name=rate-limiting" \
 --data "consumer.username={consumer username}" \
 --data "config.second=5"
```

上記で 1 分間に 6 回以上リクエストを送ると ```Rate Limit``` のエラーが返るようになります．

## [レスポンスのキャッシュ](https://docs.konghq.com/gateway/3.5.x/get-started/proxy-caching/)

[Proxy Cache プラグイン](https://docs.konghq.com/hub/kong-inc/proxy-cache/) を利用することでレスポンスをキャッシュして，繰り返しのリクエストへの応答の高速化を図ることができます．

```shell: Proxy Cache プラグインを有効化
# Kong Gateway 全体で Proxy Cache プラグインを有効化
curl -i -X POST http://localhost:8001/plugins \
 --data "name=proxy-cache" \
 --data "config.request_method=GET" \
 --data "config.response_code=200" \
 --data "config.content_type=application/json; charset=utf-8" \
 --data "config.cache_ttl=30" \
 --data "config.strategy=memory"

# 特定の Service で Proxy Cache プラグインを有効化
curl -X POST http://localhost:8001/services/{service name or id}/plugins \
  --data "name=proxy-cache" \
  --data "config.request_method=GET" \
  --data "config.response_code=200" \
  --data "config.content_type=application/json; charset=utf-8" \
  --data "config.cache_ttl=30" \
  --data "config.strategy=memory"

# 特定の Route で Proxy Cache プラグインを有効化
curl -X POST http://localhost:8001/routes/{route name or id}/plugins \
  --data "name=proxy-cache" \
  --data "config.request_method=GET" \
  --data "config.response_code=200" \
  --data "config.content_type=application/json; charset=utf-8" \
  --data "config.cache_ttl=30" \
  --data "config.strategy=memory"

# 特定の Consumer で Proxy Cache プラグインを有効化
curl -X POST http://localhost:8001/consumers/{consumer username}/plugins \
  --data "name=proxy-cache" \
  --data "config.request_method=GET" \
  --data "config.response_code=200" \
  --data "config.content_type=application/json; charset=utf-8" \
  --data "config.cache_ttl=30" \
  --data "config.strategy=memory"
```

上記で 30 秒 (TTL) 以内の同一のリクエストに対しては ```X-Cache-Status: Hit``` とともに同じレスポンスが返ります (例に使った World Time API だと同じ時間が返ることがわかります) ．

## [API キー認証](https://docs.konghq.com/gateway/3.5.x/get-started/key-authentication/)

[Key Authentication プラグイン](https://docs.konghq.com/hub/kong-inc/key-auth/)を利用することで API キー認証を実装することができます．

まず ```Consumer``` foo に任意のキー (例では password) を登録します．

```shell: Consumer にキーを登録
curl -i -X POST http://localhost:8001/consumers/foo/key-auth \
 --data key=password
```

次に Key Authentication プラグインを有効化します．

```shell: Key Authentication プラグインを有効化
curl -X POST http://localhost:8001/plugins/ \
   --data "name=key-auth"  \
   --data "config.key_names=apikey"
```

以上で正しいキーをヘッダに含めないとエラーになります．

```shell: API キーを使った認証を検証
# キーを含めずにリクエスト
curl -i http://localhost:8000/mock/api/timezone/Asia/Tokyo

# キーを含めてリクエスト
curl -i http://localhost:8000/mock/api/timezone/Asia/Tokyo \
 -H 'apikey:password'
```

特定の Service または Route に対してキー認証を有効化することもできます．

```shell: Key Authentication プラグインを有効化
# 特定の Service で Key Authentication プラグインを有効化
curl -X POST http://localhost:8001/services/{service name or id}/plugins \
 --data name=key-auth

# 特定の Route で Key Authentication プラグインを有効化
curl -X POST http://localhost:8001/routes/{route name or id}/plugins \
 --data name=key-auth
```

こちらの記事ではさらに [ACL プラグイン](https://docs.konghq.com/hub/kong-inc/acl/)を利用して API のアクセス制御を実装しています．

https://qiita.com/okuura/items/4c1a5db37faf7671aabf

## [Prometheus](https://prometheus.io/) で監視

[Prometheus プラグイン](https://docs.konghq.com/hub/kong-inc/prometheus/)を利用することで Prometheus と簡単に連携し，Kong Gateway を監視することができます．

```shell: Prometheus プラグインを有効化
curl -s -X POST http://localhost:8001/plugins/ \
 --data "name=prometheus" 
```

次に Prometheus 用の config ファイルを作成します．

```shell
vim prometheus.yml
```

```prometheus.yml``` には Prometheus がスクレイプする際の設定を記載します．[^PROMETHEUS/CONFIG]
Kong Gateway と同一の Docker ネットワークを使うかどうかも含め，ご自身の環境に合わせて ```targets``` を指定してください．

[^PROMETHEUS/CONFIG]: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config

```yaml: prometheus.yml
scrape_configs:
  - job_name: 'kong'
    scrape_interval: 5s
    static_configs:
      - targets: ['kong-kong-1:8001']
```

Prometheus を起動します．

```shell: docker-compose.prometheus.yml 作成と起動
vim docker-compose.prometheus.yml
docker compose -f docker-compose.prometheus.yml up -d
```

```yaml: docker-compose.prometheus.yml
version: '3'

services:
  prometheus:
    image: prom/prometheus:v2.48.1
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - $HOME/codes/GitHub/kong/prometheus.yml:/etc/prometheus/prometheus.yml
    shm_size: 512m
    restart: always
    logging:
      driver: json-file
      options:
        max-file: '3'
        max-size: 512m
    networks:
      - kong_kong-net

networks:
  kong_kong-net:
    external: true
```

登録可能な metric は Admin API の ```/metrics``` エンドポイントで取得できます．

```shell: Kong Gateway の metric を確認
curl -s localhost:8001/metrics
```

http://localhost:9090 で Prometheus に接続できます．
数回適当に Kong Gateway を介した通信を行ってから少し待って Prometheus に接続すると，Kong Gateway の metric が取得できていることを確認できます．

![Kong-Prometheus.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997806/5959f2a1-aae5-7780-58dc-265994de79d3.png)

## [カスタムプラグイン](https://docs.konghq.com/gateway/latest/plugin-development/)でさらに拡張

いくつかのプラグインを使って Kong Gateway の拡張を行ってきましたが，自身でカスタムプラグインを作成して拡張することもできます．

以下の記事にて Go による Kong Gateway のカスタムプラグインを作成を試してみたので，ぜひご覧になっていただければと思います．

https://qiita.com/caunu-s/items/b6ea0a86252ad7b3f6dc

## [decK](https://docs.konghq.com/deck/latest/) で Kong Gateway 構成管理

decK は Kong Gateway の設定を行う CLI ツールであり，

- Kong Gateway クラスタを一括設定
- 手動設定によるドリフトを検知
- 設定ファイルを活用することで [GitOps](https://docs.konghq.com/deck/latest/guides/ci-driven-configuration/) や [APIOps](https://docs.konghq.com/deck/latest/guides/apiops/) の実現を支援

に役立てられます．

decK コマンドを使えるようにする方法はいくつかありますが，ここでは [kong/deck Docker イメージ](https://hub.docker.com/layers/kong/deck/v1.29.2/images/sha256-4f01267d60e52318c3ef2c71da7023fee85bbca52e394bf93774ea65655bd261?context=explore)を手元に準備しておくことで docker run から実行します．

```shell: decK イメージを取得
docker pull kong/deck:v1.29.2
```

decK で Kong Gateway の設定をエクスポートしてみます．
エクスポート先を適当に準備して ```dump``` をします．
以下は公式ドキュメントにはまだ書かれていませんが必要となります．

- 最新版では ```deck dump``` ではなく ```deck gateway dump``` を使うことが推奨です (```reset``` も同様)．```sync``` も ```deck gateway sync``` に変更となっているようですが，ヘルプに ```kong.yml``` を読み込むオプションが見つからなかったため ```deck sync``` で利用します．
- decK コンテナから Kong Gateway に接続できるように Docker ネットワークを共有するなどしてください．

【追記 2023/12/28】
```deck gateway sync``` について問い合わせてみました．

https://github.com/Kong/deck/issues/1154

```deck gateway sync *.yaml``` を使うように変更される予定でリリース待ち状態とのことです．

```shell: Kong Gateway の設定を dump
# 出力先準備
mkdir $HOME/codes/GitHub/kong/deck

# dump 実行
docker run --rm \
 --network=kong_kong-net \
 -i -v $HOME/codes/GitHub/kong/deck:/deck \
 kong/deck:v1.29.2 --kong-addr http://kong-kong-1:8001 -o /deck/kong.yaml gateway dump

# 確認
cat $HOME/codes/GitHub/kong/deck/kong.yaml
> _format_version: "3.0"
> plugins:
> - config:
> ...
```

以上でエクスポートができました．

続いて Kong Gateway の設定をすべて削除してみます．

```shell: Kong Gateway の設定を reset
# reset 実行
docker run --rm \
 --network=kong_kong-net \
 -i kong/deck:v1.29.2 --kong-addr http://kong-kong-1:8001 gateway reset

> This will delete all configuration from Kong's database.
> Are you sure? y
> deleting plugin prometheus (global)
> ...
```

以上で設定の全削除ができました．管理 GUI を見てもキレイさっぱり消えていることがわかります．

最後にエクスポートしたファイルをインポートして復元します．

```shell: Kong Gateway の設定を import
# import 実行
docker run --rm \
 --network=kong_kong-net \
 -i -v $HOME/codes/GitHub/kong/deck:/deck \
 kong/deck:v1.29.2 --kong-addr http://kong-kong-1:8001 -s /deck/kong.yaml sync
```

以上で Kong Gateway の復元ができました．

## まとめ

Kong Gateway の公式ドキュメントを一通り眺め，動作確認を行いました．

(起動方法で多少悩みはしたものの) 比較的簡単に導入できるうえに，設定や拡張の方法まで整っている素晴らしい OSS だと感じました．

decK は便利ですがコマンドの改定など絶賛発展途上にある感じなので，今後に期待かなと思います．