Envoy Gateway コア概念: Gateway、Listener、Proxy、Route ファミリーを整理する

12 min read

Gateway API を初めて見たとき、多くの人はこう感じます。「用語の数はそこまで多くないのに、似た名前の登場人物が一気に出てくる感じで、誰が主役で誰が脇役かわからない。」この記事はその混乱を切り分けるためのものです。あわせて代表的な route type も一通り整理します。

全体アーキテクチャ

Envoy Gateway の公式概念では、全体を 3 層に分けています。

  • User Configuration: あなたが書く Gateway API リソースと Envoy Gateway 拡張 CRD
  • Envoy Gateway Controller: リソースを読み、検証し、設定へ変換する
  • Envoy Proxy: 実際にトラフィックを処理するデータプレーン

つまり、普段あなたが編集するのは Envoy Proxy そのものではなく、「どうしたいかの宣言」です。 Envoy Gateway がその宣言を Envoy Proxy が実行できる設定に変換します。これが proxy 設定を手で書くより気持ちよい理由です。

主要な役割

今はこの対応関係だけ覚えておけば十分です。

  • GatewayClass: 「この cluster でどの Gateway 実装を使うか」を定義する
  • Gateway: 「入口がどこにあり、どの protocol を話すか」を定義する
  • Listener: 特定の port/protocol/hostname の入口スロットを定義する
  • Route: 「どのリクエストをどの Service に送るか」を定義する
  • Envoy Proxy: 実際にトラフィックを受けて転送する Gateway Proxy

平たく言うと:

  • GatewayClass は仕様書
  • Gateway は建物の正面入口
  • Listener は受付窓口
  • Route は館内の案内表示
  • Envoy Proxy は入退室管理と案内を実行するセキュリティシステム

このどれか一つが欠けても、トラフィックは意図した場所へ届きません。

全体像が見える最小 YAML

理解しやすい最小例を見ましょう。

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000

連鎖としてはこうなります。

  1. GatewayClassEnvoy Gateway controller を担当者として示す
  2. Gateway が port 80 の HTTP 入口を 1 つ宣言する
  3. HTTPRoutewww.example.com へのリクエストを backend:3000 に送ると定義する
  4. Envoy Gateway がこれらをまとめて Envoy Proxy 用に変換する

各 field の理解

GatewayClass

これは cluster-level の入口タイプ定義です。最重要 field はたいていこれです。

spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

意味は単純です。 「この GatewayClass は Envoy Gateway controller に管理される。」

controllerName が一致しないと、配達先を別会社にしているようなものです。誰も受け取りません。

Gateway

これは「入口がどう見えるか」を定義します。最もよく参照する field は listeners です。

listeners:
  - name: http
    protocol: HTTP
    port: 80

意味は次の通りです。

  • http という名前の listener を開く
  • HTTP トラフィックを受ける
  • 外部向けに port 80 を listen する

HTTPS なら、通常は protocol: HTTPS の listener を追加し、TLS 設定を付けます。

Gateway がよく管理するもの:

  • 外部向けの port と protocol
  • listener ごとの hostname
  • TLS termination の位置
  • どの namespace の route を attach 可能にするか

Gateway は app 側というより platform 層の関心事であることが多く、所有者も platform team になるのが一般的です。

Listener

初心者に最も見落とされやすい役割ですが、実はかなり重要です。

listener は Gateway 上の外向き入口スロットです。次を定義します。

  • name
  • port
  • protocol
  • hostname
  • tls
  • allowedRoutes

例:

listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: api.example.com

意味:

  • このスロット名は https
  • HTTPS を受ける
  • port 443 を listen する
  • api.example.com 専用

たとえば複数 listener を持つなら:

  • port 80 用の http
  • port 443 用の https
  • port 50051 用の grpc

同じ Gateway の中に複数の入口スロットを開いており、それぞれに別の route を attach できます。

Envoy Proxy

YAML ばかり見て、実際にライブトラフィックを処理するのが Envoy Proxy だという点を忘れる人は少なくありません。

役割は次の通りです。

  • クライアントリクエストを受ける
  • Envoy Gateway から push された設定にマッチさせる
  • 適切な backend へ転送する
  • TLS、header、timeout、retry などの data-plane 振る舞いを処理する

なので、Envoy Gateway は「control plane」、Envoy Proxy は「data plane / Gateway Proxy」と考えると整理しやすいです。

