Gateway API 是 Kubernetes 官方推出的下一代路由和負載平衡 API。本文介紹如何在 ACK Edge 叢集中通過 Gateway with Inference Extension 組件配置 HTTP 路由、請求 Header 修改和按比例分發請求。
工作原理
Gateway with Inference Extension組件基於 Envoy Gateway專案構建,支援完整的Gateway API基礎能力及Envoy Gateway擴充資源。
Envoy Gateway 架構包括:
控制面:由 Envoy Gateway 組件構成,負責監聽叢集中的流量規則,動態建立和管理 Envoy 代理執行個體,並即時更新轉寄規則。控制面不直接參与業務流量轉寄。
資料面:由 Envoy Proxy 執行個體組成,負責處理和轉寄業務流量。
在ACK Edge叢集中,Envoy Gateway的部署方式與標準ACK叢集有所不同:
差異項 | 標準 ACK | ACK Edge |
服務暴露方式 | LoadBalancer | NodePort |
控制面部署 | 叢集層級 | 每個節點池各部署一套 |
資料面部署 | 叢集層級 | 按節點池維度部署 |
多節點池 | 共用一個 Gateway | 每個節點池需單獨建立 Gateway |
服務拓撲 | 無需配置 | 需配置 |
當前部署配置了節點池打散策略,可通過組件管理調節副本數,確保每個節點池至少運行一個控制面副本。

