土法炼钢 · 系统与基础设施

【Envoy Gateway】HTTPRoute / GRPCRoute:匹配进入 RDS,阴影要靠 RouteRulesOverlap

文章导航

分类入口
kubernetesnetwork
标签入口
#envoy-gateway#httproute#grpcroute#rds#route-rules-overlap#gateway-api#v1.9.0

目录

HTTPRoute YAML 能 apply、Accepted=True,不等于这条规则在吃流量。Gateway API 允许同一 listener 上挂多条 Route;规范保证每个请求只命中一条规则。更具体的规则赢,并列时更老的 Route 赢。输家可以仍然是 Accepted——直到 Envoy Gateway v1.9.0RouteRulesOverlap 把「匹配条件完全相同」标成警告。

本文只钉附着与 hostname、matches/filters/backendRefs 如何进入 RDS、GRPCRoute 的差异,以及 v1.9 这条警告的边界。角色模型与金丝雀菜谱见 k8s-network/18(该文钉 Gateway API v1.2 / EG v1.2,字段全集不得搬来当 v1.9)。权重如何变成 Envoy weighted cluster 的 Filter 细节外链 envoy/06,本篇不重写 HCM。

本文是「Envoy Gateway / Gateway API」系列第 6 篇(共 16 篇)。→ 系列目录

篇目 核心内容
第 5 篇 · xDS Translator 与 Infra IR → xDS;推送 ≠ 在服务
第 6 篇 · HTTPRoute / GRPCRoute 匹配与权重 → RDS;阴影与 RouteRulesOverlap
第 7 篇 · TLS / BackendTLSPolicy / SDS 监听器证书与后端 TLS

上一篇xDS Translator 与 Infra · 下一篇TLS / SDS

版本锚定:Envoy Gateway v1.9.0;Gateway API v1.6.1 HTTPRoute/GRPCRoute 规范;EG v1.9 路由文档钉 gateway.envoyproxy.io/v1.9/。无伪造 Route status 输出。


一、附着与 hostname

HTTPRoute / GRPCRoute 要进某条 Gateway listener,必须同时满足:parentRefs 指向该 Gateway(可选 sectionNameport)、listener 的 allowedRoutes 允许该 kind 与 namespace、hostname 与 listener hostname 有交集。

EG v1.9 HTTPRoute 页与 Gateway API v1.6.1 一致:

v1.9 HTTP routing 任务把不同主机拆成不同 HTTPRoute:example.comfoo.example.combar.example.com 各一份。文档写明:hostname 未出现在任何 HTTPRoute 上时,请求不应被路由,客户端看到 404。这是匹配失败,不是 5xx,也不是「控制器没 Accepted」。

v1.9.0 有一条与附着相关的修复,避免把 listener 证书问题误判成 Route 拒绝:HTTPRoute、GRPCRoute、TLSRoute、TCPRoute、UDPRoute 的 Accepted 不再因为「所附着 listener 因缺少 TLS certificate ref 而未 Programmed」被设为 False。listener 是否 Programmed 与 Route 是否 Accepted 分开计算。排障时不要用「Route 未 Accepted」去解释「HTTPS listener 没证」。

hostname 与 listener 的交集,规范给了可核对例子:listener test.example.com 只与写了该名或匹配通配的 Route 相交;*.example.com 匹配 test.example.comfoo.test.example.com匹配 example.com。Route 上多写的、与 listener 不相交的 hostname 必须忽略;一个都交不上则不得 Accepted。这是附着失败,不是 RDS 阴影。

跨 namespace 的 parentRefs / backendRefs 仍受 ReferenceGrant 约束,机制在第 2 篇。本篇只强调:未 grant 时失败落在 ResolvedRefs,不是 RDS 里多了一条阴影规则。

EG v1.9 HTTP routing 任务还写:hostname 未出现在任何 HTTPRoute 时返回 404。这与「规则默认 / 匹配全部 HTTP」不矛盾——后者只在 hostname 已经选中该 Route(或 Route 未限制 hostname)之后生效。先问 Host,再问 path。

v1.9 另修:ExternalName Service 不得作为 route backend——会生成空地址 cluster,IR 校验失败并卡住整份 snapshot。现在显式 ResolvedRefs: False;集群外 FQDN 应改用 EG Backend。这是整棵 xDS 树的正确性门闩,不是单条 404。


二、matches / filters / backendRefs

规则内部三件套对应 IR 再对应 RDS 里的一条(或一组)route。EG v1.9 HTTPRoute 文档对 matches 的例子与规范相同:一条 rule 里两个 match 是「/foo 前缀且 header version=2」/v2/foo 前缀」——满足任一即可。不要把「同一 rule 多个 match」理解成必须同时成立。

