LoginSignup
7
12

More than 3 years have passed since last update.

オープンソースなAPI Gateway Kong(とKonga)を使ってみた

Posted at

Kongとは

詳しくはこちらの記事が参考になりました。
KONGことはじめ - Qiita

  • 無料のAPI Gateway
  • 無料のものと、Enterprise版がある(この記事では無料版を使用)
  • 無料のものには、デフォルトでは管理コンソール的なものはない(非公式・無料の管理コンソールKongaがある)
  • Admin APIと呼ばれるKongに標準搭載されているAPIを介してルーティングなどを設定する
  • Gatewayのポートは8000、Admin APIのポートは8001が使用される

Kongに登場するService、Routeオブジェクトについて

詳しくはこちらが参考になりました
(Kongaの使い方の説明記事ですが、Kongの概念について冒頭で紹介されています)
Kongの使い方を知る① ~Service & Route編~ | ウルシステムズ株式会社

また、公式のドキュメントにも同様の説明がありました。
image.png
Expose your Services with Kong Gateway - vlatest | Kong - Open-Source API Management and Microservice Management

ざっくり言うと、Routeはクライアントがアクセスしてくるときのパスを表していて、
Serviceはそのパスにアクセスがきた時にどのバックエンドサーバーにリクエストを飛ばすかを設定するもの。
なのでServiceには1つ以上のRouteを設定して、ルーティングを設定する。

準備

すべてローカルで実施。

構成のイメージ

image.png

環境

  • MacOS Catalina v10.15.4
  • docker version 19.03.8
  • docker-compose version 1.25.4 ← Kong、Postgresql、Kongaの起動に使用

APIの準備

今回はNode Expressで適当なGET、POSTのAPIを用意。
https://github.com/popy1017/sample-express
これをポートとメッセージを適当に変えて2つ起動
& をつけるとバックグラウンドで起動できる。

node app.js &

確認

※ jq は JSON形式の文字列をパースするコマンド

curl localhost:3000 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    35  100    35    0     0  35000      0 --:--:-- --:--:-- --:--:-- 35000
{
  "message": "This is service1. GET"
}
curl -X POST -H 'Content-type:application/json' -d '{"service": 1 }' localhost:3000 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    72  100    57  100    15  28500   7500 --:--:-- --:--:-- --:--:-- 36000
{
  "message": "This is service1. POST",
  "body": {
    "service": 1
  }
}

Kongを起動する

KongやDB、Kongaは下記のdocker-compose.ymlで行った。
https://github.com/Kuari/kong-konga-docker-compose
ただし、1箇所だけ修正

〜略〜
  konga:
    image: pantsel/konga
    ports:
      - 1337:1337
    links:
      - kong:kong
    container_name: konga
    environment:
      - NODE_ENV=production
    networks:     # <- 追加
      - kong-net  # <- 追加
〜略〜

起動と確認

まだルーティングなどを設定していないので、Gatewayにアクセスすると、"no Route matched with those values"というメッセージが返ってくる。

docker-compose up -d

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                NAMES
cb08a1c66bdc        pantsel/konga       "/app/start.sh"          41 hours ago        Up 41 hours         0.0.0.0:1337->1337/tcp                                               konga
6562aeafeb48        kong                "/docker-entrypoint.…"   41 hours ago        Up 41 hours         0.0.0.0:8000-8001->8000-8001/tcp, 0.0.0.0:8443-8444->8443-8444/tcp   kong
8df4ff5a0599        postgres:9.6        "docker-entrypoint.s…"   41 hours ago        Up 41 hours         0.0.0.0:5432->5432/tcp                                               kong-database

curl localhost:8000 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    48  100    48    0     0   5333      0 --:--:-- --:--:-- --:--:--  5333
{
  "message": "no Route matched with those values"
}

まずはAdmin API経由で使ってみる

Kongでは、Admin APIを介してServiceやRouteなどの設定を行う。
Admin APIの詳細な仕様については下記を参照してください。
Admin API - v2.0.x | Kong - Open-Source API Management and Microservice Management

Serviceを追加する

