HTTPRoute 没有 Gateway,也能作用于 Service 吗

前提是实现支持 Gateway API 的网格路由能力(GAMMA),不是“集群安装了 HTTPRoute CRD”就自动生效。第 06 篇的五层证据仍适用:提交 HTTPRoute、检查控制器接受与关联状态、查代理当前 route/cluster、观察真实请求经过哪条代理路径、核对库存服务的版本和请求 ID。控制面不处于普通 orders → inventory 请求的转发链上。

生产者和消费者 HTTPRoute 分别附着于 inventory Service,但命名空间决定作用的调用者

与入口流量附着到 Gateway 不同,网格中的 HTTPRoute 通过 parentRefs 指向 Kubernetes Service,例如 inventory 的端口 8080。parentRefs 回答“哪条 Service 流量可受此规则影响”,backendRefs 回答“命中后转发到哪个目标”;前者不是后端 Pod 列表,后者也不表示调用者身份。通过目标应用日志的同一请求 ID 才能核对后端版本,不能只看对象 Accepted=True。

放在哪个命名空间,改变了谁受影响

Gateway API 网格概览将与目标 Service 同命名空间的 Route 称为生产者 Route:它由 Service 提供方定义,对访问该 Service 的客户端生效。位于其他命名空间的 Route 是消费者 Route,只作用于该 Route 所在命名空间的客户端。图中 service-mesh-lab 内的规则拟约束所有对库存服务的调用;mesh-clients 内的规则只针对该命名空间发往库存服务的调用。先确认具体实现支持这两类 Route,别把“跨命名空间能创建 Route”误读成“所有来源都经过它”。

1
2
3
4
orders (service-mesh-lab) ──> inventory Service ──> inventory-v1/v2
orders (mesh-clients) ──> inventory Service ──> inventory-v1/v2
来源作用域 ───────────> Route parentRef 决定附着对象
请求匹配 ─────────────> Route rule/backendRef 决定目标

例如将 header x-canary: yes 的请求路由到 inventory-v2:先确保 v2 Service、端口和后端实例存在,再提交指向 inventory Service 的 Route;同时保留没有该 header 的 v1 基线。同一 Service 同一命名空间内的多条 Route 会依 Route 合并与优先级规则处理,不能假定“后一条 YAML 自动覆盖前一条”。ReferenceGrant 涉及跨命名空间后端引用时还需单独审查;不要把消费方 Route 的跨命名空间 parentRefs 与跨命名空间 backendRefs 混为一谈。

分开运行生产者与消费者规则

本工程固定 Gateway API 1.3.0 CRD 与 Istio 1.27.0 候选实现。sidecar 安装入口已包含 CRD;功能是否被实现接受仍以 Route 状态与数据面请求判断。从 examples/service-mesh/ 执行 SM_CONTEXT=kind-service-mesh-sidecar bash scripts/cluster-case.sh 12,前提是第 06、10 篇的 VirtualService 已清理。

生产者清单在 deploy/kubernetes/inventory-httproute.yaml,Route 位于 service-mesh-lab,与 parent Service 同 namespace;parentRefs 的 group 是空字符串、kind 是 Service、name 是 inventory、port 是 8080。带 x-canary: yes 的请求转给 inventory-v2:8080,其余转给 inventory-v1:8080。脚本采集 status.parents、orders 代理资源、canary/default 响应和 v2 handler ID。

消费者阶段先确认 mesh-clients namespace 不存在,避免覆盖已有工作负载;再使用 mainline/12/consumer.yaml,其中包含带注入标签的 mesh-clients namespace、一个调用者 Deployment、指向跨 namespace inventory 的 HTTPRoute,以及允许该 Route 引用 inventory-v2 后端的 ReferenceGrant。此规则将 mesh-clients 的调用导向 v2;service-mesh-lab 的调用不应仅因这条消费者规则被强制导向 v2。普通 Service 原本就可能选中 v2,因此不能用外部来源偶然一次 v2 响应证明作用域越界。

1
2
3
4
kubectl --context kind-service-mesh-sidecar apply -f mainline/12/consumer.yaml
kubectl --context kind-service-mesh-sidecar -n mesh-clients rollout status deployment/client --timeout=90s
kubectl --context kind-service-mesh-sidecar -n mesh-clients exec deploy/client -c app -- /mesh-demo -role loadgen -frontend-url http://inventory.service-mesh-lab.svc.cluster.local:8080 -requests 20 -request-id sm-12-consumer
kubectl --context kind-service-mesh-sidecar -n mesh-clients get httproute inventory -o yaml

生产者和消费者先分阶段运行。官方网格概览仍将两类规则的相互关系标为持续完善的部分,不应假定“消费者一定覆盖生产者”。跨 namespace parentRefs 的附着语义与 backendRefs 的引用许可也不同,ReferenceGrant 在这里授予的是后端 Service 引用。

负例把消费者 parent 名改成不存在的 missing-inventory,保存带 observedGeneration 的 conditions 和代理路由,再重复请求。不能要求业务必失败:失去 Route 后普通 Service 仍可能可达;要判定的是该 Route 不再按原附着对象生效。恢复重新 apply consumer.yaml,等待状态与 v2 请求同时恢复。结束删除本次清单,保留原 namespace 外其他资源。当前生产者/消费者实际集群验证均 NOT_RUN。

[PATTERN] 角色化配置把服务提供者的默认行为与调用方范围分开;API 对象所在 namespace 是语义的一部分。

原则 检验点
附着与目标分离 parentRefs 与 backendRefs 分别核对
权限最小化 ReferenceGrant 仅允许指定后端名称
失效规则不等于失效服务 错 parent 检查状态,不猜固定 HTTP 码

练习与参考解答

  1. HTTPRoute 状态显示 Accepted=True,但 v2 没有任何请求,能认定负载均衡有错吗?参考解答:不能。先检查来源是否在作用范围、请求 header 是否匹配、backendRefs 服务/端口与 endpoints 是否有效,再看代理当前路由和同一请求 ID 的库存日志。Accepted 不能证明请求实际经过该规则。
  2. 保留规则内容不变,把生产者 Route 移到 mesh-clients 命名空间;哪些请求应重新核验?参考解答:此时它是消费者 Route,重点对比该来源和其他来源(如 service-mesh-lab)访问同一 Service 的结果;如仍有生产者 Route,应检查两者优先级与合并行为。控制器对这一组合是否支持要看选定版本,不可先填预期状态码。

官方参考与系列导航

系列导航:00 无网格基线 → 11 连接与负载均衡 → 12 Gateway API 网格路由(本文)→ 13 超时预算。