Gateway API是Kubernetes社区推出的下一代服务网络模型API,云原生API网关(APIG)支持Kubernetes Gateway API标准,您可以通过声明式的Gateway和HTTPRoute资源来配置网关路由,将集群内的服务暴露给外部用户访问。
背景信息
Gateway API是Kubernetes社区推出的下一代服务网络模型API,旨在提供更加具有表达力、可扩展性和面向角色的路由与负载均衡接口。相较于传统的Ingress API,Gateway API提供了更清晰的资源模型分层(GatewayClass、Gateway、HTTPRoute等),支持更丰富的流量管理能力。
云原生API网关(APIG)支持Kubernetes Gateway API标准,您可以通过声明式的Gateway和HTTPRoute资源来配置网关路由,将集群内的服务暴露给外部用户访问。
前提条件
已创建云原生API网关实例,且引擎版本在2.1.16及以上。如果低于该版本,请先升级网关实例。
已有Kubernetes集群(ACK集群),版本在1.24及以上,且已安装Gateway API CRD。当前网关兼容的最高版本为v1.3.0,建议安装v1.3.0版本。如果使用的是阿里云ACK,建议直接通过组件管理安装Gateway API CRD。
配置Gateway API监听
开启Gateway API监听
登录云原生API网关控制台,单击目标网关实例,进入API页面,单击创建API。
在HTTP API下方,单击导入Gateway API。
在创建面板中,填写API名称和描述,选择ACK来源集群。在自定义配置区域,根据需要配置监听的命名空间和GatewayClass,默认监听集群中所有命名空间的Gateway API资源。配置完成后,单击确定。
单击进入新创建的API。如果ACK集群中已存在Gateway API资源且在配置的监听范围内,路由列表中将展示对应的路由条目,表示Gateway API监听已生效。
出于对开源Higress的兼容性考虑,云原生API网关默认监听GatewayClass为higress的资源,不受上述过滤配置的影响。
修改Gateway API监听
登录云原生API网关控制台,单击目标网关实例,进入API页面,单击需要修改的Gateway API类型的API。
在右上角单击编辑,根据需要调整监听的GatewayClass和命名空间,单击确认后配置生效。如果对应配置项留空,则表示监听全部。
实操示例
在满足上述前提条件并完成Gateway API监听配置后,您可以参考以下示例,通过创建Gateway API资源实现服务的路由转发。
部署示例应用
创建
httpbin.yaml文件,内容如下:apiVersion: apps/v1 kind: Deployment metadata: name: httpbin namespace: default spec: replicas: 1 selector: matchLabels: app: httpbin template: metadata: labels: app: httpbin version: v1 spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/mse-ingress/go-httpbin args: - "--port=8080" - "--version=v1" imagePullPolicy: Always name: httpbin ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: httpbin namespace: default spec: type: ClusterIP ports: - port: 80 targetPort: 8080 protocol: TCP selector: app: httpbin部署应用:
kubectl apply -f httpbin.yaml确认应用运行状态:
kubectl get pods -l app=httpbin预期输出:
NAME READY STATUS RESTARTS AGE httpbin-5d4f8b6c7f-xxxxx 1/1 Running 0 30s
部署Gateway和路由
开启监听后,云原生API网关会默认创建一个名为higress的GatewayClass。您也可以根据需要自行创建GatewayClass资源。
(可选)如需自定义GatewayClass,创建
gatewayclass.yaml文件:apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: apig # 可按需修改为自定义名称 spec: controllerName: higress.io/gateway-controllerkubectl apply -f gatewayclass.yaml创建
gateway.yaml文件,内容如下:apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: apig-gateway namespace: default spec: gatewayClassName: apig listeners: - name: http protocol: HTTP port: 80 hostname: "*.example.com" allowedRoutes: namespaces: from: Same --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin-route namespace: default spec: parentRefs: - name: apig-gateway hostnames: - "demo.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - kind: Service name: httpbin port: 80部署Gateway和路由规则:
kubectl apply -f gateway.yaml确认Gateway创建状态。等待约2分钟,执行以下命令:
kubectl get gateway apig-gateway预期输出:
NAME CLASS ADDRESS PROGRAMMED AGE apig-gateway apig nlb-xxxx True 2mPROGRAMMED状态为True表示Gateway已就绪。确认路由已被正确监听:登录云原生API网关控制台,进入目标网关实例,单击API,找到Gateway API类型的API,点击进入后查看路由列表。如果列表中包含在容器侧创建的Gateway API路由,说明路由已被正确监听。
测试应用访问
获取网关接入点:登录云原生API网关控制台,进入目标网关实例,单击概览 > 基本信息,获取网关接入点地址。
访问应用(将
<网关接入点>替换为上一步获取的地址):curl -H "Host: demo.example.com" http://<网关接入点>/version预期输出:
version: v1 hostname: httpbin-5d4f8b6c7f-xxxxx
场景演示
以下示例参考自Gateway API官方文档,更丰富的实践场景请参考Gateway API官方用户指南。
场景一:使用filter修改请求头
通过HTTPRoute中的filter能力,可以在请求或响应阶段进行额外处理。以下演示如何使用filter为发送到后端的请求添加自定义请求头。
创建
httproute-filter.yaml文件:apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-filter spec: parentRefs: - name: apig-gateway hostnames: - "filter.example.com" rules: - matches: - path: type: PathPrefix value: / filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: my-header value: foo backendRefs: - kind: Service name: httpbin port: 80该配置将创建一个名为
demo-filter的HTTPRoute资源。部署后,访问域名filter.example.com的请求将自动添加请求头my-header: foo。部署路由规则:
kubectl apply -f httproute-filter.yaml访问应用:
curl -H "Host: filter.example.com" http://<网关接入点>/header预期输出中包含自动添加的请求头:
headers: { ... "My-Header": [ "foo" ], ... }
场景二:按照权重对流量进行切分
通过设置后端多个服务的权重,可以将请求按比例分发到不同的服务,常用于灰度发布场景。
创建
nginx.yaml文件,部署两个nginx应用。其中old-nginx服务返回字符串old,new-nginx服务返回字符串new:apiVersion: apps/v1 kind: Deployment metadata: name: old-nginx spec: replicas: 1 selector: matchLabels: run: old-nginx template: metadata: labels: run: old-nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx imagePullPolicy: Always name: old-nginx ports: - containerPort: 80 protocol: TCP restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: old-nginx spec: type: ClusterIP ports: - port: 80 protocol: TCP targetPort: 80 selector: run: old-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: new-nginx spec: replicas: 1 selector: matchLabels: run: new-nginx template: metadata: labels: run: new-nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx imagePullPolicy: Always name: new-nginx ports: - containerPort: 80 protocol: TCP restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: new-nginx spec: type: ClusterIP ports: - port: 80 protocol: TCP targetPort: 80 selector: run: new-nginx创建
httproute-weight.yaml文件:apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-weight spec: parentRefs: - name: apig-gateway hostnames: - "weight.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - kind: Service name: old-nginx port: 80 weight: 90 - kind: Service name: new-nginx port: 80 weight: 10说明weight字段为相对权重值,无需等于100。上述配置中90:10表示约90%的流量路由到old-nginx,约10%的流量路由到new-nginx。部署应用和路由规则:
kubectl apply -f nginx.yaml kubectl apply -f httproute-weight.yaml多次访问应用验证流量分配:
for i in {1..10}; do curl -s -H "Host: weight.example.com" http://<网关接入点>/; echo; done预期输出中,大部分返回
old,少量返回new,比例接近9:1。
场景三:基于Header的灰度路由
通过Header匹配规则,可以将携带特定请求头的流量路由到灰度服务,未携带则路由到稳定版本。该方式常用于在不影响线上用户的前提下,对灰度版本进行验证。
在上述实操示例的基础上,为httpbin部署灰度版本服务。创建
httpbin-canary.yaml文件:apiVersion: apps/v1 kind: Deployment metadata: name: httpbin-canary namespace: default spec: replicas: 1 selector: matchLabels: app: httpbin-canary template: metadata: labels: app: httpbin-canary version: v2 spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/mse-ingress/go-httpbin args: - "--port=8080" - "--version=v2" imagePullPolicy: Always name: httpbin ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: httpbin-canary namespace: default spec: type: ClusterIP ports: - port: 80 targetPort: 8080 protocol: TCP selector: app: httpbin-canarykubectl apply -f httpbin-canary.yaml创建
httproute-canary.yaml文件,配置基于Header的灰度路由规则:apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: demo-canary spec: parentRefs: - name: apig-gateway hostnames: - "canary.example.com" rules: - matches: - headers: - type: Exact name: env value: canary backendRefs: - kind: Service name: httpbin-canary port: 80 - backendRefs: - kind: Service name: httpbin port: 80该配置定义了两条路由规则:携带请求头
env: canary的流量路由到灰度服务httpbin-canary,其余流量路由到稳定版本httpbin。部署路由规则:
kubectl apply -f httproute-canary.yaml验证灰度路由。不携带Header时访问稳定版本:
curl -H "Host: canary.example.com" http://<网关接入点>/version预期输出:
version: v1 hostname: httpbin-f4c58d59c-xxxxx携带
env: canary请求头时访问灰度版本:curl -H "Host: canary.example.com" -H "env: canary" http://<网关接入点>/version预期输出:
version: v2 hostname: httpbin-canary-585859f9b6-xxxxx