Serviceを追加するためには、http://{Kongサーバーのアドレスorドメイン}:8001/services にPOSTリクエストを投げる。(今回はローカルで作業するので、http://localhost:8001/services)
必須パラメータはurlまたは、host,port,pathの3点セット。例えば、url=http://localhost:3000/hogeと設定するのと、host=localhost, port=3000, path=/hogeと設定するのは同義だと思われる。
※ 今回の構成では、Dockerコンテナの中(kong)からローカルサーバー(Node Express)にアクセスする必要があるため、hostにhost.docker.ineternalを設定する。(localhostを指定すると、コンテナ内のローカルと認識されてしまう。)

urlのみ指定したが、レスポンスを見るとhost="host.docker.internal",port=3000,path="/"となっていることが確認できる。

curl -X POST http://localhost:8001/services \
--data name=service1 \
--data url=http://host.docker.internal:3000/ | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   351  100   300  100    51  42857   7285 --:--:-- --:--:-- --:--:-- 50142
{
  "host": "host.docker.internal",
  "created_at": 1587283600,
  "connect_timeout": 60000,
  "id": "936cd429-1e8b-4732-87a6-1215634c5c98",
  "protocol": "http",
  "name": "service1",
  "read_timeout": 60000,
  "port": 3000,
  "path": "/",
  "updated_at": 1587283600,
  "retries": 5,
  "write_timeout": 60000,
  "tags": null,
  "client_certificate": null
}

Serviceの確認

GETで/servicesまたは、/services/{service name or id}を実行すると、Service一覧やSerivceの情報が取得できる。

# Service一覧
curl http://localhost:8001/services | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   323  100   323    0     0  64600      0 --:--:-- --:--:-- --:--:-- 64600
{
  "next": null,
  "data": [
    {
      "host": "host.docker.internal",
      "created_at": 1587283600,
      "connect_timeout": 60000,
      "id": "936cd429-1e8b-4732-87a6-1215634c5c98",
      "protocol": "http",
      "name": "service1",
      "read_timeout": 60000,
      "port": 3000,
      "path": "/",
      "updated_at": 1587283600,
      "retries": 5,
      "write_timeout": 60000,
      "tags": null,
      "client_certificate": null
    }
  ]
}

# 特定のService情報
curl http://localhost:8001/services/service1 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   300  100   300    0     0  75000      0 --:--:-- --:--:-- --:--:-- 75000
{
  "host": "host.docker.internal",
  "created_at": 1587283600,
  "connect_timeout": 60000,
  "id": "936cd429-1e8b-4732-87a6-1215634c5c98",
  "protocol": "http",
  "name": "service1",
  "read_timeout": 60000,
  "port": 3000,
  "path": "/",
  "updated_at": 1587283600,
  "retries": 5,
  "write_timeout": 60000,
  "tags": null,
  "client_certificate": null
}

Routeを追加する

Routeは/services/{service name or id}/routesにPOSTで追加できる。
必須パラメータは、methods, hosts, headers, pathsのいずれか。
今回は、methodとpathを指定。

curl -X POST http://localhost:8001/services/service1/routes --data name=service1-api --data methods[]="GET" --data methods[]="POST" --data paths[]="/service1" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   512  100   448  100    64  44800   6400 --:--:-- --:--:-- --:--:-- 51200
{
  "id": "c2c410e4-5f0f-4e8f-a040-e5dc55f90a42",
  "path_handling": "v0",
  "paths": [
    "/service1"
  ],
  "destinations": null,
  "headers": null,
  "protocols": [
    "http",
    "https"
  ],
  "methods": [
    "GET",
    "POST"
  ],
  "snis": null,
  "service": {
    "id": "936cd429-1e8b-4732-87a6-1215634c5c98"
  },
  "name": "service1-api",
  "strip_path": true,
  "preserve_host": false,
  "regex_priority": 0,
  "updated_at": 1587285662,
  "sources": null,
  "hosts": null,
  "https_redirect_status_code": 426,
  "tags": null,
  "created_at": 1587285662
}

確認

Admin APIで確認

特定のServiceが持つRoute一覧を取得するには、GETで/services/{service name or id}/routesを実行する。