字段 规范要点(Gateway API v1.6.1) 落到数据面时
matches 同一 rule 下多个 match 是 ;一个 match 内 path/header/query/method 是 。未写 matches 时 HTTPRoute 默认为 / 的 PathPrefix,匹配全部 HTTP。Path 类型包括 Exact / PathPrefix / RegularExpression(以后两者是否 Core 以实现与 channel 为准,不在此把未核字段写成 v1.9 全集) 进入 RDS 的 match 树;Envoy 按顺序取第一条命中
filters Core 必须实现(HTTPRouteRule 上 RequestHeaderModifier、RequestRedirect 为 Core)。URLRewrite 与 RequestRedirect 不得组合。不兼容时 Accepted=False,reason 可用 IncompatibleFilters。多次指定同一 core filter 的语义在规范里是 unspecified / implementation-specific 多数变成 HCM per-route 或 filter 配置;EG 扩展走 extensionRef
backendRefs 未指定且没有会直接响应的 filter 时,HTTPRoute 规范要求返回 500 每个 backendRef 对应 Envoy cluster(或 v1.9 experimental mergeBackends 下的共享 cluster,第 10 篇)
weight 同 rule 多 backend 按权重分流 RDS weighted clusters,不是第二条 HTTPRoute

v1.9 HTTP routing 任务用 header env: canary 做更具体匹配:有 header 走 canary Service,否则走稳定 Service。这是同一 HTTPRoute 内的规则优先级(更具体者优先),不是两条 Route 抢 listener。站内 18 的金丝雀实验基于 EG v1.2,不得把那次命令输出写成 v1.9 事实。

Gateway API 对跨 Route 的优先级写在 HTTPRouteRule / Listener allowedRoutes 叙述里,并列时继续比:

  1. 该 Route 类型定义的最具体匹配(HTTP:非通配 hostname 字符数、hostname、path、header 等,以 v1.6.1 spec 原文为准)。
  2. 更老的 Route(creationTimestamp)。
  3. {namespace}/{name} 字典序更前。
  4. 仍并列则该 Route 内部第一条满足条件的 rule。

Envoy 侧是「RDS 列表从上到下,第一条匹配获胜」。EG 翻译必须把上述优先级变成这个列表顺序。社区 issue #9135 上维护者说明:两条合法 HTTPRoute 可以都是 Accepted=True / ResolvedRefs=True,较老且匹配相同的那条吃流量,较新的被 Envoy 顺序阴影。这是规范行为,不是控制器「没挂上」。

v1.9 任务还展示两类 EG 扩展,不要当成 Gateway API core:

超时:timeouts.request / backendRequest 自 Gateway API v1.2 起在 Standard channel。backendRequest 不得大于 request。v1.9.0 修过:由 backendRequest 推导的 per-retry timeout 在未配 retry backoff 时也会被应用。

flowchart TD
  req["Request Host and path"] --> host{"Hostname match"}
  host -->|"no HTTPRoute hostname"| miss["404"]
  host -->|"match route A and B"| spec{"Gateway API specificity"}
  spec -->|"A more specific"| a["RDS first: route A"]
  spec -->|"tie"| ts{"Older creationTimestamp"}
  ts --> a
  ts -->|"same timestamp"| name{"namespace/name lexical"}
  name --> a
  a --> envoy["Envoy first-match wins"]
  shadow["Route B Accepted still True"] -.-> envoy

图:同 listener 上多条 HTTPRoute 的匹配顺序。阴影 Route 可以保持 Accepted;v1.9 对完全相同的 match 另打 RouteRulesOverlap(第四节)。


三、GRPCRoute 差异

GRPCRoute 自 Gateway API v1.1.0 起在 Standard channel,apiVersion 为 gateway.networking.k8s.io/v1。EG v1.9 GRPC routing 任务用 grpcurlyages.Echo/Ping,并说明支持 gRPC-Web。

与 HTTPRoute 的机制差,而不是口味差:

维度 HTTPRoute GRPCRoute
默认匹配 未写 matches → PathPrefix / 未写 matches → 匹配全部 gRPC 请求
方法匹配 URI path,例如 /package.Service/Method service + method 字段;EG 文档支持 Exact(默认)与 RegularExpression
无 backend 且无直接响应 filter HTTP 500 gRPC UNIMPLEMENTED
过滤器 HTTPRoute filters 功能相同的头修改等复用 HTTPRoute filter 形状;v1.9 允许 GRPCRoute rule 经 extensionRef 引用 EG HTTPRouteFilter(rewrite、direct response、credential、cookie match)
超时 HTTPRoute timeouts 长流常用 BackendTrafficPolicy 把 HTTP request timeout 设为 0s(v1.9 任务页)

何时必须 HTTPRoute:要在同一 hostname 上用 URI 区分普通 HTTP 与 gRPC。规范建议分主机;若实现强制两类 Route 的 hostname 唯一,混服只能两边都用 HTTPRoute。

EG v1.9 允许 GRPCRoute 经 extensionRef 引用 HTTPRouteFilter,从而在 gRPC 规则上做 URL rewrite(authority/host 与 regex :path)、direct response、credential injection 与 cookie 匹配。这是 v1.9 New features,不是 Gateway API core。不要把这些能力写成「GRPCRoute spec 自带」。

