LoginSignup
6
1

Kong Gateway を触ってみる

Last updated at Posted at 2023-12-27

この記事の目的

公式ドキュメントに沿って Kong Gateway の動作確認を行ったので,こちらの記事に残します.

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

構成

Kong-Architecture.png

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

Kong Gateway

Kong.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 の中心的なサービスであり,以下を支援する機能が提供されています.

  • ワークフロー,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-Includes.PNG

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 は

  • コントロールプレーンを提供する OSS の Kuma
  • データプレーンプロキシを提供する OSS の Envoy

を拡張したエンタープライズ向けのサービスメッシュを提供します.1

Kong-Mesh-Architecture.png

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

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 へ接続できないエラーとなります.

対処方法として

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

コンテナリンクを使う場合
# 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 ネットワークと環境変数を共有する場合
# docker-compose.yml を作成
mkdir -p $HOME/codes/GitHub/kong && cd $_ && \
vim docker-compose.yml
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
DB と Kong を順番に起動
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-Manager-Top.png

Kong Gateway では利用ユーザを定義する Consumer があります.

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

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

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

管理 GUI でも Consumer を管理できます.

http://localhost:8002/consumers
Kong-Consumer.png

Kong Gateway を Hybrid Mode で起動

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

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

Kong-Hybrid.png

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

任意のリクエストをプロキシ

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

Kong-Route-Service.png

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

/services エンドポイントに POST をすることで Service を登録できます.
例として World Time API を登録します.

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 に送られたリクエストをルーティングします.

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 を行ったことになります.

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 を確認・修正・削除するには次のコマンドを利用します.

# 設定済みの 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

http://localhost:8002/routes
Kong-Gateway-Route.png

ロードバランシング

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

Kong-Load-Balancing.png

複数ターゲットへロードバランシングできるように 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

リクエストの流量制御

Rate Limiting プラグインを利用することで Kong Gateway を通過するリクエストの流量制御を行うことができます.

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 のエラーが返るようになります.

レスポンスのキャッシュ

Proxy Cache プラグイン を利用することでレスポンスをキャッシュして,繰り返しのリクエストへの応答の高速化を図ることができます.

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) を登録します.

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

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

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

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

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 に対してキー認証を有効化することもできます.

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 プラグインを利用して API のアクセス制御を実装しています.

Prometheus で監視

Prometheus プラグインを利用することで Prometheus と簡単に連携し,Kong Gateway を監視することができます.

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

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

vim prometheus.yml

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

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

Prometheus を起動します.

docker-compose.prometheus.yml 作成と起動
vim docker-compose.prometheus.yml
docker compose -f docker-compose.prometheus.yml up -d
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 エンドポイントで取得できます.

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

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

Kong-Prometheus.png

カスタムプラグインでさらに拡張

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

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

decK で Kong Gateway 構成管理

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

  • Kong Gateway クラスタを一括設定
  • 手動設定によるドリフトを検知
  • 設定ファイルを活用することで GitOpsAPIOps の実現を支援

に役立てられます.

decK コマンドを使えるようにする方法はいくつかありますが,ここでは kong/deck Docker イメージを手元に準備しておくことで docker run から実行します.

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

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

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

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

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

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 の設定をすべて削除してみます.

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 を見てもキレイさっぱり消えていることがわかります.

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

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 は便利ですがコマンドの改定など絶賛発展途上にある感じなので,今後に期待かなと思います.

  1. https://docs.konghq.com/mesh/2.5.x/introduction/how-kong-mesh-works/

  2. https://docs.konghq.com/gateway/3.5.x/production/networking/default-ports/

  3. https://docs.konghq.com/gateway/3.5.x/production/networking/configure-postgres-tls/

  4. https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1