Envoy Gateway 核心概念:Gateway、Listener、Proxy 與 Route 家族一次搞懂
很多人第一次看 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這三段串起來後,邏輯是:
GatewayClass說明由Envoy Gateway這個 controller 來接手Gateway宣告有一個 HTTP 入口在80HTTPRoute說明www.example.com進來的請求要導去backend:3000Envoy 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 上的一個對外入口插槽。它會定義:
nameportprotocolhostnametlsallowedRoutes
範例:
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: api.example.com這代表:
- 這個入口叫
https - 接 HTTPS
- 監聽
443 - 專門服務
api.example.com
如果你有多個 listener,例如:
httpfor port 80httpsfor port 443grpcfor 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: 3000parentRefs:掛到哪個 Gatewayhostnames:哪個 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 模型。
官方文件也特別提醒:GRPCRoute 和 HTTPRoute 在同一個 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 的習慣。尤其是 HTTPRoute 跟 Gateway:
kubectl get gateway eg -o yaml
kubectl get httproute backend -o yaml通常先看:
- route 有沒有被
Accepted - gateway listener 有沒有 Ready
- address 有沒有分配成功
這很像看考卷成績單。不要只管有沒有交作業,還要看老師到底有沒有批改通過。
一句話總結
把 GatewayClass、Gateway、Listener、Route、Envoy Proxy 想成「誰來管、入口怎麼開、每個插槽怎麼接、流量怎麼分、最後誰執行」,你就已經抓到 80% 的核心概念了。
💡 初學者很容易一上來就鑽進 CRD 細節。先別急,先把這幾個角色分清楚,後面看各種 YAML 才不會每段都像第一次見面。
下一步
概念有了,下一篇開始玩最常見的 HTTP 路由場景:host、path、header、流量分配: 👉 HTTP 路由實戰