プロキシリファレンス
このドキュメントでは、Kong Gateway の プロキシ機能 について、ルーティング機能と内部動作の詳細を説明します。
Kong Gatewayは、次の設定プロパティによって調整できるいくつかのインターフェースを公開します。
-
proxy_listen
は、Kong Gatewayクライアントからの パブリックHTTP(gRPC、WebSocketなど)トラフィック を受け入れ、それをアップストリームサービス(デフォルトは8000
)にプロキシするアドレス/ポートのリストを定義します。 -
admin_listen
もアドレスとポートのリストを定義しますが、これらは Kong の構成機能である Admin API (デフォルトでは8001
)を公開するため、管理者のみがアクセスできるように制限する必要があります。
重要 :本番環境で
admin_listen
ポートをインターネットに公開する必要がある場合は、 secure it with authentication.
-
stream_listen
はproxy_listen
に似ていますが、レイヤー4(TCP、TLS)汎用プロキシ向けです。デフォルトではオフになっています。
用語解説
-
client
: Kong Gateway の プロキシポートに対してリクエストを行う ダウンストリーム クライアントを指します。 -
upstream service
: クライアントのリクエスト/接続が転送される Kong Gateway の背後にある自身の API/サービスを指します。 -
Service
: サービスエンティティは、その名のとおり、独自のアップストリームサービスのそれぞれを抽象化したものです。サービスの例としては、データ変換マイクロサービス、課金APIなどがあります。 -
Route
: これは、Kong Gateway ルートエンティティを指します。ルートは Kong Gateway へのエントリポイントであり、リクエストをマッチングして特定のサービスにルーティングするためのルールを定義します。 -
Plugin
: これは Kong Gateway “プラグイン” を指します。これはプロキシライフサイクルで 実行されるビジネスロジックの一部です。プラグインは グローバル(すべての受信トラフィック)または特定のルートやサービス上 のAdmin APIで構成されます。
概要
要約すると、Kong Gatewayは構成済みのプロキシポート(デフォルトでは8000
と8443
)でHTTPトラフィックをリッスンし、明示的に構成されたstream_listen
ポートでL4トラフィックをリッスンします。
Kong Gatewayは、ユーザーが構成済みのルートに照らして受信するHTTPリクエストまたはL4接続を評価し、一致するものを見つけようとします。
特定のリクエストが特定のルートのルールに一致する場合、Kong Gatewayはリクエストのプロキシ設定を処理します。
各ルートはサービスにリンクされている可能性があるため、Kong Gatewayはお客様がルートと関連する サービスに設定したプラグインを実行し、リクエストをアップストリームに プロキシします。Kong GatewayのAdmin APIを介してルートを管理できます。ルートには 受信HTTPリクエストを照合してルーティングするために使用される特別な属性があります。 ルーティング属性はサブシステム(HTTP/HTTPS、gRPC/gRPCS、TCP/TLS)によって異なります。
サブシステムとルーティング属性:
-
http
:methods
。hosts
。headers
、paths
(https
の場合はsnis
) -
tcp
:sources
、destinations
(そしてtls
の場合はsnis
) -
grpc
:hosts
、headers
、paths
(そしてgrpcs
の場合はsnis
)
サポートされていないルーティング属性(たとえば、sources
または destinations
フィールドを持つ http
ルート)でルートを構成しようとすると、エラーメッセージが表示されます。
HTTP/1.1 400 Bad Request
Content-Type: application/json
Server: kong/<x.x.x id="sl-md0000000">
{
"code": 2,
"fields": {
"sources": "cannot set 'sources' when 'protocols' is 'http' or 'https'"
},
"message": "schema violation (sources: cannot set 'sources' when 'protocols' is 'http' or 'https')",
"name": "schema violation"
}
Kong Gatewayが、設定されたルートのいずれにも一致しないリクエストを受信した場合、 (またはルートが設定されていない場合)、次のように応答します。
HTTP/1.1 404 Not Found
Content-Type: application/json
Server: kong/<x.x.x id="sl-md0000000">
{
"message": "no route and no Service found with those values"
}
サービスの構成方法
サービスの設定クイックスタートガイドでは、 Admin API経由で Kong を構成する方法を説明しています。
Kong Gateway にサービスを追加するには、Admin API に HTTP リクエストを送信します。
curl -i -X POST http://localhost:8001/services/ \
-d 'name=foo-service' \
-d 'url=http://foo-service.com'
レスポンス:
HTTP/1.1 201 Created
...
{
"connect_timeout": 60000,
"created_at": 1515537771,
"host": "foo-service.com",
"id": "d54da06c-d69f-4910-8896-915c63c270cd",
"name": "foo-service",
"path": "/",
"port": 80,
"protocol": "http",
"read_timeout": 60000,
"retries": 5,
"updated_at": 1515537771,
"write_timeout": 60000
}
このリクエストは、 Kong Gatewayに「foo-service」という名前のサービスを登録するように指示します。
これは http://foo-service.com
(上流) を指します。
注: url
引数は、protocol
、 host
、 port
、およびpath
属性を一度に設定するための省略法の因数です。
次に、Kong Gateway を介してこのサービスにトラフィックを送信するために、Kong Gateway へのエントリポイントとして機能するルートを指定する必要があります。
curl -i -X POST http://localhost:8001/routes/ \
-d 'hosts[]=example.com' \
-d 'paths[]=/foo' \
-d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd'
レスポンス:
HTTP/1.1 201 Created
...
{
"created_at": 1515539858,
"hosts": [
"example.com"
],
"id": "ee794195-6783-4056-a5cc-a7e0fde88c81",
"methods": null,
"paths": [
"/foo"
],
"preserve_host": false,
"priority": 0,
"protocols": [
"http",
"https"
],
"service": {
"id": "d54da06c-d69f-4910-8896-915c63c270cd"
},
"strip_path": true,
"updated_at": 1515539858
}
これで、指定されたhosts
と paths
に一致する受信リクエストを照合し、設定したfoo-service
に転送するルートを設定し、このトラフィックがhttp://foo-service.com
にプロキシされるようになりました。
Kong Gatewayは透過的プロキシで、デフォルトでは、HTTP仕様で要求されるConnection
、Date
などのさまざまヘッダーを除いて、リクエストをそのままアップストリームサービスに転送します。
ルートとマッチング機能
では、Kong Gatewayがリクエストを設定されたルーティング属性とどのように照合するかについて説明しましょう。
Kong Gatewayは、HTTP/HTTPS、TCP/TLS、および GRPC/GRPCS プロトコルのネイティブプロキシをサポートします。前述のように、これらのプロトコルはそれぞれ異なるルーティング属性のセットを受け入れます。
-
http
:methods
。hosts
。headers
、paths
(https
の場合はsnis
) -
tcp
:sources
、destinations
(そしてtls
の場合はsnis
) -
grpc
:hosts
、headers
、paths
(そしてgrpcs
の場合はsnis
)
これらのフィールドはすべて オプション ですが、少なくとも 1つ を指定する必要があることに留意してください。
リクエストがルートにマッチする条件は以下のとおりです。
- リクエストには、構成された すべての フィールドを含める 必要があります 。
- リクエスト内のフィールド値の少なくとも1つは、構成済みの値と一致する 必要があります (フィールド構成は1つ以上の値を受け入れますが、リクエストが必要とするのは一致とみなされる値のうち1つのみです)
いくつかの例を見てみましょう。次のように設定されたルートについて考えてみます。
{
"hosts": ["example.com", "foo-service.com"],
"paths": ["/foo", "/bar"],
"methods": ["GET"]
}
このルートに一致する可能性のあるリクエストの一部は次のようになります。
GET /foo HTTP/1.1
Host: example.com
GET /bar HTTP/1.1
Host: foo-service.com
GET /foo/hello/world HTTP/1.1
Host: example.com
これら3つのリクエストはすべて、ルート定義で設定された条件をすべて満たしています。
しかし、以下のリクエストは設定された条件にマッチ しません 。
GET / HTTP/1.1
Host: example.com
POST /foo HTTP/1.1
Host: example.com
GET /foo HTTP/1.1
Host: foo.com
これら3つのリクエストはすべて、構成された条件の2つのみを満たします。最初のリクエストのパスは、構成されたpaths
のいずれとも一致せず、2つ目のリクエストのHTTPメソッド、3つ目のリクエストのHostヘッダーとも一致しません。
ルーティングプロパティの連携の仕組みを理解したところで、各プロパティを個別に調べてみましょう。
リクエストヘッダー
Kong Gateway は任意の HTTP ヘッダーによるルーティングをサポートします。この 機能の特別なケースとして、ホストヘッダーによるルーティングがあります。
Hostヘッダーに基づいたルーティングのリクエストは、特にこれが意図されたHTTP Hostヘッダーの使用方法であるため、Kong Gatewayを介してトラフィックをプロキシするための最も簡単な方法です。Kong Gatewayは、ルートエンティティのhosts
フィールド経由で実行するのを容易にします。
hosts
は複数の値を使用できますが、Admin APIから指定する場合はカンマ区切りである必要があり、JSONペイロードで次のように表現されます。
curl -i -X POST http://localhost:8001/routes/ \
-H 'Content-Type: application/json' \
-d '{"hosts":["example.com", "foo-service.com"]}'
レスポンス:
HTTP/1.1 201 Created
...
しかし、Admin APIはフォームURLエンコードされたコンテンツタイプもサポートしているので、
[]
表記を使用して配列を指定できます。
curl -i -X POST http://localhost:8001/routes/ \
-d 'hosts[]=example.com' \
-d 'hosts[]=foo-service.com'
レスポンス:
HTTP/1.1 201 Created
...
このルートのhosts
条件を満たすには、クライアントからのすべてのホストヘッダーは次のいずれかに設定する必要があります。
Host: example.com
または:
Host: foo-service.com
同様に、他のヘッダーをルーティングに使用できます。
curl -i -X POST http://localhost:8001/routes/ \
-d 'headers.region=north'
レスポンス:
HTTP/1.1 201 Created
Region
ヘッダーがNorth
に設定された受信リクエストは、そのルートに
ルーティングされます。
Region: North
ワイルドカードホスト名の使用
柔軟性を実現するために、Kong Gatewayを使用するとhosts
フィールドのワイルドカードを使用してホスト名を指定できるようになります。ワイルドカードホスト名を使用すると、一致するすべてのHostヘッダーが条件を満たすため、特定のルートと一致できます。
ワイルドカードのホスト名には、 必ず 、左端にアスタリスクを 1つのみ 、 または 右端にドメインのラベルを含めます。 以下に例を示します。
-
*.example.com
であれば、a.example.com
やx.y.example.com
のような Host値がマッチします。 -
example.*
であれば、example.com
やexample.org
のようなホストの値がマッチします。
完全な例は次のようになります。
{
"hosts": ["*.example.com", "service.com"]
}
これにより、次のリクエストがこのルートに一致するようになります。
GET / HTTP/1.1
Host: an.example.com
GET / HTTP/1.1
Host: service.com
preserve_host
プロパティ
プロキシ時の Kong Gateway のデフォルトの動作は、
サービスの host
で指定されたホスト名に、上流リクエストのホストのヘッダーを設定します。preserve_host
フィールドは、 Kong Gatewayにそうしないように指示するブールフラグを受け入れます。
たとえば、preserve_host
プロパティが変更されておらず、ルートがそのように
構成されている場合:
{
"hosts": ["service.com"],
"service": {
"id": "..."
}
}
クライアントからKong Gatewayへのリクエストは、次のようなものが考えられます。
GET / HTTP/1.1
Host: service.com
Kong Gatewayはサービスのhost
プロパティからホストヘッダー値を抽出し、
次のアップストリームリクエストを送信します。
GET / HTTP/1.1
Host: <my-service-host.com id="sl-md0000000">
ただし、 preserve_host=true
を使用してルートを明示的に構成すると、次のようになります。
{
"hosts": ["service.com"],
"preserve_host": true,
"service": {
"id": "..."
}
}
そして、クライアントからの同じ要求を想定すると次のようになります。
GET / HTTP/1.1
Host: service.com
Kong Gatewayは、クライアントのリクエストのホストを保持し、代わりに、次のアップストリームリクエストを送信します。
GET / HTTP/1.1
Host: service.com
追加のリクエストヘッダー
Host
以外のヘッダーによってリクエストをルーティングすることも可能です。
これを行うには、ルートでheaders
プロパティを使用します。
{
"headers": { "version": ["v1", "v2"] },
"service": {
"id": "..."
}
}
次のようなヘッダーを持つリクエストがあるとします。
GET / HTTP/1.1
version: v1
このリクエストは、サービスにルーティングされます。次の場合も同じことが起こります。
GET / HTTP/1.1
version: v2
ただし、このリクエストはサービスにルーティングされません。
GET / HTTP/1.1
version: v3
注 :headers
キーは論理値AND
で、値は論理値OR
です。
リクエストパス
ルートを一致させる別の方法は、リクエストパスを使用することです。この
ルーティング条件を満たすには、クライアントリクエストの正規化されたパスには、paths
属性の値の次のいずれかを接頭辞に
付ける必要があります 。
たとえば、ルートが次のように構成されているとします。
{
"paths": ["/service", "/hello/world"]
}
次のリクエストが一致します。
GET /service HTTP/1.1
Host: example.com
GET /service/resource?param=value HTTP/1.1
Host: example.com
GET /hello/world/resource HTTP/1.1
Host: anything.com
これらのリクエストごとに、 Kong Gatewayは正規化されたURLパスにプレフィックスとしてルートのpaths
値のいずれかが付いていることを検出します。デフォルトでは、 Kong GatewayはURLパスを変更せずにリクエストをアップストリームにプロキシします。
パスプレフィックスを使用してプロキシする場合、 最長のパスが最初に評価されます 。これにより、2つのパス/service
と/service/resource
を持つ2つのルートを定義し、前者が後者を「シャドウ」しないようにできます。
パスでの正規表現の使用
パスが正規表現を見なされるためには、先頭に~
を付ける必要があります。
paths: ["~/foo/bar$"]
~
が先頭に付いていないパスはプレーンテキストとみなされます。
"paths": ["/users/\d+/profile", "/following"]
ルーターが正規表現を処理する方法の詳細については、Expressionsを使用する際のパフォーマンス上の考慮事項を参照してください。
評価の順序
ルーターは、ルートが設定されている Route
の regex_priority
フィールドを使用してルートを評価します。regex_priority
の値が大きいほど、優先順位が高くなります。
[
{
"paths": ["~/status/\d+"],
"regex_priority": 0
},
{
"paths": ["~/version/\d+/status/\d+"],
"regex_priority": 6
},
{
"paths": /version,
},
{
"paths": ["~/version/any/"],
}
]
このシナリオでは、 Kong Gatewayは、次の順序で定義されたURIに対して受信リクエストを評価します。
/version/\d+/status/\d+
/status/\d+
/version/any/
/version
正規表現の数が多いルーターは、他のルールを対象としたトラフィックを消費する可能性があります。正規表現は構築と実行に非常にコストがかかり、簡単に最適化することもできません。 ルーター式言語を使用して、複雑な正規表現を作成することを避けることができます。
の応答ヘッダーに一致したルートIDが示されます。
予期しない動作が見られる場合は、Kongデバッグヘッダーを使用して原因を追跡します。
-
kong.conf
でallow_debug_header: on
を設定します。 - トラブルシューティング目的で、リクエストヘッダーで
Kong-Debug: 1
を送信し、応答ヘッダーで一致したルートIDを示します。
通常どおり、リクエストはルートのhosts
およびmethods
プロパティと一致する必要があり、Kong Gatewayは最も多くのルールと一致するものが見つかるまでルートをトラバースします。
グループのキャプチャ
グループの取得もサポートされており、一致したグループはパスから抽出され、プラグインで使用できます。次の正規表現を考えてみましょう。
/version/(?<version id="sl-md0000000">\d+)/users/(?<user id="sl-md0000000">\S+)
そして、次のリクエストパス:
/version/1/users/john
Kong Gatewayはリクエストパスを一致とみなし、(他のルーティング属性を考慮したうえで)ルート全体が一致する場合、抽出される取得グループはngx.ctx
変数形式でプラグインから使用できます。
local router_matches = ngx.ctx.router_matches
-- router_matches.uri_captures is:
-- { "1", "john", version = "1", user = "john" }
特殊文字のエスケープ
次に、Regexで見つかる文字は、
RFC 3986などに応じた予約文字であることが多いため
、パーセントエンコード
する必要があります。Admin APIを 使用して正規表現パスでルートを設定する場合
、必要に応じて、ペイロードをURLエンコードしてください 。例えば、
curl
を使用し、 application/x-www-form-urlencoded
MIME タイプを使用します:
curl -i -X POST http://localhost:8001/routes \
--data-urlencode 'uris[]=/status/\d+'
レスポンス:
HTTP/1.1 201 Created
...
curl
はペイロードを自動的にURLエンコードしないことに注意してください。また、--data-urlencode
の使用により、Kong GatewayのAdmin APIによって +
文字がURLデコードされスペースとして解釈されることを防ぐことができます。
strip_path
プロパティ
ルートと一致するようにパスの接頭辞を指定するのが望ましいかもしれませんが、これを
アップストリームのリクエストに含めないでください。これを行うには、次のように設定してstrip_path
ブールプロパティを使用してください。
{
"paths": ["/service"],
"strip_path": true,
"service": {
"id": "..."
}
}
このフラグを有効にするとKong Gatewayが指示され、このルートを一致してサービスにプロキシする場合に、アップストリームリクエストのURLに一致したURLパスの一部が含まれては いけません 。たとえば、次のクライアントのリクエストを上記のルートに送信します。
GET /service/path/to/resource HTTP/1.1
Host: ...
これにより、Kong Gatewayは以下のアップストリームリクエストを送信します。
GET /path/to/resource HTTP/1.1
Host: ...
同じように、strip_path
が有効になっているルートで正規表現パスが定義されている場合、リクエスト URL マッチングシーケンス全体が削除されます。以下に例を示します。
{
"paths": ["/version/\d+/service"],
"strip_path": true,
"service": {
"id": "..."
}
}
指定されたRegexパスに一致する次のHTTPリクエスト:
GET /version/1/service/path/to/resource HTTP/1.1
Host: ...
次のように Kong Gateway で上流にプロキシされます。
GET /path/to/resource HTTP/1.1
Host: ...
正規化動作
単純なルートマッチのバイパスを防止するため、クライアントから受信するリクエストURIは、ルーターのマッチングが実施される前に、RFC 3986に従って必ず正規化されます。 具体的には、受信リクエストURIには次の正規化手法が使用されます。この手法が選択されるのは、リクエストURIのセマンティックを通常変更しないためです。
- パーセントエンコーディングされた3文字の組み合わせが大文字に変換されます。例:
/foo%3a
は/foo%3A
となります。 - 予約されていない文字のパーセントエンコーディングされた 3 文字の組み合わせがデコードされます。例:
/fo%6F
は/foo
となります。 - ドットセグメントは必要に応じて削除されます。例:
/foo/./bar/../baz
は/foo/baz
となります。 - 重複するスラッシュは統合されます。例:
/foo//bar
は/foo/bar
となります。
ルートオブジェクトの paths
属性も正規化されます。パスがプレーンテキストまたは正規表現パスの場合、まず最初に決定することで
達成されます。結果に基づいて、さまざまな正規化技術
が使用されます。
プレーンテキストのルートパスの場合:
上記と同じ正規化手法である1〜4が使用されます。
正規表現ルートパスの場合。
方法 1 と 2 のみが使用されます。さらに、デコードされた文字が正規表現 のメタ文字になる場合は、バックスラッシュでエスケープされます。
Kong Gatewayは、ルーターの一致を実行する前に、受信したリクエストURIを 正規化します。その結果、アップストリームのサービスに送信されるリクエストURIも、 元のURIセマンティックを保持する正規化された形式となります。
リクエストHTTPメソッド
methods
フィールドはHTTPメソッドに応じてリクエストをマッチングします。
複数の値を指定できますが、デフォルト値は空です(HTTPメソッドはルーティングには使用されません)。
次のルートはGET
とHEAD
経由のルーティングを許可します。
{
"methods": ["GET", "HEAD"],
"service": {
"id": "..."
}
}
このようなルートは、次のリクエストと照合されます。
GET / HTTP/1.1
Host: ...
HEAD /resource HTTP/1.1
Host: ...
しかし、POST
やDELETE
リクエストにはマッチしません。これにより、ルート上でプラグインを設定する際のより詳細な設定が可能になります。たとえば、同じサービスを指す2つのルートを想像してみます。1つ目は無制限で認証されていない
GET
リクエスト、2つ目は認証済みで流量制限されたPOST
リクエストのみを許可するとします(認証プラグインおよび流量制限プラグインをそのようなリクエストに適用することによる
)。
リクエスト元
注: このセクションは、TCPおよびTLSルートにのみ適用されます。
sources
ルーティング属性によって、
受信接続 IP および/またはポートソースのリストによるルートの照合が行われます。
次のルートは、送信元IP/ポートのリストを経由したルーティングを許可します。
{
"protocols": ["tcp", "tls"],
"sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}],
"id": "...",
}
上記ルートは、CIDR範囲”10.1.0.0/16”内にあるIPアドレスもしくはIPアドレス”10.2.2.2”から、またはポート”9123”から発信されるTCP接続またはTLS接続と一致します。
リクエスト先
注: このセクションは、TCPおよびTLSルートにのみ適用されます。
destinations
属性は、 sources
と同様に、
着信接続IPおよび/またはポートのリストによるルートのマッチングを許可しますが、
TCP/TLS 接続の宛先をルーティング属性として使用します。
SNI のリクエスト
安全なプロトコル(https
、grpcs
、またはtls
)を使用する場合は、サーバー
名表示はルーティング属性として使用できます。次のルートは
SNI経由のルーティングを許可します。
{
"snis": ["foo.test", "example.com"],
"id": "..."
}
TLS接続のSNI拡張子に設定されたホスト名と一致する受信リクエストは、このルートにルーティングされます。前述のように、SNIルーティングはTLSのみでなく、HTTPSなどTLSに伝送されるその他ののプロトコルにも適用され、複数のSNIがルートで指定されている場合、それらのいずれかは受信するリクエストのSNIと受信するリクエスト(名前間のOR)と一致する可能性があります。
SNIはTLSハンドシェイク時に示され、TLS接続が確立した後は変更できません。これは、例えば、同じkeepalive接続を再利用する複数のリクエストが、Host
ヘッダーに関係なく、ルーター照合を実行する間に同じSNIホスト名を持つことを意味します。
が設立されました。これは、複数のリクエストを送るkeepaliveコネクションが、ルーター照合中(Host
ヘッダーに関係なく)、同じSNIホスト名を持つことを意味します。
SNI と Host
ヘッダーマッチャーが一致しないルートを作成することは可能ですが、一般的には推奨されません。
優先順位の一致
ルートは、そのheaders
、hosts
、paths
、およびmethods
(さらに安全なルートである"https"
、"grpcs"
、"tls"
のsnis
)フィールドに基づいて一致ルールを定義する場合があります。Kong Gatewayが受信するリクエストをルートに一致させるには、既存のすべてのフィールドが満たされる必要があります。ただし、Kong Gatewayを使用すると、2つ以上のルートを同じ値が含まれているフィールドで構成できるようになり、これが発生すると、Kong Gatewayは優先度ルールを提供します。
ルールは次のとおりです。 リクエストを評価するとき、 Kong Gatewayは最初に最も多くの ルールを持つルートを一致させようとします 。
例えば、2つのルートが次のように設定されているとします。
{
"hosts": ["example.com"],
"service": {
"id": "..."
}
},
{
"hosts": ["example.com"],
"methods": ["POST"],
"service": {
"id": "..."
}
}
2番目のルートにはhosts
フィールド と methods
フィールドがあるため、
まず、Kong Gatewayによって評価されます。そうすることで、2番目のルートのために意図された呼び出しを最初のルートが「シャドーイング」しないようにすることができます。
したがって、このリクエストは最初のルートと一致します。
GET / HTTP/1.1
Host: example.com
そして、このリクエストは2つ目のリクエストと一致します:
POST / HTTP/1.1
Host: example.com
この理論に従うと、3 番目のルートが hosts
フィールド、methods
フィールド、uris
フィールドで構成する場合、まず
Kong Gateway によって評価されることになります。
与えられたリクエストのルール数が2つのルート A
とB
で同じ場合は
、次のタイブレーカールールが記載された順序で適用されます。ルート A
は、次の場合に B
よりも選択されます。
-
A
には「プレーンな」ホストヘッダーのみが含まれ、B
には「ワイルドカード」ホストヘッダーが1つまたは複数含まれる。 -
A
は、B
よりも多くの非ホストヘッダを持っています。 -
A
には “ 正規表現” パスが少なくとも 1 つあり、B
には “プレーン” パスしかありません。 -
A
の最長パスは、B
の最長パスよりも長くなります。 A.created_at < B.created_at
プロキシ動作
上記のプロキシルールは、Kong Gatewayが受信するリクエストをアップストリームサービスに転送する方法を詳述しています。以下では、 Kong GatewayがHTTPリクエストと登録されたルートを 一致させる ときと、リクエストが実際に 転送 されるときの間に内部で発生する内容を詳述しています。
ロードバランシング
Kong Gatewayは、アップストリームサービスのインスタンスのプール全体にわたるプロキシされたリクエストを分散するロードバランシング機能を実装します。
ロードバランシングの設定に関する詳細は、ロードバランシンリファレンスを参照してください。
プラグインを実行
Kong Gatewayは、プロキシされたリクエストのリクエスト/応答ライフサイクル内に組み込まれる「プラグイン」を介して拡張できます。 プラグインは、お使いの環境でさまざまな操作とプロキシされたリクエストで変換を実行できます。
プラグインは、グローバルに(すべてのプロキシトラフィックに対して)実行したり、あるいは特定のルートやサービス上で実行したりするように構成できます。どちらの場合も、Admin API 経由でプラグイン構成を作成する必要があります。
ルート(および関連するサービスエンティティ)が一致すると、Kong Gatewayは これらのエンティティのいずれかに関連するプラグインを実行します。ルートに構成されているプラグインは、 サービスに構成されているプラグインの前に実行されますが、それ以外は通常の プラグインの関連付けのルールが適用されます。
これらの設定済みのプラグインは access
フェーズを実行します。詳細は、プラグイン開発ガイドを参照してください。
プロキシとアップストリームのタイムアウト
Kong Gatewayが必要なロジックをすべて(プラグインを含む)を実行したら、リクエストをアップストリームサービスに転送する準備が完了します。これはNginxのngx_http_proxy_module
を介して行われます。以下のサービスのプロパティに従って、Kong Gatewayと特定のアップストリーム間の接続の希望のタイムアウトを構成できます。
-
connect_timeout
: アップストリームサービスへの接続を確立するためのタイムアウトをミリ秒単位で定義します。デフォルトは60000
です。 -
write_timeout
: リクエストを上流サービスに転送するための連続した2 つの 書き込み操作間のタイムアウトをミリ秒で 定義します。デフォルトは60000
です。 -
read_timeout
: アップストリームのサービスからリクエストを 受け取るための2つの連続する読み込み操作の間のタイムアウトをミリ秒単位で 定義します。デフォルトは60000
です。
Kong GatewayはHTTP/1.1経由でリクエストを送信し、次のヘッダーを設定します。
-
Host: <your_upstream_host id="sl-md0000000">
、このドキュメントで前述したとおりです。 -
Connection: keep-alive
アップストリーム接続の再利用を可能にします。 -
X-Real-IP: <remote_addr id="sl-md0000000">
ここでは、$remote_addr
は、ngx_http_core_moduleで提供された名前と同名の変数ベアリングです。$remote_addr
は ngx_http_realip_moduleによって上書きされる可能性が高いことにご注意ください。 -
X-Forwarded-For: <address id="sl-md0000000">
ここでは、<address id="sl-md0000000">
は、 同名のリクエストヘッダーに追加されたngx_http_realip_moduleによって提供された$realip_remote_addr
の内容です。 -
X-Forwarded-Proto: <protocol id="sl-md0000000">
ここでは<protocol id="sl-md0000000">
はクライアントが使用するプロトコルです。$realip_remote_addr
が 信頼できる アドレスの 1 つである場合は、同じ名前のリクエストヘッダーが提供されれば転送されます。それ以外の場合は、ngx_http_core_module が提供する$scheme
変数の値が使用されます。 -
X-Forwarded-Host: <host id="sl-md0000000">
。<host id="sl-md0000000">
はクライアントから送信されるホスト名です。$realip_remote_addr
が 信頼できる アドレスの1つである場合、同じ名前のリクエストヘッダーが提供されると転送されます。 それ以外の場合は、ngx_http_core_moduleが提供する$host
変数の値が使用されます。 -
X-Forwarded-Port: <port id="sl-md0000000">
ここは、リクエストを承認する<port id="sl-md0000000">
サーバーのポートです。$realip_remote_addr
が 信頼できる アドレスの1つである場合、同じ名前のリクエストヘッダーが提供されると転送されます。 それ以外の場合は、ngx_http_core_moduleが提供する$server_port
変数の値が使用されます。 -
X-Forwarded-Prefix: <path id="sl-md0000000">
、ここでは<path id="sl-md0000000">
はリクエストのパスであり、 Kong Gatewayによって承認されています。$realip_remote_addr
が 信頼できる アドレスの1つである場合は、 同じ名前のリクエストヘッダーが提供されていれば 転送されます。それ以外の場合は、ngx_http_core_moduleによって提供される$request_uri
変数の値( クエリ文字列は削除されます)が 使用されます。
注 :Kong Gateway は空のパスに
"/"
を返しますが、リクエストパスで他の正規化は行いません。
他のすべてのリクエストヘッダーはKong Gatewayによってそのまま転送されます。
唯一の例外となるのがWebSocketプロトコルを使用する場合です。その場合、Kong Gatewayはクライアントとアップストリームサービスの間のプロトコルをアップグレードできるように次のヘッダーを設定します。
Connection: Upgrade
Upgrade: websocket
このトピックに関する詳細は、 プロキシWebSocketトラフィックセクションで確認できます。
エラーと再試行
プロキシ中にエラーが発生すると、Kong Gateway はNginxの基本的な再試行メカニズムを使ってリクエストを次のアップストリームに渡します。
ここには、次の2つの構成可能な要素があります。
-
再試行回数:
retries
プロパティを使用してサービスごとに構成できます。詳細については、Admin APIを参照してください。 -
正確には何がエラーになるのか:ここでKong GatewayはNginxのデフォルトを使用しています。これは、サーバーとの接続を確立したり、サーバーにリクエストを渡したり、レスポンスヘッダーを読み取ったりする間に、エラー又はタイムアウトが発生することを意味します。
二つ目のオプションは、Nginxのproxy_next_upstream
ディレクティブに基づいています。このオプションは Kong Gatewayから直接設定することはできませんが、Nginx のカスタム設定を使って追加することができます。 詳細は設定リファレンスを参照してください。
応答
Kong Gatewayアップストリームサービスから受信した応答を、ストリーミング形式でダウンストリームクライアントに送信します。この時点でKong Gatewayは、header_filter
フェーズにフックを実装するルートやサービスに追加される後続プラグインを実行します。
登録されているすべてのプラグインの header_filter
フェーズが実行されると、Kong Gateway によって次のヘッダーが追加され、ヘッダー一式がクライアントに送信されます。
-
Via: kong/x.x.x
ここでは、x.x.x
は使用中の Kong Gateway バージョンです -
X-Kong-Proxy-Latency: <latency id="sl-md0000000">
。latency
は、Kong Gatewayがクライアントからリクエストを受信する時間からアップストリームサービスにリクエストを送信するまでの時間をミリ秒単位で示したものです。 -
X-Kong-Upstream-Latency: <latency id="sl-md0000000">
、latency
は、Kong Gatewayがアップストリームサービス応答の最初のバイトを待っていたミリ秒単位の時間です。
ヘッダーがクライアントに送信されると、Kong Gateway が body_filter
フックを実装するルートやサービスの登録済みプラグインの実行を開始します。Nginx のストリーミングの性質により、このフックは複数回呼び出される可能性があります。このような body_filter
フックによって正常に処理されたアップストリームレスポンスの各チャンクは、クライアントに送り返されます。body_filter
フックの詳細については、プラグイン開発ガイドを参照してください。
フォールバックルートの構成
Kong Gatewayのプロキシ機能によって提供される柔軟性の実用的なユースケースとして、「フォールバックルート」を実装してみます。これにより、Kong GatewayがHTTP 404
、「ルートが見つかりません」で応答するのを避けるために、このようなリクエストをキャッチして特別なアップストリームサービスにプロキシするか、プラグインを適用することができます(このようなプラグインは、たとえば、リクエストをプロキシせずに、別のステータスコードまたは応答でリクエストを終了できます)。
以下はこのようなフォールバックルートの例です。
{
"paths": ["/"],
"service": {
"id": "..."
}
}
ご想像のとおり、Kong GatewayへのHTTPリクエストはすべてこのルートに一致します。すべてのURIの先頭にはルート文字/
が付くためです。
リクエストパスセクションで学んだように、Kong Gatewayは最長URLパスを最初に評価します。一方、/
パスが
Kong Gatewayによって評価されるのは最後になり、実質的な「フォールバック」ルートとして最終手段としてのみ照合されます。
その後、トラフィックを特別なサービスに送信したり、このルートに任意に配置するプラグインに適用できます。
ルートのTLSの構成
Kong Gateway 、基礎接続ごとに TLS 証明書を動的に提供する手段を提供します。TLS 証明書はコアによって直接処理され、Admin API経由で 構成可能です。この機能を利用するには、TLS 経由でKong Gatewayに接続するクライアントがServer Name Indication拡張をサポートしている必要があります。
TLS 証明書は、Kong Gateway Admin API の 2 つのリソースによって処理されます。
-
/certificates
:キーと証明書が保存されます。 -
/snis
は、登録済みの証明書をサーバー名表示に関連付けます 。
これら2つのリソースに関するドキュメントは、Admin API参考資料を参照してください。
特定のルートでTLS証明書を構成する方法は次のとおりです。まず、TLS証明書とキーを Admin API経由でアップロードします。
curl -i -X POST http://localhost:8001/certificates \
-F "cert=@/path/to/cert.pem" \
-F "key=@/path/to/cert.key" \
-F "snis=*.tls-example.com,other-tls-example.com"
レスポンス:
HTTP/1.1 201 Created
...
snis
フォームパラメータは便利なパラメータです。内部的には、SNI を直接挿入し、アップロードされた証明書を SNI に関連付けます。
上記の snis
で定義されている SNI 名の 1 つにワイルドカードが含まれていることに注意してください
(*.tls-example.com
)。SNI の左端(プレフィックス)または
右端(サフィックス)にワイルドカードを 1 つ含めることもできます。これは、複数のサブドメインを管理する場合に便利です。それぞれ SNI を作成せずに、ワイルドカード名で構成された単一
の sni
を複数
のサブドメインの一致に使用できます。
有効なワイルドカードの位置は、mydomain.*
、 *.mydomain.com
、*.www.mydomain.com
です。
Kong Gateway構成の次のパラメータを使用して、デフォルトの証明書を追加できます。
または、SNIが*
のデフォルトの証明書を動的に構成します。
curl -i -X POST http://localhost:8001/certificates \
-F "cert=@/path/to/default-cert.pem" \
-F "key=@/path/to/default-cert.key" \
-F "snis=*"
レスポンス:
HTTP/1.1 201 Created
...
snis
のマッチングは、以下の優先順位が優先されます。
- 正確なSNIの一致証明書
- 接頭辞ワイルドカードによる証明書の検索
- サフィックスワイルドカードによる証明書の検索
- SNIに関連付けられている証明書の検索
*
- ファイルシステム上のデフォルトの証明書
ここで、次のルートを Kong Gateway内に登録する必要があります。このルートへのリクエストは、以下のように、便宜上Hostヘッダーのみを使ってマッチさせます。
curl -i -X POST http://localhost:8001/routes \
-d 'hosts=prefix.tls-example.com,other-tls-example.com' \
-d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd'
レスポンス:
HTTP/1.1 201 Created
...
これで、ルートがKong GatewayによってHTTPS経由で提供されることが期待できます。
curl -i https://localhost:8443/ \
-H "Host: prefix.tls-example.com"
レスポンス:
HTTP/1.1 200 OK
...
接続を確立し、TLSハンドシェイクをネゴシエートする際に、クライアントがSNI拡張子の一部としてprefix.tls-example.com
を送信する場合、Kong Gatewayは以前に構成されたcert.pem
証明書を提供します。証明書はHTTPSとTLSの両方の接続向けです。
クライアントプロトコルの制限
ルートには、すべきクライアントプロトコルを制限する protocols
プロパティがあります
聞いてください。 この属性で設定できる値は、"http"
、
"https"
、 "grpc"
、 "grpcs"
、 "tcp"
、または"tls"
です。
http
と https
を含むルートは、両方のプロトコルのトラフィックを受け入れます。
{
"hosts": ["..."],
"paths": ["..."],
"methods": ["..."],
"protocols": ["http", "https"],
"service": {
"id": "..."
}
}
プロトコルを指定しない場合でも、ルートはデフォルトで
["http", "https"]
になるため、同じ効果があります。
ただし、https
のみ のルートでは、HTTPS経由のトラフィック のみ が許可されます。また、信頼できるIPによってTLS終了が以前に 発生した場合 は、暗号化されていないトラフィック も 許可されます。TLS終了は、リクエストがtrusted_ipsの構成済みのIPのいずれかから送信された場合と、X-Forwarded-Proto: https
ヘッダーが設定されている場合に有効と見なされます。
{
"hosts": ["..."],
"paths": ["..."],
"methods": ["..."],
"protocols": ["https"],
"service": {
"id": "..."
}
}
上記のようなルートがリクエストに一致したが、そのリクエストが 有効な事前の TLS 終了のないプレーンテキストの場合、 Kong Gateway次のように応答します。
HTTP/1.1 426 Upgrade Required
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: Upgrade
Upgrade: TLS/1.2, HTTP/1.1
Server: kong/x.y.z
{"message":"Please use HTTPS protocol"}
生のTCP(必ずしもHTTPである必要なし)向けルートは、protocols
属性で"tcp"
を使用して作成できます。
{
"hosts": ["..."],
"paths": ["..."],
"methods": ["..."],
"protocols": ["tcp"],
"service": {
"id": "..."
}
}
同様に、"tls"
値を使用して、生のTLSトラフィック(必ずしもHTTPSではない)を
受け入れるルートを作成することもできます。
{
"hosts": ["..."],
"paths": ["..."],
"methods": ["..."],
"protocols": ["tls"],
"service": {
"id": "..."
}
}
TLS
のみ のルートでは、TLS経由のトラフィック のみ が許可されます。
TCP と TLS の両方を同時に受け入れることもできます。
{
"hosts": ["..."],
"paths": ["..."],
"methods": ["..."],
"protocols": ["tcp", "tls"],
"service": {
"id": "..."
}
}
L4 TLSプロキシが動作するためには、tls
protocol
を受け入れるルートを作成し、適切なTLS証明書をアップロードし、そのsni
属性が着信コネクションのSNIと一致するように適切に設定されている必要があります。設定方法については、ルートのTLS設定セクションを参照してください。
WebSocketトラフィックのプロキシ
Kong Gatewayは、基盤となるNginx実装のおかげでWebSocketトラフィックをサポートします。クライアントとアップストリームサービスの間でKong Gatewayを 介して WebSocket接続を確立したい場合、WebSocketハンドシェイクを確立する必要があります。これは、HTTPアップグレードメカニズムを介して行われます。Kong Gatewayに行われたクライアントリクエストは以下のようになります。
GET / HTTP/1.1
Connection: Upgrade
Host: my-websocket-api.com
Upgrade: WebSocket
これにより、Kong Gatewayは、標準HTTPプロキシのホップバイホップの性質上、Connection
ヘッダーとUpgrade
ヘッダーを拒否するのではなく、アップストリームサービスに転送するようになります。
WebSocketプロキシモード
Kong GatewayでWebSocketトラフィックをプロキシする方法は2つあります。
- HTTP(S) サービスとルート
- WS(S) サービスとルート
HTTP(S) サービスとルート
http
および https
プロトコルを使用するサービスとルートは、特別な構成を行わなくても WebSocket 接続を処理できます。この方法では、WebSocket セッションは通常のHTTPリクエストと同じように動作し、リクエスト/レスポンスのデータは不透明なバイトストリームとして扱われます。
services:
- name: my-http-websocket-service
protocol: http
host: 1.2.3.4
port: 80
path: /
routes:
- name: my-http-websocket-route
protocols:
- http
- https
WS(S) サービスとルート
HTTPサービスとルートに加え、 Kong Gateway Enterpriseには、
ws
(WebSocket-over-http) およびwss
(WebSocket-over-https) オプション
サービスprotocol
、ルートprotocols
が含まれます。http
/ https
とは対照的に、 ws
およびwss
サービスは、基盤となるWebSocket接続を完全に制御します。
つまり、WebSocketプラグインとWebSocket PDKを使って、メッセージ単位でビジネスロジックを実行できます(メッセージ検証、アカウンティング、流量制限など)。
services:
- name: my-dedicated-websocket-service
protocol: ws
host: 1.2.3.4
port: 80
path: /
routes:
- name: my-dedicated-websocket-route
protocols:
- ws
- wss
注記 :WebSocketメッセージのデコードと暗号化は、プロトコルに依存しない
http(s)
サービスの動作と比較した場合、ゼロでないパフォーマンスオーバヘッドの値が付属しています。APIにws(s)
サービスが提供する追加の機能が必要でない場合は、代わりにhttp(s)
サービスを使用することをおすすめします。
WebSocketとTLS
どのサービス/ルートが使用されているかに関係なく(http(s)
またはws(s)
)、
Kong GatewayはプレーンおよびTLS WebSocket接続を、それぞれ
http
およびhttps
のポートで受け入れます。クライアントからのTLS接続を強制するには、
ルートのprotocols
プロパティをhttps
またはwss
にのみ
設定します。
サービスがアップストリームWebSocketサービスを指すように設定する場合、Kong Gatewayとアップストリーム間で使用するプロトコルを慎重に選択する必要があります。
TLS を使用する場合は、サービス protocol
プロパティで https
(または wss
)プロトコルと適切なポート(通常は443)を使用して、アップストリーム WebSocket サービスを定義する必要があります。TLS を使用せずに接続するには、代わりに http
(または ws
)プロトコルとポート(通常は 80)を protocol
内で使用する必要があります。
Kong GatewayにTLSを終了させる場合、クライアントからのみhttps
/wss
を許可することができますが、アップストリームサービスはプレーンテキスト(http
またはws
)でプロキシします。
プロキシ gRPC トラフィック
gRPCプロキシはKong Gatewayでネイティブにサポートされています。gRPCサービスを管理し、Kong GatewayでgRPCリクエストをプロキシするには、gRPCサービスのサービスとルートを作成します。
gRPCでは、オブザーバビリティとロギングのプラグインのみがサポートされています。 -gRPCでサポートされているプラグインには、たとえば Kong Hubページの「サポートされているプロトコル」フィールドの下に記載されている”grpc”と”grpcs”があります。 File Logプラグインのページをチェックしてください。
プロキシ TCP/TLS トラフィック
TCP および TLS プロキシは Kong Gateway でネイティブでサポートされています。
このモードでは、stream_listen
エンドポイントに到達する受信接続のデータはアップストリームを通じて渡されます。TLS接続もこのモードを使用してクライアントから終了できます。
このモードを使用するには、stream_listen
を定義する以外に、プロトコルタイプがtcp
またはtls
の適切なルート/サービスオブジェクトを作成する必要があります。
Kong Gateway による TLS 終了が必要な場合は、次の条件を満たす必要があります。
- TLS接続が接続されるKong Gatewayポートでは、
ssl
フラグを有効にする必要があります - TLSの終了に使用できる証明書/キーはルートのTLSの構成内に表示されるよう、Kong Gateway内に存在する必要があります。
Kong Gatewayは接続しているクライアントのTLS SNIサーバー名拡張子を使用して、使用する適切なTLS証明書を見つけます。
サービス側では、Kong Gatewayとアップストリームサービス間の接続を
暗号化する必要があるかどうかに応じて、tcp
またはtls
のプロトコル型をそれぞれ設定できます。
つまり、このモードでは以下のすべてのセットアップがサポートされます。
- クライアント <- TLS -> Kong <- TLS -> アップストリーム
- クライアント<- TLS -> Kong<- Cleartext -> アップストリーム
- Client <- Cleartext -> Kong <- TLS -> Upstream
注: L4 プロキシモードでは、サポートされるプロトコルリスト内の、tcp
または tls
を保持するプラグインのみがサポートされます。このリストは、Kong Hub のそれぞれのドキュメントで確認できます。
プロキシ TLS パススルー トラフィック
Kong Gateway は、終了させることなく TLS リクエストをプロキシする、 SNI プロキシをサポートしています。
Kong Gateway接続している クライアントのTLS SNI拡張を使用して、一致するルートとサービスを検索し、 着信 TLS トラフィックを復号化せずに、完全なアップストリームの TLS 要求を転送します。
このモードでは次の手順を実行する必要があります。
- プロトコル
tls_passthrough
でルートおぷじぇくとを作成し、snis
フィールドを1つ以上のSNIに設定します。 - 対応するサービスオブジェクトのプロトコルを
tcp
に設定します。 -
stream_listen
ディレクティブにssl
フラグがあるポートにリクエストを送信します。
個別のSNIおよび証明書エンティティは必要なく、使用されません。
ルートが同時にtls
とtls_passthrough
プロトコルを一致させることはできません。ただし、同じSNIは異なるルートでtls
とtls_passthrough
を一致できます。
ルートをtls_passthrough
に設定し、サービスをtls
に設定することもできます。この
モードでは、アップストリームへの接続は TLS で 2 回暗号化されます。
注: このモードでプラグインを実行するには、プラグインの
protocols
フィールドがtls_passthrough
を含む必要があります。
結論
このガイドを通じて、リクエストが関連サービスにルーティングされるルートを照合する仕組みから、WebSocketプロトコルの使用を許可する方法、動的TLS証明書を設定する方法まで、Kong Gatewayの基礎となるプロキシのメカニズムについての知識を得ていただけたことを願っています。
このウェブサイトはオープンソースであり、 github.com/Kong/docs.konghq.com 。 この文書へのフィードバックや改善提案など、お気軽にお寄せください。
まだお読みでない場合は、これまで取り上げてきたトピックに密接に関連するロードバランシング参考資料を読むこともおすすめします。