概要
EnvoyのルーティングはListener > Network filter chain > HCM(HTTP connection manager)のVirtual Hostで適用されます。

設定の一部は配列で複数設定することができますが、ものによっては
- 一致率が高いものから順に適用する(完全一致→部分一致→ワイルドカードなど)
- 先に設定した順で走査し、マッチしたものを適用する
といった違いがあったりなど、きちんと理解していないとハマることがあるので1つ1つ読み解いていきます。
環境
- Envoy v1.24.0
解説
例えば以下のような設定があるときに「これだけ知っておけばとりあえず大丈夫」な最低限理解しておく必要があるものを書いていきます。
route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - name: get match: { prefix: "/get" } route: cluster: httpbin timeout: 30s - name: default match: { prefix: "/" } route: cluster: default_root timeout: 30s
設定項目
よく使うものだけ解説します。それ以外の詳細はリンクのドキュメントを参照してください。
config.route.v3.VirtualHost
| 項目 | 型 | 説明 | required |
|---|---|---|---|
| name | string | Virtual Hostの論理名。statsなどで使われる。ルーティング自体とは無関係 | o |
| domains | repeated string | ドメイン名。incoming requestと一致するドメインに振り分ける。ワイルドカードが利用でき、走査順は後述。 | o |
| routes | repeated config.route.v3.Route | incoming requestに対するルーティングリスト。先頭から順に走査し先に一致したものが適用される。詳細は後述。 | x |
domainsの走査順
以下の順で走査され、一致するものが先に適用されます。
- 完全一致:
www.foo.com - 後方一致:
*.foo.com,*-bar.foo.com - 前方一致:
foo.*,foo-* - ワイルドカード:
*
config.route.v3.Route
| 項目 | 型 | 説明 | required |
|---|---|---|---|
| name | string | ルーティング名 | x |
| match | config.route.v3.RouteMatch | domainsで一致したリクエストの内、さらにpathやheaderで一致するものを適用する。詳細は後述 |
o |
| route | config.route.v3.RouteAction | リクエストをどのclusterに流すか、timeoutなど設定を行う。詳細は後述 | x |
config.route.v3.RouteMatch
どのルーティングに一致させるかの設定です。
| 項目 | 型 | 説明 | required |
|---|---|---|---|
| prefix | string | pathが前方一致するものを対象とする | x |
| path | string | pahtが完全一致するものを対象とする | x |
| headers | repeated config.route.v3.HeaderMatcher |
headerが一致するものを対象とする。複数ある場合は全て満たすものが対象となる。:methodや:pathのような予約語もあり、HTTP header以外も設定可能 |
x |
| query_parameters | repeated config.route.v3.QueryParameterMatcher |
クエリパラメータが一致するものを対象とする。複数ある場合は全て満たすものが対象となる | x |
RouteMatchは以下の設定の少なくともどれか1つは必要です。
- prefix
- path
- safe_regex
- connect_matcher
- path_separated_prefix
- path_match_policy
通常はprefixで/と設定することですべてのリクエストを対象とするパターンを用います。
headersやqueryparametersを使うことでABテストを簡単に導入できます。
gRPCのpathを設定するには?
gRPCでは以下の文法で設定します。
/package{.subpackage}.ServiceName/RpcName
ref: https://github.com/grpc/grpc-web/issues/702#issuecomment-588121877
なので
syntax = "proto3"; package helloworld; service Greeter { rpc SayHello(HelloRequest) returns (HelloReply) {} rpc SayHi(HiRequest) returns (HiReply) {} }
といったproto定義であれば以下のようになります。
| ケース | 設定方法 |
|---|---|
| パッケージのみ一致させたい | /helloworld |
| gRPCサービス名まで指定したい | /helloworld.Greeter |
| gRPCの特定メソッドだけ指定したい | /helloworld.Greeter/SayHello |
一部のメソッドだけretry policyを設定した、timeoutを変更したいといった場合に有用です。
config.route.v3.RouteAction
ルーティング先の設定です。
| 項目 | 型 | 説明 | required |
|---|---|---|---|
| cluster | string | clusterディレクティブで定義したcluster名 | x |
| timeout | Duration | タイムアウト | x |
| prefix_rewrite | string | pathのrewrite処理を適用できる | x |
| weighted_clusters | config.route.v3.WeightedCluster | 重み付けした負荷分散が可能 | x |
| retry_policy | config.route.v3.RetryPolicy | リトライ方針 | x |
演習
では最初の設定を元に解説を行います。
route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - name: get match: { prefix: "/get" } route: cluster: httpbin timeout: 30s - name: default match: { prefix: "/" } route: cluster: default_root timeout: 30s
- domainsはワイルドカードなので全てのincomming requestが一致する
- routesは2つあるので先に一致するものが適用される
/getというpath prefixを持つものがあればhttpbin clusterに流す- 3以外のリクエストはdefault_root clusterに流す
と読み解けます。
先に一致したものが適用されるので、デフォルトルートは4のように最後に設定するようにしましょう。
サンプルコード
検証するためのサンプルコードです。
可視化のためのPrometheus & Grafanaも付いてます。

まとめ
EnvoyのVirtual Hostについて解説しました。