Envoy Gateway 核心概念:Gateway、Listener、Proxy 與 Route 家族一次搞懂

10 min read

很多人第一次看 Gateway API 會有一種感覺:名詞看起來不多,但腦袋像在看一群長很像的角色名字,分不清誰是主角、誰是路人。這篇就是來拆掉這個混亂感,順便把常見的 route 類型一次講清楚。

先看整體架構

Envoy Gateway 官方概念裡,整套系統可以拆成三層:

  • User Configuration:你寫的 Gateway API 資源與 Envoy Gateway 擴充 CRD
  • Envoy Gateway Controller:讀取資源、驗證、轉譯設定
  • Envoy Proxy:真正承接流量的資料面

這代表你平常改的,大多不是 Envoy Proxy 本體,而是「宣告你想要什麼」。
Envoy Gateway 會幫你把需求翻成 Envoy Proxy 可執行的設定。這就是它比手寫代理配置舒服的地方。

最重要的幾個角色

你先記這幾個就好:

  • GatewayClass:定義「這個叢集要用哪種 Gateway 實作」
  • Gateway:定義「入口開在哪、聽什麼協定、要不要 TLS」
  • 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. GatewayClass 說明由 Envoy Gateway 這個 controller 來接手
  2. Gateway 宣告有一個 HTTP 入口在 80
  3. HTTPRoute 說明 www.example.com 進來的請求要導去 backend:3000
  4. Envoy Gateway 會把這些宣告轉譯給 Envoy Proxy

每個欄位該怎麼理解

GatewayClass

它是叢集層級的入口類型定義。最關鍵的欄位通常是:

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

這行意思其實很單純:
「這個 GatewayClass 交給 Envoy Gateway controller 管。」

如果 controllerName 對不上,就像你訂便當卻寄到別家公司,沒人會接單。

Gateway

它定義「入口長什麼樣」。最常看的欄位是 listeners

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

這代表:

  • 開一個 listener 叫 http
  • 接 HTTP 流量
  • 對外監聽 80

如果要 HTTPS,通常就是再加一個 protocol: HTTPS 的 listener,後面再補上 TLS 設定。

Gateway 常見會管這些事:

  • 對外 port 與 protocol
  • 每個 listener 的 hostname
  • TLS 終止位置
  • 哪些 namespace 的 route 可以附掛

也就是說,Gateway 比較像平台入口設定,責任通常偏平台團隊。

Listener

這是很多初學者最容易忽略,但其實超重要的角色。

一個 listener 可以理解成 Gateway 上的一個對外入口插槽。它會定義:

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

範例:

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

這代表:

  • 這個入口叫 https
  • 接 HTTPS
  • 監聽 443
  • 專門服務 api.example.com

如果你有多個 listener,例如:

  • http for port 80
  • https for port 443
  • grpc for port 50051

那其實是在同一個 Gateway 上開了多個對外入口,各自能掛不同 route。

Envoy Proxy

很多人只看到 YAML,反而忘了真正在線上接流量的是 Envoy Proxy

它的角色是:

  • 接收 client request
  • 根據 Envoy Gateway 下發的設定做匹配
  • 把流量轉送到對應 backend
  • 處理 TLS、header、timeout、重試等資料面行為

所以你可以把 Envoy Gateway 理解為「控制平面」,把 Envoy Proxy 理解為「資料面 / Gateway Proxy」。

Route 家族

Route 不是只有 HTTPRoute 一種。這整個家族是 Gateway API 很核心的設計。

HTTPRoute

這是你最常寫、也最常改的部分。關鍵欄位有三個:

spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - name: backend
          port: 3000
  • parentRefs:掛到哪個 Gateway
  • hostnames:哪個 Host header 會匹配這條規則
  • backendRefs:匹配後送去哪個後端

這邊最容易搞混的是:
Gateway 不是拿來寫細路由的,真正決定「怎麼分流」的是 HTTPRoute

GRPCRoute

如果你處理的是 gRPC,GRPCRoute 會比硬拿 HTTPRoute 來湊更自然。

它的特色是可以根據:

  • gRPC hostname
  • gRPC service
  • gRPC method
  • header

來做匹配。

例如:

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

這種語意對 gRPC 服務來說很直觀,因為它不是只看 URL path,而是直接對齊 gRPC 的 service/method 模型。

官方文件也特別提醒:GRPCRouteHTTPRoute 在同一個 listener 上,如果 hostname 衝突,實作方應該拒絕其中一個。簡單講,HTTP 跟 gRPC 最好不要共用同一組 hostname 亂打架。

TCPRoute

TCPRoute 用來處理原始 TCP 流量。
這時 Gateway 不會像 HTTPRoute 一樣理解 path、header 這些 L7 語意,而是比較偏 L4 轉發。

它適合的場景通常是:

  • 非 HTTP 協定服務
  • 純 TCP 服務
  • 只想根據 listener port 把連線送到不同 backend

像資料庫協定、自訂 TCP 協定,這類就比較接近 TCPRoute 的使用場景。

TLSRoute

TLSRoute 是處理 TLS 流量的重要角色,特別常見在 TLS passthrough 場景。

它的核心概念是:

  • Gateway 不一定終止 TLS
  • 可能只根據 TLS handshake 裡的 SNI hostname 做分流
  • 加密流量一路保留到 backend 再解

這對某些需要端到端加密、或不想在 Gateway 終止 TLS 的場景很重要。

怎麼選 Route 類型

需求 該用什麼
網站、REST API、一般 Web 流量 HTTPRoute
gRPC service / method 路由 GRPCRoute
純 TCP 流量 TCPRoute
TLS passthrough / SNI-based routing TLSRoute

這張表很重要,因為很多人一看到 route 就先下意識寫 HTTPRoute。但你如果實際處理的是 gRPC 或 TCP,硬塞進 HTTPRoute 只會越寫越彆扭。

Route 為什麼比 Ingress 好懂

以前 Ingress 很常把很多責任擠在同一個資源裡,長久下來就容易有幾個痛點:

  • 平台設定和應用路由混在一起
  • 高級功能靠 annotation 表達,可讀性差
  • 對不同協定的表達能力有限

而 Gateway API 的思路是拆責任:

  • 平台團隊可以管理 GatewayClass / Gateway
  • 應用團隊可以管理自己的 HTTPRoute

這種拆法很適合多人協作。你不用每次改一條 path,就去碰整個入口層設定,團隊之間互相踩腳的機率會低很多。

你要開始注意的狀態

除了 spec,你也要慢慢養成看 status 的習慣。尤其是 HTTPRouteGateway

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

通常先看:

  • route 有沒有被 Accepted
  • gateway listener 有沒有 Ready
  • address 有沒有分配成功

這很像看考卷成績單。不要只管有沒有交作業,還要看老師到底有沒有批改通過。

一句話總結

GatewayClassGatewayListenerRouteEnvoy Proxy 想成「誰來管、入口怎麼開、每個插槽怎麼接、流量怎麼分、最後誰執行」,你就已經抓到 80% 的核心概念了。

💡 初學者很容易一上來就鑽進 CRD 細節。先別急,先把這幾個角色分清楚,後面看各種 YAML 才不會每段都像第一次見面。

下一步

概念有了,下一篇開始玩最常見的 HTTP 路由場景:host、path、header、流量分配: 👉 HTTP 路由實戰