跨 Route 合并:GRPCRoute spec 写明 不得与 HTTPRoute 做 merging;优先级在 GRPC 自己的 hostname / service / method / header 尺度上计算,并列时同样是时间戳再名字。

Gateway API v1.6.0 发行说明改过语气:以前规范要求实现拒绝同一 hostname 上的 HTTPRoute 与 GRPCRoute(不少实现并未做到);现在 可以拒绝,也 可以让二者并存(#4598)。EG v1.9 GRPCRoute 页仍写「实现可以强制唯一」。本文不把「EG 一定拒绝」写成 v1.9 保证——以集群里实际 Accepted 条件为准,本篇未跑。


四、v1.9 RouteRulesOverlap

v1.9.0 Release Notes 原文:新增 RouteRulesOverlap warning status condition,用于「某条 route 的 match 条件与同一 listener 上另一条 route 完全相同」,以便发现被静默阴影的规则。

边界必须写死:

发现 Overlap 之后的处理是改匹配(hostname / path / header / method / query)或删掉被阴影的那条,而不是重装控制器。金丝雀应落在同一 rule 的 weighted backendRefs更具体的 header match,不要复制整份 HTTPRoute 抢同一组 match。

排障时把「没流量」拆开:hostname 未命中是 404;backend 未指定且无直接响应 filter 是 500;ExternalName 是 ResolvedRefs False 且可能卡住整份 snapshot;完全相同 match 才是 Overlap 警告。四者都可能伴随 Accepted=True 的某一条 Route,不能用单一绿灯否定其它失败。

v1.9 没有把这条条件承诺为「所有部分重叠都会报警」。部分重叠、跨 GRPC/HTTP 的 hostname 策略、以及实验性 rule name 字段,都不在本篇展开。


五、谱系、争论与开放问题

谱系

Ingress:host + path + 不可移植 annotation
  → Gateway API HTTPRoute(角色分离、可移植 core、显式优先级)
  → GRPCRoute(封装协议单独成资源,避免生态分裂)
  → 实现把优先级编译成 Envoy RDS 有序列表
  → EG v1.9:用 RouteRulesOverlap 补「Accepted 仍被阴影」的可观测缺口

HTTP 反向代理「第一条匹配获胜」是数据面常识;Gateway API 要在多租户、多对象上给出可移植的排序键(具体度、时间戳、名字),否则换实现金丝雀会翻面。EG 的工作是遵守这组键,并在完全重复时发出警告。

争论:重叠算错误还是警告

A 侧(早期 issue #8101 的诉求):相同 exact path 两条 Route 都 Accepted,结果不确定,status 应标冲突。

B 侧(规范 + v1.9 实现):重叠常是故意的 fallback;拒绝会误伤。最终选择是 warning + 保持 Accepted,只覆盖 identical match。

这是「status 能否当生效 SLO」的一个实例:警告存在,流量仍可能全在另一条规则上。

开放问题

  1. Overlap 是否应覆盖「语义覆盖」而不只是字段全等(例如 / prefix 阴影 /api)?覆盖会带来大量故意 fallback 的噪音。
  2. HTTPRoute 与 GRPCRoute 同 hostname 的可选拒绝,在 EG 的实际默认是什么?v1.6 规范已放松;需要实现级测试,本文不测不写。
  3. 多 Route 权重金丝雀与单 Route weighted backends 在排障上的成本差:前者制造阴影,后者把分流留在一条 RDS 规则内。

六、小结

  1. Hostname 先于规则;未匹配主机在 EG 任务文档里是 404,不是 500。
  2. matches 的或/与、filters 兼容性、backendRefs 与 weight 决定 RDS 条目;跨 Route 优先级由 Gateway API 规定,Envoy 用有序列表执行。
  3. GRPCRoute 用 service/method 匹配;无后端时是 UNIMPLEMENTED;与 HTTPRoute 不得按规范合并。
  4. v1.9 RouteRulesOverlap 只警告同 listener 上 完全相同 的 match;Accepted 绿仍可能被更老或更具体的规则阴影。

下一篇把「谁在终止 TLS」从路由里拆出来:监听器证书、BackendTLSPolicy、以及 v1.9 SDS 的 unix:// 与共享 system_ca_certificates


七、参考资料

规范 / 官方文档(A)

源码 / 追踪(A/B)

核心论文 / GEP

实验 / 工具

站内对照


上一篇:xDS Translator 与 Infra · 系列目录 · 下一篇:TLS / BackendTLSPolicy / SDS

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-08-19 · kubernetes / network

Envoy Gateway / Gateway API:从 CR 附着到 xDS

补齐站内 Gateway API 产品教程与 Envoy 数据面消费侧之上的南北向控制面内核:附着与 status、Provider watch、IR 翻译、xDS 与 Infra、路由/TLS/L4/Policy 边界,并以排障与相对 Cilium Gateway / Istio / Ingress 的选型收束。


By .