Gateway API是Kubernetes官方项目,是下一代Kubernetes路由和负载均衡API,支持通过Gateway API配置流量规则。本文介绍Gateway with Inference Extension支持的一些Gateway API基础能力配置方法。
工作原理
Gateway with Inference Extension组件基于Envoy Gateway项目构建,支持完整的Gateway API基础能力及开源Envoy Gateway扩展资源。
Envoy Gateway架构包括:
控制面:由Envoy Gateway组件构成,主要负责监听集群中的流量规则,动态创建和管理Envoy代理实例,并实时更新其转发规则,但不直接参与业务流量的转发。
数据面:由实际运行的Envoy Proxy实例组成,负责处理和转发业务流量,确保高效和可靠的通信。
适用范围
准备工作
创建测试应用backend和backend-2。将以下YAML内容保存为backend.yaml,然后执行
kubectl apply -f backend.yaml命令。说明应用backend-2只需要将backend的YAML中
backend全部替换为backend-2即可。apiVersion: v1 kind: ServiceAccount metadata: name: backend --- apiVersion: v1 kind: Service metadata: name: backend 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安装Gateway with Inference Extension会默认创建GatewayClass,可参考以下方式进行查看。
kubectl get gatewayclass NAME CONTROLLER ACCEPTED AGE ack-gateway gateway.envoyproxy.io/gatewayclass-controller True 2m31s如未发现GatewayClass资源,需手动创建。
创建Gateway资源。将以下YAML内容保存为gateway.yaml,然后执行
kubectl apply -f gateway.yaml命令。apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: ack-gateway spec: gatewayClassName: ack-gateway listeners: - name: http protocol: HTTP port: 80Gateway with Inference Extension组件控制面会根据当前Gateway资源创建出EnvoyProxy Deployment以及对应的LB类型的Service,并在指定端口开启监听。关于LB实例的计费标准,请参见负载均衡计费说明。
也可自定义EnvoyProxy的Deployment规格以及Service参数,或者开启网关HPA。
获取网关地址。
export GATEWAY_HOST=$(kubectl get gateway/ack-gateway -o jsonpath='{.status.addresses[0].value}')
基于路径前缀匹配的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
处理TLS流量
更新Gateway资源,配置证书并添加TLS监听,以验证对TLS流量处理的支持。
生成证书,并创建Secret。
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization" openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt更新Gateway资源。添加TLS监听,并引用上一步创建的证书。
kubectl patch gateway ack-gateway --type=json --patch ' - op: add path: /spec/listeners/- value: name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - kind: Secret group: "" name: example-cert '查看更改是否生效。
kubectl get gateway/ack-gateway -o yaml | grep spec: -A 20预期输出:
spec: gatewayClassName: ack-gateway listeners: - allowedRoutes: namespaces: from: Same name: http port: 80 protocol: HTTP - allowedRoutes: namespaces: from: Same name: https port: 443 protocol: HTTPS tls: certificateRefs: - group: "" kind: Secret name: example-cert mode: Terminate status:输出结果表明,更改已经生效。
测试访问。
curl -H Host: www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" \ --cacert example.com.crt https://www.example.com/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": [ "https" ], "X-Request-Id": [ "ac539756-3826-474b-be2f-5e57fdd49dac" ] }, "namespace": "default", "ingress": "", "service": "", "pod": "backend-5bff7XXXXX-XXXXX" }