適用範圍
已建立叢集,且叢集版本為1.30及以上。
已安裝Gateway with Inference ExtensionGateway with Inference Extension組件。
準備工作
步驟一:建立測試應用
將下方樣本儲存到backend.yaml,執行 kubectl apply -f backend.yaml,建立測試應用backend和backend-2。
ACK Edge情境需要佈建服務拓撲。在Service中需添加 openyurt.io/topologyKeys: openyurt.io/nodepool 註解,確保流量只會轉寄到同一節點池內的Pod。詳情參見節點池服務拓撲管理。apiVersion: v1
kind: ServiceAccount
metadata:
name: backend
---
apiVersion: v1
kind: Service
metadata:
name: backend
annotations:
openyurt.io/topologyKeys: openyurt.io/nodepool # 配置節點池拓撲
labels:
app: backend
service: backend
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
version: v1
template:
metadata:
labels:
app: backend
version: v1
spec:
serviceAccountName: backend
containers:
- image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/envoygateway-echo-basic:v20231214-v1.0.0-140-gf544a46e
imagePullPolicy: IfNotPresent
name: backend
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend-2
---
apiVersion: v1
kind: Service
metadata:
name: backend-2
annotations:
openyurt.io/topologyKeys: openyurt.io/nodepool # 配置節點池拓撲
labels:
app: backend-2
service: backend-2
spec:
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: backend-2
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-2
spec:
replicas: 1
selector:
matchLabels:
app: backend-2
version: v1
template:
metadata:
labels:
app: backend-2
version: v1
spec:
serviceAccountName: backend-2
containers:
- image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/envoygateway-echo-basic:v20231214-v1.0.0-140-gf544a46e
imagePullPolicy: IfNotPresent
name: backend-2
ports:
- containerPort: 3000
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace步驟二:確認GatewayClass
安裝Gateway with Inference Extension組件後會預設建立GatewayClass。執行以下命令確認:
kubectl get gatewayclass預期輸出:
NAME CONTROLLER ACCEPTED AGE
ack-gateway gateway.envoyproxy.io/gatewayclass-controller True 2m31s如果未發現 GatewayClass資源,需手動建立。將下方樣本儲存到gatewayclass.yaml,執行 kubectl apply -f gatewayclass.yaml建立。
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: ack-gateway
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller步驟三:建立自訂EnvoyProxy配置
在ACK Edge叢集中,需要為每個節點池建立自訂 EnvoyProxy 配置,指定資料面 Pod 的調度節點池和服務暴露方式。
將下方樣本中的 NPXXX 替換為實際的節點池ID,然後儲存到gateway-config.yaml,執行 kubectl apply -f gateway-config.yaml。
可在ACK控制台的頁面查看節點池 ID。
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: custom-proxy-config
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
pod:
nodeSelector:
alibabacloud.com/nodepool-id: NPXXX # 替換為實際的節點池 ID
envoyService:
annotations:
openyurt.io/topologyKeys: openyurt.io/nodepool # 佈建服務拓撲
type: NodePort # ACK Edge 使用 NodePort 暴露服務該配置包含三個ACK Edge情境的關鍵設定:
配置項 | 說明 |
| 將 Gateway 資料面 Pod 調度到指定節點池 |
| 佈建服務拓撲,確保流量在節點池內閉環 |
| 使用 NodePort 暴露服務(邊緣情境不使用 LoadBalancer) |
步驟四:建立Gateway資源
將下方樣本儲存到gateway.yaml,執行 kubectl apply -f gateway.yaml。
組件控制面會根據Gateway資源自動建立EnvoyProxy Deployment和NodePort類型的Service,並在節點上指定連接埠開啟監聽。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ack-gateway
spec:
gatewayClassName: ack-gateway
listeners:
- name: http
protocol: HTTP
port: 80
infrastructure:
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: custom-proxy-config # 關聯步驟三建立的自訂配置步驟五:擷取網關地址
網關服務採用NodePort方式暴露,對應的服務地址為節點池內任一節點IP和服務的連接埠。
查詢Service連接埠。
kubectl get service -n kube-system -l gateway.envoyproxy.io/owning-gateway-name=ack-gateway預期輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE envoy-default-ack-gateway-7452df7d NodePort 192.168.86.174 <none> 80:30364/TCP 19m設定網關地址環境變數。將
NODEIP替換為節點池內任一節點的IP地址,NODEPORT替換為上一步查詢到的連接埠號碼。export GATEWAY_HOST=NODEIP:NODEPORT
基於路徑首碼匹配的HTTP路由
以下樣本配置HTTPRoute匹配/get首碼,並進行測實驗證。
建立HTTPRoute資源。將以下YAML內容儲存為httproute.yaml,然後執行
kubectl apply -f httproute.yaml命令。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 matches: - path: type: PathPrefix value: /get測試訪問。
curl -H "Host: www.example.com" http://$GATEWAY_HOST/get預期輸出:
{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": [ "*/*" ], "User-Agent": [ "curl/8.9.1" ], "X-Envoy-External-Address": [ "115.XX.XXX.55" ], "X-Forwarded-For": [ "115.XX.XXX.55" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "953b2f8f-26d3-4ba9-93ba-a482b197b1ff" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
添加請求Header
更新HTTPRoute配置,為路由的請求添加Header。
更新HTTPRoute資源。將以下YAML內容儲存為httproute.yaml,然後執行
kubectl apply -f httproute.yaml命令。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 1 filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: "added-header" value: "foo"測試訪問。
curl -H "Host: www.example.com" http://$GATEWAY_HOST/get預期輸出:由於樣本應用會將請求資訊作為響應返回,因此可以在響應中看到已添加的
added-header,表明操作已成功。{ "path": "/get", "host": "www.example.com", "method": "GET", "proto": "HTTP/1.1", "headers": { "Accept": [ "*/*" ], "Added-Header": [ "foo" ], "User-Agent": [ "curl/8.9.1" ], "X-Envoy-External-Address": [ "115.XX.XXX.55" ], "X-Forwarded-For": [ "115.XX.XXX.55" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "d37f19e5-25c1-45cf-90e5-51453e7ae3ed" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }
按比例分發請求
以下將再次更新HTTPRoute配置,增加backend-2的路由規則,並為backend和backend-2服務配置權重。
Gateway API並不要求所有backendRef的權重之和為100。單個服務比例計算規則為:
更新HTTPRoute資源。將以下YAML內容儲存為httproute.yaml,然後執行
kubectl apply -f httproute.yaml命令。apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: ack-gateway hostnames: - "www.example.com" rules: - matches: - path: type: PathPrefix value: /get backendRefs: - group: "" kind: Service name: backend port: 3000 weight: 8 - group: "" kind: Service name: backend-2 port: 3000 weight: 2測試連續訪問20次,查看兩個服務的比例。
以下命令進行了額外處理,使輸出僅顯示
backend和backend-2。for i in $(seq 1 20); do curl -sS -H "Host: www.example.com" http://$GATEWAY_HOST/get |grep backend; done | \ sed -E 's/".*"(backend(-2)?)-[0-9a-zA-Z]*-.*/\1/'預期輸出: 兩個服務接收到的流量比例大致為80%和20%。
backend-2 backend backend backend backend backend backend backend backend backend backend backend-2 backend-2 backend backend backend-2 backend backend backend backend