curl http://localhost:8001/services/service1/routes | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   471  100   471    0     0  78500      0 --:--:-- --:--:-- --:--:-- 78500
{
  "next": null,
  "data": [
    {
      "id": "c2c410e4-5f0f-4e8f-a040-e5dc55f90a42",
      "path_handling": "v0",
      "paths": [
        "/service1"
      ],
      "destinations": null,
      "headers": null,
      "protocols": [
        "http",
        "https"
      ],
      "methods": [
        "GET",
        "POST"
      ],
      "snis": null,
      "service": {
        "id": "936cd429-1e8b-4732-87a6-1215634c5c98"
      },
      "name": "service1-api",
      "strip_path": true,
      "preserve_host": false,
      "regex_priority": 0,
      "updated_at": 1587285662,
      "sources": null,
      "hosts": null,
      "https_redirect_status_code": 426,
      "tags": null,
      "created_at": 1587285662
    }
  ]
}

Gatewayから確認

{GatewayURL}:8000/{Routeで設定したPath}で実行

# GET
curl localhost:8000/service1 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    35  100    35    0     0   4375      0 --:--:-- --:--:-- --:--:--  4375
{
  "message": "This is service1. GET"
}

# POST
curl -X POST -H 'Content-type:application/json' -d '{"aaa":"bbb"}' localhost:8000/service1 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    70  100    57  100    13   8142   1857 --:--:-- --:--:-- --:--:-- 10000
{
  "message": "This is service1. POST",
  "body": {
    "aaa": "bbb"
  }
}

以上がAdmin API経由でのルーティング設定。
慣れれば楽なんだろうが、何が起こっているのか、どう設定されているのかが非常にわかりにくい。
ので、続いてKongの非公式GUI Kongaを使ってみる。

Konga経由でルーティング設定をす

初期設定&ログイン

KongaのURLは http://localhost:1337/
初回アクセス時に、管理アカウントを作成する画面が表示されるので、適当に作成する。
作成が完了すると、ログイン画面に遷移するので、作成した管理アカウントでログインする。
ログインすると下記のような画面が表示されるので、下記のように設定する。(Nameは任意)
Name: KongSample
Kong Admin URL: http://kong:8001
※ KongaとKongはコンテナ間通信であるため、docker-compose.ymlで設定しているcontainer_name(=kong)で名前解決できる。ここでをlocalhostとしてしまうと、Kongaコンテナはコンテナ内を探しにいってしまう。
image.png

API経由で追加したService&Route確認

Admin URLの設定(Connectionという)が完了すると、以下のような画面が表示される。
image.png

サイドメニューのServicesやRoutesを選択すると、上記でAdmin API経由で追加したServiceやRouteの情報がみられる。
image.png

Konga経由でServiceを追加する

  1. 左サイドメニューの「Services」を選択する
  2. 「+Add New Service」ボタンを押す
  3. 「CREATE SERVICE」というモーダルが表示されるので、下記のように設定する。
  4. 「Submit Service」ボタンを押し、Serviceを追加する。

登録が完了すると、Service一覧にservice2が追加されているはず。

Konga経由でRouteを追加する

続いてRouteを追加するが、Routeはサイドメニューの「Services」を選択して、いずれかのServiceを選択した後表示される画面で追加する。(サイドメニューRoutesを選択した場合の画面からは追加できない)
1. 左サイドメニューの「Services」を選択する
2. Service一覧から、「service2」を選択する
3. 画面中央のサイドメニューから「Routes」を選択する
4. 「+Add Route」ボタンを押す
5. モーダルが表示されるので、下記のように設定する(他はデフォルト)
* Name: service2-api
* Paths: /service2
* Methods: GET,POST
※ PathsやMethodsのように複数の値を設定できる項目は、値を1つ入力するごとにEnterを押さないと反映されないので注意
6. 追加が成功すると、Route一覧にservice2-apiが表示されるはず

Gatewayから確認してみる

# GET
curl localhost:8000/service2 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    35  100    35    0     0   4375      0 --:--:-- --:--:-- --:--:--  4375
{
  "message": "This is service2. GET"
}

# POST
curl -X POST -H 'Content-type:application/json' -d '{"aaa":"bbb"}' localhost:8000/service2 | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    70  100    57  100    13   3000    684 --:--:-- --:--:-- --:--:--  3684
{
  "message": "This is service2. POST",
  "body": {
    "aaa": "bbb"
  }
}
7
12
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
7
12