Carpe Diem

備忘録

EnvoyのVirtual hostを読み解く

概要

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の走査順

以下の順で走査され、一致するものが先に適用されます。

  1. 完全一致:www.foo.com
  2. 後方一致:*.foo.com, *-bar.foo.com
  3. 前方一致:foo.*, foo-*
  4. ワイルドカード*

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/と設定することですべてのリクエストを対象とするパターンを用います。

headersqueryparametersを使うことで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
  1. domainsはワイルドカードなので全てのincomming requestが一致する
  2. routesは2つあるので先に一致するものが適用される
  3. /getというpath prefixを持つものがあればhttpbin clusterに流す
  4. 3以外のリクエストはdefault_root clusterに流す

と読み解けます。
先に一致したものが適用されるので、デフォルトルートは4のように最後に設定するようにしましょう。

サンプルコード

検証するためのサンプルコードです。

github.com

可視化のためのPrometheus & Grafanaも付いてます。

まとめ

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

参考