使用Gateway with Inference Extension访问服务
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及以上。
准备工作
步骤一:创建测试应用
将下方示例保存到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