2026年K8s Gateway API遷移完全指南:從Ingress到Gateway API
2026年K8s Gateway API遷移完全指南:從Ingress到Gateway API
如果你在2026年還在用Kubernetes Ingress管理叢集流量,你正在錯過雲原生流量管理的未來。Gateway API在2025年底正式成為Kubernetes GA API,各大廠商(Istio、Contour、Traefik、Kong)已全面支援。Ingress的設計缺陷——單角色、擴充性差、無法表達複雜路由——在微服務規模爆炸的今天已經不可接受了。
Gateway API引入了Gateway、GatewayClass、HTTPRoute等角色分離的API,支援多團隊協作、多叢集部署、流量拆分和鏡像。本文將從架構對比開始,給出完整的遷移步驟,覆蓋流量管理、多租戶和多叢集場景。
為什麼Gateway API取代Ingress?
| 對比維度 | Ingress | Gateway API |
|---|---|---|
| API成熟度 | GA(但已停止演進) | GA(2025.11) |
| 角色分離 | 無(全由叢集管理員管理) | 三角色(基礎設施/叢集/應用) |
| 路由表達能力 | 有限(path+host) | 強大(header/query/weight/mirror) |
| 多協定支援 | 僅HTTP/HTTPS | HTTP/TLS/TCP/UDP/gRPC |
| 流量拆分 | 需要annotation hack | 原生支援(weight欄位) |
| 多租戶 | 不支援 | 原生支援(命名空間隔離) |
| 擴充性 | 依賴annotation | 原生擴充(PolicyAttachment) |
| 跨叢集 | 不支援 | 支援Multi-cluster Gateway |
核心差異:Ingress把所有設定混在一起,而Gateway API實現了角色分離——基礎設施團隊管GatewayClass,維運團隊管Gateway,開發團隊管Route。
一、架構對比
1.1 Ingress架構
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1/users(/|$)(.*)
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
問題:所有設定擠在一個Ingress物件裡,annotation滿天飛,不同廠商的annotation互不相容。
1.2 Gateway API架構
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
namespace: infra
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: user-route
namespace: app-team
spec:
parentRefs:
- name: api-gateway
namespace: infra
rules:
- matches:
- path:
type: PathPrefix
value: /v1/users
backendRefs:
- name: user-service
port: 8080
weight: 90
- name: user-service-canary
port: 8080
weight: 10
優勢:角色清晰——GatewayClass由平台團隊定義,Gateway由維運團隊設定,HTTPRoute由開發團隊管理。
二、逐步遷移指南
2.1 安裝Gateway API CRD
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
2.2 安裝控制器(以Istio為例)
istioctl install --set profile=minimal
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
EOF
2.3 遷移Ingress到Gateway+HTTPRoute
遷移腳本思路:
for ingress in $(kubectl get ingress -A -o name); do
namespace=$(echo $ingress | cut -d'/' -f1 | cut -d'.' -f1)
name=$(echo $ingress | cut -d'/' -f2)
kubectl get $ingress -o yaml | python3 ingress2gateway.py > gateway-route.yaml
kubectl apply -f gateway-route.yaml
echo "Migrated $ingress, verify before deleting"
done
2.4 自動化遷移工具
import yaml
import sys
def ingress_to_gateway_route(ingress_data):
metadata = ingress_data['metadata']
spec = ingress_data['spec']
gateway = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'Gateway',
'metadata': {
'name': f"{metadata['name']}-gateway",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'gatewayClassName': 'istio',
'listeners': [],
},
}
routes = []
for rule in spec.get('rules', []):
host = rule.get('host', '*')
listener_name = f"http-{host.replace('.', '-')}" if host != '*' else 'http'
gateway['spec']['listeners'].append({
'name': listener_name,
'port': 80,
'protocol': 'HTTP',
'hostname': host if host != '*' else None,
})
for path in rule.get('http', {}).get('paths', []):
route = {
'apiVersion': 'gateway.networking.k8s.io/v1',
'kind': 'HTTPRoute',
'metadata': {
'name': f"{metadata['name']}-route",
'namespace': metadata.get('namespace', 'default'),
},
'spec': {
'parentRefs': [{'name': f"{metadata['name']}-gateway"}],
'rules': [{
'matches': [{
'path': {
'type': 'PathPrefix',
'value': path.get('path', '/'),
}
}],
'backendRefs': [{
'name': path['backend']['service']['name'],
'port': path['backend']['service']['port']['number'],
}],
}],
},
}
routes.append(route)
return gateway, routes
if __name__ == '__main__':
ingress = yaml.safe_load(sys.stdin)
gw, routes = ingress_to_gateway_route(ingress)
for doc in [gw] + routes:
print('---')
print(yaml.dump(doc, default_flow_style=False))
三、流量管理
3.1 流量拆分(金絲雀發佈)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api/v2
backendRefs:
- name: api-v2-stable
port: 8080
weight: 95
- name: api-v2-canary
port: 8080
weight: 5
3.2 流量鏡像
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRouteFilter
metadata:
name: mirror-filter
spec:
type: RequestMirror
requestMirror:
backendRef:
name: api-mirror
port: 8080
3.3 基於Header的路由
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- headers:
- type: Exact
name: X-Feature-Flag
value: new-ui
backendRefs:
- name: frontend-v2
port: 80
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-v1
port: 80
3.4 gRPC路由
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-route
spec:
parentRefs:
- name: api-gateway
rules:
- matches:
- method:
service: "com.example.UserService"
method: "GetUser"
backendRefs:
- name: user-grpc-service
port: 50051
四、多叢集與多租戶
4.1 多叢集Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-cross-namespace
namespace: app-team
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: infra
to:
- group: ""
kind: Service
4.2 多租戶隔離
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tenant-a-gateway
namespace: tenant-a
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
租戶隔離策略對比:
| 策略 | 隔離級別 | 資源開銷 | 管理複雜度 | 適用場景 |
|---|---|---|---|---|
| 共享Gateway | Route級 | 低 | 低 | 小規模、信任租戶 |
| 命名空間隔離 | 命名空間級 | 中 | 中 | 中規模、一般隔離 |
| 獨立Gateway | Gateway級 | 高 | 高 | 大規模、強隔離需求 |
5個常見陷阱
| # | 陷阱 | 後果 | 解決方案 |
|---|---|---|---|
| 1 | 直接刪除Ingress再建立Gateway | 流量中斷 | 先並行執行,驗證後再刪除 |
| 2 | HTTPRoute引用其他命名空間的Gateway | 權限被拒 | 建立ReferenceGrant |
| 3 | Gateway的allowedRoutes設定過嚴 | Route無法綁定 | 檢查namespace selector |
| 4 | 忽略GatewayClass的參數 | 控制器行為不符預期 | 仔細閱讀GatewayClassSpec.parametersRef |
| 5 | 流量拆分weight總和不為100 | 行為未定義(實作相關) | 確認weight總和為100 |
10個常見錯誤排查
| # | 錯誤現象 | 可能原因 | 排查方法 |
|---|---|---|---|
| 1 | HTTPRoute的Parents條件為Accepted: False |
Gateway不允許該命名空間 | 檢查Gateway的allowedRoutes |
| 2 | 流量未到達後端 | Route匹配規則錯誤 | 用kubectl describe httproute檢查ResolvedRefs |
| 3 | GatewayNotReady |
控制器未安裝或未執行 | 檢查GatewayClass和控制器Pod |
| 4 | TLS憑證未生效 | 憑證Secret不存在或格式錯誤 | 檢查Secret類型為kubernetes.io/tls |
| 5 | 金絲雀流量比例不對 | weight計算錯誤 | 確認weight總和為100且比例正確 |
| 6 | 跨命名空間引用被拒 | 缺少ReferenceGrant | 建立ReferenceGrant允許跨命名空間引用 |
| 7 | GRPCRoute不生效 | Gateway listener未設定H2C | 新增protocol: HTTP的listener並啟用H2C |
| 8 | 流量鏡像不工作 | 控制器不支援RequestMirror | 確認控制器實作支援該擴充 |
| 9 | Gateway IP未分配 | 控制器未設定LB | 檢查控制器的Service和LoadBalancer |
| 10 | 遷移後效能下降 | 控制器設定未優化 | 對比Ingress和Gateway的代理設定 |
工具推薦
在Gateway API遷移過程中,以下工具可以幫助你處理設定和編碼問題:
- JSON格式化工具 — 格式化Gateway API的Status和條件資訊,方便除錯路由狀態
- Base64編碼工具 — 對TLS憑證和密鑰進行Base64編碼,用於Kubernetes Secret
- 雜湊計算工具 — 為Gateway設定產生版本指紋,用於設定變更偵測和復原判斷
總結:Gateway API不是Ingress的「升級版」,而是流量管理的「重新設計」。三角色分離讓平台、維運、開發各司其職;原生流量拆分讓金絲雀發佈不再依賴annotation hack;多協定支援讓gRPC和TCP服務也能享受統一的流量管理。2026年,Ingress已經進入維護模式,Gateway API是唯一的方向。遷移的核心原則:先並行、再驗證、最後切換——不要一步到位,讓Ingress和Gateway API共存一段時間,確認流量正常後再移除Ingress。
本站提供瀏覽器本地工具,免註冊即可試用 →