Route ファミリー

RouteHTTPRoute だけではありません。このファミリー全体が Gateway API の中心です。

HTTPRoute

最もよく書き換えるのはこれです。代表的な 3 field は次の通りです。

spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000
  • parentRefs: どの Gateway に attach するか
  • hostnames: どの Host header がこのルールを発火させるか
  • backendRefs: マッチしたリクエストをどこへ送るか

よくある誤解は、細かいルーティングを Gateway に書くと思ってしまうことです。実際に「どう振り分けるか」を決めるのは HTTPRoute のほうです。

GRPCRoute

gRPC を扱うなら、無理に HTTPRoute に押し込むより GRPCRoute のほうが自然です。

マッチできる対象:

  • gRPC hostname
  • gRPC service
  • gRPC method
  • headers

例:

matches:
  - method:
      service: com.example.User
      method: Login

この意味論は gRPC に自然に一致します。単なる URL path ではなく、gRPC の service/method モデルそのものにマッチできます。

公式ドキュメントでも、GRPCRouteHTTPRoute が同じ listener を共有し、hostname が衝突した場合は実装側が片方を reject すべきだとされています。要するに、HTTP と gRPC に同じ hostname の取り合いをさせないことです。

TCPRoute

TCPRoute は生の TCP トラフィックを扱います。 HTTPRoute と違って L7 の path や header は理解しません。L4 に近い転送です。

向いている場面:

  • 非 HTTP protocol の service
  • 純粋な TCP service
  • listener port だけを見て異なる backend へ接続を振り分ける

独自 protocol の database や proprietary な TCP protocol は TCPRoute の典型例です。

TLSRoute

TLSRoute は TLS トラフィックを扱い、特に TLS passthrough の場面でよく使われます。

コア概念:

  • Gateway が TLS を終端しない場合がある
  • TLS handshake の SNI hostname だけでルーティングすることがある
  • 暗号化トラフィックを backend までそのまま保つ

これは、end-to-end の暗号化が必要な場面や、Gateway で TLS を終端したくない場面で重要です。

Route type の選び方

要件 使うもの
Web サイト、REST API、一般的な web traffic HTTPRoute
gRPC service/method routing GRPCRoute
生の TCP トラフィック TCPRoute
TLS passthrough / SNI ベース routing TLSRoute

この表が大事なのは、多くの人が何でも HTTPRoute で書き始めてしまうからです。実際には gRPC や TCP を扱っているのに HTTPRoute に押し込むと、YAML がどんどん不自然になります。

なぜ Route のほうが Ingress より整理しやすいのか

従来の Ingress 設定は 1 つのリソースに責務を詰め込みすぎることが多く、いくつかの痛みがありました。

  • Platform 設定と app routing が混ざる
  • 高度な機能が annotation で表現され、読みづらい
  • 非 HTTP protocol の表現力が弱い

Gateway API は責務を分ける方向で設計されています。

  • Platform team が GatewayClass / Gateway を管理する
  • App team が自分たちの HTTPRoute を管理する

この分離は複数人の協業でかなり効きます。path を変えるだけなのに入口全体を触る必要がなくなり、チーム同士で踏み合う事故が大きく減ります。

status を見る習慣をつける

spec だけでなく、徐々に status も見る習慣をつけましょう。特に HTTPRouteGateway は重要です。

kubectl get gateway eg -o yaml
kubectl get httproute backend -o yaml

最初は次を見るだけでも十分です。

  • route が Accepted されたか
  • gateway listener が Ready か
  • address が割り当てられたか

提出しただけで終わりにせず、採点されて合格したかまで見る。そんな感覚です。

一文まとめ

GatewayClassGatewayListenerRouteEnvoy Proxy を、「誰が管理し、入口がどう開き、各スロットがどうつながり、トラフィックがどう分かれ、誰が実行するのか」として捉えられれば、コア概念の 8 割はもう掴めています。

💡 初心者はすぐ CRD の細部に突っ込みがちです。でも焦らなくて大丈夫です。まずこの役割分担を整理すると、YAML が毎回初対面の他人に見える感じがかなり減ります。

次の一歩

概念が入ったので、次の記事では最もよく使う HTTP ルーティングを掘ります。host、path、header、traffic splitting です。 👉 実践 HTTP ルーティング