Kubernetes Gateway API 入門指南
在 Kubernetes 發展早期,將外部流量導入叢集內部的標準途徑是 Ingress。然而隨著微服務架構普及、組織團隊擴張以及流量治理需求日益複雜,Ingress 的局限性越來越明顯。
為了徹底解決這些結構性問題,Kubernetes 官方網路特別興趣小組(SIG-Network)推出了 Gateway API。它並非 Ingress 的小幅擴充,而是從 API 結構上將基礎設施、平台與業務應用的流量設定徹底解耦。
本文專為想要理解 Gateway API 的工程師與 SRE 設計,從核心架構出發,剖析傳統 Ingress 最令人困擾的「Annotation 地獄」,並提供實戰重構範例、遷移對照表與主流實作選型指南。
什麼是 Gateway API:從分租公寓到現代商辦
理解 Gateway API 的最快方式,是觀察它如何重新劃分網路資源的管理邊界。
如果把 Kubernetes 叢集比喻成一棟建築:
傳統 Ingress:老式分租公寓
大門由誰管、鑰匙發給誰、門口掛什麼告示,全都混雜在同一張合約(單一 Ingress 資源)上。如果住戶想要換個鎖(設定跨網域 CORS)或改門牌(URL 重寫),就得拿原子筆在合約空白處塗改(塞進 Annotation)。一旦塗改錯誤,可能導致整棟樓的門禁系統崩潰。
Gateway API:現代化商辦大樓
- 大樓建設公司(Infrastructure Provider):負責提供門禁閘機與電梯系統規格(
GatewayClass)。 - 大樓管委會與總務(Cluster Operator / SRE):負責在一樓大廳設置大門、配置警衛巡邏,並統一綁定大樓門牌與 SSL 憑證(
Gateway)。 - 各樓層進駐公司(Application Developer):每家公司各自決定走廊進來後的接待路線與各會議室轉發規則(
HTTPRoute),只要申請掛載到一樓大門即可,完全動不到大門本身的安全設定。
這種「各司其職、職責解耦」的設計,正是 Gateway API 架構設計的核心所在。
核心三大角色與 CRD 設計
Gateway API 透過 Kubernetes 自訂資源(CRD),將流量控制權責拆解為清晰的三層結構:
【1】基礎設施提供者(Infra Provider)
+-----------------------------------------------+
| GatewayClass: envoy-gateway, cilium |
+-----------------------------------------------+
| 定義底層實作規格
v
【2】叢集管理員 / 平台組(Cluster Admin / SRE)
+-----------------------------------------------+
| Gateway: Port 80/443, TLS cert, external IP |
+-----------------------------------------------+
| |
| | 允許 HTTPRoute 掛載
v v
【3】應用程式開發團隊(App Dev)
+----------------------+ +----------------------+
| HTTPRoute: orders | | HTTPRoute: users |
| /orders -> order-svc | | /users -> user-svc |
+----------------------+ +----------------------+
| |
v v
+----------------------+ +----------------------+
| Service: order-svc | | Service: user-svc |
+----------------------+ +----------------------+
這三種核心資源各自對應明確的角色邊界:
GatewayClass: 由基礎設施提供者或雲端廠商管理。宣告「這座閘道背後是用哪種底層技術實現」(例如 Envoy、Cilium 或是雲端供應商的 ALB),概念就像儲存系統中的StorageClass。Gateway: 由叢集管理員或平台工程團隊維護。代表實際對外接收流量的實體或虛擬入口(通常對應一組實體 Load Balancer 或 IP),負責定義監聽通訊埠(Port 80/443)、傳輸協定(HTTP/HTTPS/TCP)以及 TLS 憑證的掛載。HTTPRoute: 由各業務微服務開發團隊獨立撰寫。定義具體的流量轉發邏輯,例如「路徑為/api/v1/orders時轉發到order-svc」。開發者無須知道底層 LB 的真實 IP,只需在spec.parentRefs宣告掛載到哪個Gateway。
除了生產環境最核心的 HTTPRoute,官方規範亦針對其他通訊協定提供專屬路由(如已邁入 GA 的 GRPCRoute,以及 L4 傳輸層的 TCPRoute、UDPRoute 與 TLSRoute),按需選用。
為什麼 Ingress 不夠用了?三大結構性痛點
Ingress 最早在 2015 年隨 Kubernetes 1.1 加入。在微服務萌芽期,它成功提供了一種比 NodePort 和 LoadBalancer 更靈活且節省成本的 L7(HTTP)路由機制。
然而走過十年演進,現代生產環境的治理複雜度早已超越當時的架構預期,暴露出三大難以忽視的結構性痛點。
痛點一:惡名昭彰的「Annotation 地獄」
在 Ingress 的官方規範中,定義的屬性極其簡略,僅有 rules(網域與路徑)和 backend(目標 Service)。但實際線上業務幾乎不可避免需要進階功能:
- URL 重寫(Rewrite)與重新導向(Redirect)
- 跨來源資源共享(CORS)標頭控制
- 請求逾時(Timeout)與失敗重試(Retry)
- 金絲雀分流(Canary 發布比例)
- 頻寬限制與請求速率限制(Rate Limiting)
由於 Ingress 規格本身不支援這些設定,各大 Ingress Controller(如 NGINX、Traefik、HAProxy、Emissary)只能各自發明專屬的 metadata.annotations 來補足。這在維運實務中衍生出三大典型問題:
- 無型別檢查,拼字錯誤默默失效:
Annotation 屬於非結構化的字串鍵值。若不慎將
proxy-connect-timeout誤拼成proxy-connet-timeout,Kubernetes API Server 完全不會攔阻並回報成功;設定在線上默默失效,直到後端逾時故障才被察覺。 - 廠商鎖定(Vendor Lock-in),更換控制器代價高昂: NGINX 的 URL Rewrite 依賴正規表示式捕獲群組註解,Traefik 需要宣告專屬的 Middleware CRD,HAProxy 又有另一套標頭規則。一旦團隊決定從 Ingress-NGINX 遷移至其他方案,叢集內數百份 Ingress 必須全部重寫。
- 黑魔法堆疊,維護成本劇增: 單一 Ingress 檔案往往堆積數十行缺乏語意約束的 Annotation,無法進行正規單元測試與語法驗證,查修問題如同猜謎。
核心對比:字串註解 vs 強型別規格
以 URL 重寫與金絲雀分流為例,兩者的宣告哲學截然不同:
# 傳統 Ingress:依賴非標準字串註解,無型別檢查且語法隨 Controller 而異
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/$1
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
# Gateway API:一等公民 Filter 與原生權重,API Server 嚴格驗證 Schema
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /api
backendRefs:
- name: order-service-v1
port: 8080
weight: 80
- name: order-service-v2
port: 8080
weight: 20
在 Gateway API 中,無論底層採用哪一家 Controller,filters.urlRewrite 和 backendRefs.weight 都具備跨廠商一致的標準語意,由 API Server 在套用時嚴格驗證。
痛點二:單一資源導致跨團隊權責混雜
在 Ingress 架構下,整份 YAML 必須同時容納基礎設施設定(如 TLS 憑證 Secret 引用、全域 Host 網域)與業務開發設定(如微服務路徑映射)。
這種設計直接引發組織衝突:
- 業務開發團隊為了微調服務路由,必須獲得編輯 Ingress 的權限,可能不慎更動到全站共用的 TLS 憑證或全域逾時時間。
- 平台團隊為了維持穩定,只能收緊 Ingress 權限;結果開發團隊每次發布或調整路徑都得開單給 SRE,拖慢交付節奏。
Gateway API 透過 Gateway(SRE 管)與 HTTPRoute(業務團隊管)的徹底分離,配合 Kubernetes 原生 RBAC,讓權限劃分重歸清晰。
痛點三:受限的跨 Namespace 路由能力
微服務架構通常會將不同團隊的服務部署在各自獨立的 Namespace 中。
Ingress 預設只能將流量導向同一個 Namespace 內的 Service。若要將單一入口網域的不同路徑分流到跨 Namespace 的服務,往往得依賴特定 Controller 的私有註解或繁雜的 ExternalName 繞道方案。
Gateway API 原生支援跨 Namespace 掛載與細粒度授權:中央 Gateway 透過 allowedRoutes 控管哪些命名空間的 Route 允許掛載進來。
若進一步涉及跨 Namespace 存取敏感資源(例如 Gateway 引用其他命名空間的 TLS Secret,或 Route 轉發至不同命名空間的後端 Service),則由被存取方明確簽發 ReferenceGrant 授權,兼具彈性與安全性。
實戰重構:從 Ingress-NGINX 遷移至 Gateway API
為了將抽象觀念轉化為具體實作,我們以一個典型的微服務電商系統 shop.example.com 為例,對比同一個業務情境在兩代架構下的設定差異。
實戰情境設定
目標為線上商城建立對外入口,包含四項常見需求:
- 全站 HTTPS:統一掛載
shop-tls-secret憑證。 - 靜態前端:造訪根路徑
/時,轉發給前端靜態服務frontend-svc:80。 - 使用者服務(需 URL 重寫):外部請求
/api/v1/users,在轉發給後端user-svc:8080前需剝除前綴,重寫為/users。 - 訂單服務(金絲雀分流):造訪
/api/v1/orders時,新版本order-svc-v2:8080上線,需維持 80% 流量至舊版order-svc-v1、20% 流量導入新版。
改造前:Ingress-NGINX 的妥協寫法
在傳統 Ingress-NGINX 中,由於規格本身不支援單一規則內的權重切分,工程師被迫必須維護兩份獨立的 Ingress YAML:
檔案一:主 Ingress (shop-ingress-main.yaml 核心片段)
處理靜態前端、使用者服務重寫與基準版本訂單服務:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop-ingress-main
annotations:
# 為了 URL 重寫,必須開啟正規表示式並撰寫晦澀的捕獲群組
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
tls:
- hosts:
- shop.example.com
secretName: shop-tls-secret
rules:
- host: shop.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port: { number: 80 }
- path: /api/v1(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: user-svc
port: { number: 8080 }
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-svc-v1
port: { number: 8080 }
檔案二:金絲雀影子 Ingress (shop-ingress-canary.yaml 核心片段)
為了將 20% 流量導入新版本,必須額外複製一份結構雷同的 Ingress 並貼上分流標籤。
Ingress-NGINX controller 偵測到兩份 Ingress 指向相同 host,且其中一份帶有 canary: "true" 時,會自動將後者視為前者的金絲雀變體,依 canary-weight 比例分配流量:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop-ingress-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
tls:
- hosts:
- shop.example.com
secretName: shop-tls-secret
rules:
- host: shop.example.com
http:
paths:
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-svc-v2
port: { number: 8080 }
這套寫法存在明顯的維運隱患:主 Ingress 的 TLS 或 Hostname 若有調整,影子 Ingress 極易漏改而引發事故;而 rewrite-target: /$2 的正規表示式捕獲群組寫法晦澀,稍有不慎便會導致路徑匹配失敗。
改造後:Gateway API 的解耦重構
改用 Gateway API 後,所有設定回歸「誰管理、誰宣告」的職責邊界。
NOTE
Gateway API 並非 Kubernetes 內建資源,而是以 CRD 形式獨立發布。這是刻意的設計決策——正因為 Ingress 內建於核心、受限於 K8s 發布週期而難以演進,Gateway API 才選擇 CRD 路線,讓 SIG-Network 能獨立迭代。使用前需預先安裝標準 CRD(可透過官方 Release 安裝或由所屬 Controller 自動注入)。
步驟一:平台 / SRE 團隊定義「大門」(gateway.yaml)
SRE 僅宣告通訊埠、TLS 憑證與允許掛載的命名空間標籤。此處採用雙向交握模型:Gateway 透過 allowedRoutes 限定只有具備 app.kubernetes.io/part-of: shop 標籤的 Namespace 才能掛載,因此業務團隊的命名空間需預先設定相應標籤:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: external-gateway
namespace: infra-gateway
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: "shop.example.com"
tls:
mode: Terminate
certificateRefs:
- name: shop-tls-secret
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
app.kubernetes.io/part-of: shop
步驟二:前端團隊定義根路由(frontend-route.yaml)
前端工程師在所屬命名空間維護靜態資源路由:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: frontend-route
namespace: frontend
spec:
parentRefs:
- name: external-gateway
namespace: infra-gateway
hostnames:
- "shop.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-svc
port: 80
步驟三:使用者服務團隊定義路徑重寫(user-route.yaml)
捨棄晦澀的正規表示式,採用標準 URLRewrite 篩選器:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: user-route
namespace: user-app
spec:
parentRefs:
- name: external-gateway
namespace: infra-gateway
hostnames:
- "shop.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1/users
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /users
backendRefs:
- name: user-svc
port: 8080
步驟四:訂單服務團隊宣告金絲雀發布(order-route.yaml)
不再需要第二份影子 YAML,在單一規則內直接以 weight 宣告流量比例:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: order-route
namespace: order-app
spec:
parentRefs:
- name: external-gateway
namespace: infra-gateway
hostnames:
- "shop.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1/orders
backendRefs:
- name: order-svc-v1
port: 8080
weight: 80
- name: order-svc-v2
port: 8080
weight: 20
NOTE
多 Route 衝突裁決機制:上述三個 Route 皆宣告了相同的 shop.example.com,且前端 Route 佔據了根路徑 /。Gateway API 規格明定了確定性的最長前綴優先(Longest Prefix Match)與排序規則,因此 /api/v1/orders 與 /api/v1/users 會精準命中各自的服務,徹底消除了 Ingress 時代多份 YAML 合併順序未定義的覆蓋風險。
遷移對照表
下表整理了從 Ingress 遷移至 Gateway API 的核心概念轉變:
| 使用情境 | 傳統 Ingress (以 NGINX 為例) | Gateway API 標準做法 | 架構與維運優勢 |
|---|---|---|---|
| 通訊埠與 TLS 憑證 | 寫在各 Ingress 的 spec.tls,到處重複複製 | 集中於 Gateway.spec.listeners 由平台團隊控管 | 憑證安全邊界清晰,業務開發免碰 Secret |
| URL 重寫 (Rewrite) | rewrite-target 註解搭配 Regex 捕獲群組 | filters.type: URLRewrite 的 ReplacePrefixMatch | 宣告式直觀語法,支援 API 嚴格型別驗證 |
| 金絲雀分流 (Canary) | 需建立第二份影子 Ingress 並標註 canary: "true" | 同一 rules 的 backendRefs 直接標註 weight | 無須影子物件,分流設定集中不漏失 |
| 跨團隊/跨 Namespace | 預設僅能轉發同 Namespace 服務 | Gateway 宣告 allowedRoutes,Route 跨命名空間引用 | 原生支援多租戶微服務,權限分明 |
| 標頭匹配 (Header Match) | 仰賴控制器專屬 Annotation | rules.matches[].headers 一等公民支援 | 原生支援 A/B 測試與多條件金絲雀分流 |
| 重新導向 (Redirect) | permanent-redirect 專屬註解 | filters.type: RequestRedirect | 跨所有相容 Controller 語法一致 |
| 狀態感知與除錯 | 依賴 Controller 容器日誌,無原生狀態回饋 | 物件內建 status.conditions(如 Accepted、Programmed) | 宣告即感知,無需翻找 Controller 集中日誌 |
官方自動化遷移工具:ingress2gateway
若現有叢集內已累積大量 Ingress 資源,手動重寫耗時費力。Kubernetes SIG-Network 官方為此維護了自動化轉換工具 ingress2gateway。
工具核心優勢
- 多廠商支援:支援將 Ingress-NGINX、Kong、Istio、Traefik 等常見 Controller 的 Ingress 與 Annotations 自動翻譯為 Gateway 和 HTTPRoute。
- 純客戶端轉換:支援本機離線檔案轉換,亦可連線叢集即時讀取輸出。
常用指令範例
# 1. 安裝 CLI 工具 (可透過 Go 或 GitHub Release 下載)
go install github.com/kubernetes-sigs/ingress2gateway@latest
# 2. 轉換單一 Ingress 檔案並預覽 Gateway API 資源
ingress2gateway print --providers ingress-nginx --input-file shop-ingress-main.yaml
# 3. 批次轉換現有叢集 default 命名空間下的所有 Ingress
ingress2gateway print --providers ingress-nginx --namespace default > migrated-gateway.yaml
NOTE
ingress2gateway 能自動處理 80% 以上的標準路由、TLS 與基礎 Rewrite/Redirect 規則;但若包含冷門 Lua 腳本或深層專屬外掛,仍需進行人工驗證與金絲雀測試。
發展歷程與生產成熟度
Gateway API 歷經雲端原生社群多年的實務檢驗,在 2023 年底隨 v1.0.0 正式邁入 GA(一般可用),將 GatewayClass、Gateway 與 HTTPRoute 列為向後相容的穩定規範。
後續的 v1.1 版本將 GRPCRoute 納入 GA,並在實驗通道引入 Session 保持;後端 TLS 驗證(BackendTLSPolicy)則要到 v1.4 才正式 GA。
現狀評估
在現今(2026 年)的 Kubernetes 生態中,Gateway API 已完全具備生產級成熟度。歷經多個次版本的實務驗證,主流雲端平台與開源專案已全面將其納為標準支援對象。它已非前瞻實驗功能,而是正逐步取代 Ingress 的現行業界標準。
推薦工具與主流實作
在 Gateway API 架構中,Kubernetes 官方僅負責定義 API 規範(CRD),真正的底層網路封包轉發需由 Gateway Controller 實現。面對多元的社群實作,可依架構情境進行選型。
主要開源實作
- 通用架構與標準首選:Envoy Gateway 由 CNCF 官方發起,聚集 Envoy、Tetrate、VMware 等社群力量打造。完全以 Gateway API 作為本體設定介面,無舊有 Ingress 的歷史包袱;資料平面直接採用久經生產驗證的 Envoy Proxy,部署簡便且效能頂級,是自建叢集與標準開源架構的理想基石。
- 邊緣運算與輕量首選:Traefik 由 Traefik Labs 開發的 Go 語言反向代理,長年為 Rancher k3s 內建預設元件。單一二進位檔架構使記憶體開銷極低,且 Traefik v3 原生相容 Gateway API,允許在同一叢集內無縫混用既有 Ingress,是個人 Homelab 與邊緣裝置的輕量之選。
TIP
既有 Ingress-NGINX 使用者的選型考量:kubernetes/ingress-nginx 已由 Kubernetes 官方公告退役,自 2026 年 3 月起停止維護,且並無直接平移升級至 Gateway API 的路徑。評估遷移時,建議直接放眼 CNCF 旗艦的 Envoy Gateway,或評估 F5 官方推出的 NGINX Gateway Fabric。
務實的採用建議(KISS 原則)
- 全新專案與新建叢集:直接採用 Gateway API,推薦以 Envoy Gateway 或雲端託管 Controller 起步。
- 運作穩定的既有 Ingress 叢集:不必急於推翻重寫。Kubernetes 承諾 Ingress 規範將持續獲得維護。建議採漸進過渡策略:新業務導入 Gateway API,舊業務維持現狀,待有跨團隊權限重構或特殊流量調配需求時,再運用
ingress2gateway工具平滑切換。
結語
Gateway API 的核心價值,在於將流量治理回歸「權責清晰、強型別驗證」的現代宣告式架構。
告別非結構化字串的 Annotation 地獄,換取由 API Server 嚴格驗證的路由篩選器與跨 Namespace 權限邊界,能實質降低線上設定失誤並消除團隊間的工單摩擦。
對於維運團隊而言,無論是新建叢集直接導入,或是對既有叢集採取雙軌漸進遷移,掌握這套新世代規範都是提升平台工程成熟度的必經之路。