この記事の目的
公式ドキュメントに沿って Kong Gateway の動作確認を行ったので,こちらの記事に残します.
こちらの記事を参考にして Kong Gateway (OSS) および Kong Gateway (Free) の環境を構築することができます.
構成
Kong が提供するサービスの紹介
Kong Gateway
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 の中心的なサービスであり,以下を支援する機能が提供されています.
- ワークフロー,GitOps の活用
- マイクロサービス化,分散アーキテクチャの実現
- API 開発エコシステムの提供
- API 関連の異常・脅威の検知補助
- API とサービスの保護
Kong Gateway を利用する方法は 1. Kong Konnect, 2. Self-managed の 2 パターンあります.
1. Kong Konnect
Kong Konnect は Kong による有料の SaaS サービスで 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,Kong Gateway (Free/Enterprise) は Kong Software License Agreement で運用されます.
Kong Gateway (OSS) では API ゲートウェイとオープンソースのプラグインの利用が可能です.
Admin API (API), Kong Manager OSS (GUI), decK (CLI) で管理することができます.
Kong Gateway (Free) ではワークスペースを集中管理機能や監視機能が拡張された Kong Manager を提供しています.
Kong Gateway (Enterprise) ではさらに RBAC 機能やエンタープライズ用プラグイン等を提供しています.
それぞれで利用できるプラグインは以下のページから検索することができます.
Kong Mesh
Kong Mesh は
を拡張したエンタープライズ向けのサービスメッシュを提供します.1
(本記事では利用しませんが,後日別記事で触れるかもしれません...)
Insomnia
Insomnia は API の開発や自動テスト/デバッグを支援するデスクトップアプリケーションの OSS です.
OpenAPI や独自のテストスイートが利用されています.
Kong が提供する有償プランを利用すると,アクセス制御などを提供してチームでの 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 | kong/kong-gateway:3.5.0.2 |
公式ドキュメントに従って,Docker を利用して起動します.
ただし,ドキュメントのコマンドのまま進めると Kong Gateway から PostgreSQL へ接続できないエラーとなります.
対処方法として
- コンテナリンクを使う
- Docker ネットワークと環境変数を共有する
のいずれかで対応します.
# 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 で利用するデフォルトポート番号は以下の通りです.2
HTTPS を利用するには証明書を準備して設定を行う必要があります.3
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 を参考にして自作して利用するのが良いと思います.
KONG_PG_HOST
の値は [リポジトリ名]-[DB コンテナ名]
を参照して適切に設定する必要があります.
本記事では以下の docker-compose.yml
を使った構成を前提とします.
# docker-compose.yml を作成
mkdir -p $HOME/codes/GitHub/kong && cd $_ && \
vim docker-compose.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
docker compose --profile database up -d
docker compose --profile gateway up -d
起動確認として Admin API が提供する /services
エンドポイントにリクエストを送って正常にレスポンスが返ることを確認します.
curl -i -X GET --url http://localhost:8001/services
> HTTP/1.1 200 OK
> Date: ...
また http://localhost:8002 で 管理 GUI に接続できます.
Kong Gateway では利用ユーザを定義する Consumer
があります.
Consumer
を作成してプラグインを設定していくことで,API を利用するユーザごとに挙動を変えることができます.
Consumer
は全 Service
横断で作成されます.
/consumers
エンドポイントに POST
をすることで Consumer
を登録できます.
curl -X POST http://localhost:8001/consumers/ \
--data username=foo
管理 GUI でも Consumer
を管理できます.
http://localhost:8002/consumers
Kong Gateway を Hybrid Mode で起動
「データベースを外だしして冗長化できないかな」と考えていたところ調べてみると,Hybrid Mode という構成が提供されていました.
この構成ではコントロールプレーン (CP) にのみデータベースを付随させ,データプレーン (DP) からも参照できるようにします.
こちらは別の記事にて動作確認を行おうと思いますので,乞うご期待.
任意のリクエストをプロキシ
Kong Gateway では上流の API を指定する Service
とルーティングを決める Route
の設定によってリクエストをプロキシする設定を行います.
-
Service
の作成 -
Route
の作成 - Kong Gateway へリクエスト
/services
エンドポイントに POST
をすることで Service
を登録できます.
例として World Time 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
に送られたリクエストをルーティングします.
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
を行ったことになります.
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
を確認・修正・削除するには次のコマンドを利用します.
# 設定済みの 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 では upstream
として複数のターゲットを登録し,ターゲットを登録した upstream
を 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
リクエストの流量制御
Rate Limiting プラグインを利用することで Kong Gateway を通過するリクエストの流量制御を行うことができます.
# 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
のエラーが返るようになります.
レスポンスのキャッシュ
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 キー認証
Key Authentication プラグインを利用することで API キー認証を実装することができます.
まず Consumer
foo に任意のキー (例では password) を登録します.
curl -i -X POST http://localhost:8001/consumers/foo/key-auth \
--data key=password
次に Key Authentication プラグインを有効化します.
curl -X POST http://localhost:8001/plugins/ \
--data "name=key-auth" \
--data "config.key_names=apikey"
以上で正しいキーをヘッダに含めないとエラーになります.
# キーを含めずにリクエスト
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 に対してキー認証を有効化することもできます.
# 特定の 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 プラグインを利用して API のアクセス制御を実装しています.
Prometheus で監視
Prometheus プラグインを利用することで Prometheus と簡単に連携し,Kong Gateway を監視することができます.
curl -s -X POST http://localhost:8001/plugins/ \
--data "name=prometheus"
次に Prometheus 用の config ファイルを作成します.
vim prometheus.yml
prometheus.yml
には Prometheus がスクレイプする際の設定を記載します.4
Kong Gateway と同一の Docker ネットワークを使うかどうかも含め,ご自身の環境に合わせて targets
を指定してください.
scrape_configs:
- job_name: 'kong'
scrape_interval: 5s
static_configs:
- targets: ['kong-kong-1:8001']
Prometheus を起動します.
vim docker-compose.prometheus.yml
docker compose -f docker-compose.prometheus.yml up -d
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
エンドポイントで取得できます.
curl -s localhost:8001/metrics
http://localhost:9090 で Prometheus に接続できます.
数回適当に Kong Gateway を介した通信を行ってから少し待って Prometheus に接続すると,Kong Gateway の metric が取得できていることを確認できます.
カスタムプラグインでさらに拡張
いくつかのプラグインを使って Kong Gateway の拡張を行ってきましたが,自身でカスタムプラグインを作成して拡張することもできます.
以下の記事にて Go による Kong Gateway のカスタムプラグインを作成を試してみたので,ぜひご覧になっていただければと思います.
decK で Kong Gateway 構成管理
decK は Kong Gateway の設定を行う CLI ツールであり,
に役立てられます.
decK コマンドを使えるようにする方法はいくつかありますが,ここでは kong/deck Docker イメージを手元に準備しておくことで docker run から実行します.
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
について問い合わせてみました.
deck gateway sync *.yaml
を使うように変更される予定でリリース待ち状態とのことです.
# 出力先準備
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 の設定をすべて削除してみます.
# 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 を見てもキレイさっぱり消えていることがわかります.
最後にエクスポートしたファイルをインポートして復元します.
# 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 は便利ですがコマンドの改定など絶賛発展途上にある感じなので,今後に期待かなと思います.
-
https://docs.konghq.com/mesh/2.5.x/introduction/how-kong-mesh-works/ ↩
-
https://docs.konghq.com/gateway/3.5.x/production/networking/default-ports/ ↩
-
https://docs.konghq.com/gateway/3.5.x/production/networking/configure-postgres-tls/ ↩
-
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config ↩