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。

本站提供瀏覽器本地工具,免註冊即可試用 →

#K8s Gateway API#Ingress迁移#服务网格#流量管理#2026