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

【Envoy Gateway】排障坐标系:未 Accepted、空 IR、xDS NACK 与旧快照

文章导航

分类入口
kubernetesnetwork
标签入口
#envoy-gateway#troubleshooting#gateway-api#xds#ir#httproute#v1.9.0

目录

「HTTPRoute 已经 apply,为什么还是 404?」与「status 看起来绿,为什么 Envoy 仍走旧路由?」很少落在同一层。前者可能是 parentRefs 未附着、ResolvedRefs 为假、或同 listener 上另一条规则把匹配阴影掉;后者可能是 xDS NACK 后代理停在上一份 known-good,或 Worker 还没 warming 完。若一上来改 HTTPRoute YAML 或重装控制器,因果链会被冲掉,还可能把可恢复的 status 写成「网关坏了」。

本文是系列第 13 篇:按五轴映射症状。口诀与第 01 篇相同:先点名轴,再下钻模块。status 语义见第 02 篇;IR 见第 04 篇;xDS 与舰队见第 05 篇。无真实 Envoy Gateway 集群则不粘贴伪造 egctl、Route status 或 config_dump

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

篇目 核心内容
第 12 篇 · 运维与升级 Helm/CRD 分装、VAP、存储版本
第 13 篇 · 排障坐标系 五轴归因
第 14 篇 · 对照替代路径 Cilium Gateway / Istio / Ingress

版本锚定:Envoy Gateway v1.9.0(源码 tag v1.9.0,2026-08-14)。文档钉 gateway.envoyproxy.io/v1.9/。Gateway API v1.6.1;数据面 Envoy v1.39.0。官方 Configuration IssuesGateway Exported Metrics、v1.9.0 Release Notes(xdsNACKTotal / RouteRulesOverlap)为 A 级入口。清单是工程方法,不是一次已跑通的排障故事。


一、口诀:先点名轴,再动 YAML

轴一:附着 / status     — Accepted / Programmed / ResolvedRefs / RouteRulesOverlap
轴二:IR                 — Gateway API Translator 产出的 XdsIR / InfraIR
轴三:xDS                — xDS Translator、go-control-plane、NACK、快照未送达
轴四:Envoy 数据面       — Filter / cluster / warming(外链 envoy/15)
轴五:入口之后东西向     — 出 Envoy 之后的 CNI;指针到第 15 篇

每轴固定三列:症状 → 先查什么 → 不要先做什么。与 Cilium 排障Tetragon 排障 同一纪律:一次否证一轴

flowchart TD
  symptom["Symptom: 404 / 500 / no listener"]
  symptom --> axis["Name the axis first"]
  axis --> a1["status conditions"]
  axis --> a2["empty or wrong XdsIR"]
  axis --> a3["xDS NACK stale snapshot"]
  axis --> a4["Envoy dataplane"]
  axis --> a5["east-west after hop"]
触发选轴的症状 先查 不要先做
YAML 已 apply,条件未绿;跨 ns 引用被拒;同 listener 阴影 status.conditions / status.parents,核对 observedGeneration 先改 path 碰运气;先重装控制器
status 看似可接受,IR 无对应 Listener/Route Translator 是否吃进该对象;egctl x translate --to ir 的语义(不伪造输出) 把「Accepted=True」写成「数据面已有这条路由」
NACK、大集群重连后停在旧配置、xds_nack_total 上升 xDS 流、消息上限、上一份 known-good 先改业务重试;先扩 Envoy 副本「冲掉」
监听器在、上游耗尽、证书/协议错、503 与 warming envoy/15 五轴 在控制面 YAML 上循环,不看 Worker 快照
Gateway 已 200,后端互调失败或跨节点黑洞 交回 Cilium 五轴与四元组;见第 15 篇 用南北向 status 解释 Hubble deny

默认入口顺序(可裁剪):GatewayClass / Gateway / Route 的 status →(条件绿仍无流量)问 IR 是否为空 →(IR 有对象)问 xDS 是否 ACK →(ACK 了)问 Envoy 数据面 →(已出网关)问东西向。官方 Troubleshooting and Status 的第一句纪律是:排障 Gateway API 对象时,先看 status.conditions

图「症状如何落到五条轴」对应上表:选轴是分诊,不是结论。轴一未否证之前,不要把工单写成轴四。


二、轴一:附着与 status

症状

规范钉(不是实现口号)

Gateway API 把状态写成正极性 Conditions(GEP-1364;概念页 Troubleshooting and Status):

条件 规范含义 排障含义
Accepted 语义/句法可接受,会产生某些数据面配置,且被控制器接受 不等于整份 YAML 都合法,也不等于已推到 Envoy
Programmed 已解析并已送给数据面,「很快」就绪;「很快」由实现定义 不等于 Envoy Worker 已在服务新快照
ResolvedRefs 对象内引用都存在且合法 为假时仍可能 Accepted=True——部分配置已生效
RouteRulesOverlap v1.9.0 新增的警告:同 listener 上匹配条件完全相同 阴影路由;404/打到另一条后端时先看它

GEP-1364 把 Programmed 从旧的 Ready 里拆出来,明确写了:该条件声明数据面此刻已就绪,只声明配置已送出。把 Programmed=True 当 SLO「流量已按新规则走」,是把规范里的「soon」读成了秒表。

另一条规范陷阱:scope。实现只能给「能从自己拥有的 GatewayClass 串起所有权链」的对象写 status。parentRef 指到一个它不负责的 Gateway 时,不会出现一条「你指错了」的条件——对象可能干脆没有 parents status。排障时「没有 status」与「Accepted=False」不是同一格。

核对路径

条件是否过期observedGeneration 必须等于 metadata.generation。对不上,status 是旧世代;原因可能是控制器没追上,或对象已离开该实现的 scope。

GatewayAccepted 问的是 GatewayClass / listener 是否被本控制器认领;Programmed 在 Envoy Gateway 里还叠了 Infra Manager 拉起的 Deployment/Service。v1.9.0 Release Notes 修过一类误报:无云 LB 的裸金属上 LoadBalancer Service 没有 ingress,却有 spec.externalIPs 时,曾报 Programmed: False / AddressNotAssigned。排障时要读 reason,不要只看 type。

Route:看 status.parents[],不是只看资源级摘要。官方 v1.9 Configuration Issues 给出的对照示例是:HTTPRoute Accepted=TrueResolvedRefs=FalseBackendNotFound——后端 Service 不存在。该文档同时写明:配置未被接受时,Envoy Gateway 会给受影响路由赋 direct_response,客户端拿到 HTTP 500,access log 里 response_code_detailsdirect_response。这是轴一的典型出口,不是轴四「上游 503」。

跨 namespace:没有 ReferenceGrant 时,跨 ns 的 backendRefs / Secret 会在 ResolvedRefs 上失败。不要先怀疑 IR。

阴影:v1.9.0 为「同 listener 上匹配条件完全相同」的路由加 RouteRulesOverlap 警告。匹配更宽的规则把更具体的规则盖住,表象常是 404 或打到错误后端;先读警告条件,再谈「Envoy 路由表坏了」。机制见第 06 篇

L4 静默消失:v1.9.0 只 reconcile gateway.networking.k8s.io/v1 的 TCPRoute/UDPRoute。未装 Gateway API v1.6 CRDs 时,官方破坏性变更写的是静默跳过,不是 500。对象可能还在 etcd 里,但不进翻译输入集——看起来像「没 status / 没流量」,根因在第 08 篇第 12 篇 的 CRD 所有权,仍属轴一的「对象未进入本控制器 scope」。

Policy 未生效:v1.9.0 起 SecurityPolicy / BackendTrafficPolicymergeType 只能挂 xRoute;挂 Gateway / ListenerSet 父资源会被 admission 拒绝。Lua EnvoyExtensionPolicy 默认关闭,需 enableLua。策略 YAML 还在,并不等于进了 IR。见第 09 篇

不要先做:删掉所有 HTTPRoute「验证网络」;把 500 direct_response 写成「后端挂了」;把无 status 的 Route 当成控制器 bug,而不核 parentRef 是否 in-scope。

官方 CLI 入口是 egctl x status all -AUse egctl / Configuration Issues)。本文不粘贴未在本环境执行的表格。kube-state-metrics 可把同类条件变成大规模扫描,口径见第 11 篇


三、轴二:IR

症状

机制回顾

官方 System Design 把动态配置收成两份中间表示:Translator(internal/gatewayapiTranslator)输出 XdsIR(给 xDS Translator)和 InfraIR(给 Infra Manager)。Gateway API Translator Design 写明:每一步既可能写 IR,也可能写 status。IR 存在的理由是把 Gateway API 与 Envoy 资源树解耦——排障多一跳,是设计税,不是事故。

轴二要否证的问题只有一句:这份 Gateway API 对象有没有变成 Translator 认为应该下发的那棵 IR? status 绿只证明 Translator 计算过条件;IR 空证明「计算的结果是不生成对应 Listener/Route」。两件事可以同时发生,例如:listener 因证书引用失败而未编程,v1.9.0 已把「listener 未 Programmed」与「Route Accepted」拆开——Route 仍可 Accepted,IR 里却没有那条 HTTPS 链。

核对路径

输入集:对象是否在 Kubernetes Provider 的 watch 里?漏装 CRD、namespace-scoped watch 未包含控制器自己的命名空间、条件 watch 因集群 CRD 子集而跳过(v1.9.0 为 GKE/OpenShift 一类「缺 ListenerSet / BackendTLSPolicy」的包做了条件 watch)——对象不会进 Translator。这与轴一的 scope 相邻,但根因是 Provider,不是 Route YAML。见第 03 篇

翻译命令语义:官方 egctl x translate 可以把 Gateway API 译成 --to ir--to xdsUse egctl)。这是轴二与轴三的分界工具:IR 空而 xDS 也空,停在轴二;IR 有对象而 Envoy 无对应资源,进入轴三。本文不伪造任何 translate 输出。

Policy / Patch 匹配旧名:v1.9.0 多处破坏面是「xDS 资源改名,EnvoyPatchPolicy 仍匹配旧键」——JWT provider 名、DNS cluster typed config、Lua filter 名、system_ca_certificates 共享 SDS secret、共享限流从 route.rateLimits 挪到 typedPerFilterConfig。Patch 还在,IR/xDS 里的目标已经改名,表象是「策略写了不生效」。这是轴二/三交界,先核 Release Notes 的字段搬家,再谈 Filter 链。

不要先做:把 DeepWiki 或 /latest/ 文档里的 IR 字段当成 v1.9.0;在无 dump 时用想象中的 Listener 名写结论。

轴二出口:IR 里明确没有该 Listener/Route,就不要进轴四改 Envoy 日志级别。


四、轴三:xDS

症状

机制钉

xDS Translator 把 XdsIR 编成 LDS/RDS/CDS/EDS/SDS,经 go-control-plane 的 Delta xDS 送给 Envoy。v1.9.0 新增 xdsNACKTotal:NACK 是带 ErrorDetailDiscoveryRequest,表示 Envoy 拒绝了上一份更新;指标按 node ID 与 resource type URL 打标。Prometheus 导出名为 xds_nack_totalGateway Exported Metrics)。

NACK 之后的数据面语义,站内 envoy/09–11 已经写过:ACK 表示「这份资源孤立看来合法、意图应用」,不等于依赖树 warming 完、流量已切。Envoy 在拒绝后常停在上一份 known-good。控制面「已推送」与「正在服务」在这一轴上再次分裂。

v1.9.0 把 xDS gRPC 默认接收上限从 4MiB 提到 32MiBxdsServer.maxReceiveMessageSize)。官方原因:大规模下 Envoy 重连时的 delta 请求可能超过 4MiB,流以 “received message larger than max” 断开,代理留在最后一份 known-good。这是轴三的容量故障,不是 Route 写错。

同轴还要看:快照是否创建/更新(xds_snapshot_create_total / xds_snapshot_update_total)、流是否还在(xds_stream_duration_seconds)。有 snapshot 更新而无 ACK,优先查 NACK 而不是再 apply 一次 YAML。

核对路径

先读 type URL:NACK 打在 Listener 还是 Cluster/Secret,决定回到第 07 篇(SDS unix://、证书链)还是第 05 篇 的资源树。

GatewayNamespaceMode:v1.9.0 修过该模式下 xDS 认证绕过,并给 SotW 请求做校验。认证失败的表象是「推不动」,容易被写成轴二。安全更新见第 10 篇 与第 12 篇。

不要先做:把 NACK 当成「改副本数就能好」;把 4MiB 时代的 runbook 原样用在 v1.9.0 默认 32MiB 上却不核实际设置。

轴三出口:拿到 type URL 与 NACK/上限证据后,若资源已 ACK 仍行为不对,才进轴四。


五、轴四:Envoy 数据面

本轴不在本系列展开。监听器已在、cluster 空、SDS 未 warming、Hot restart drain、连接池溢出、RESPONSE_FLAGS,全部使用 Envoy 数据面第 15 篇 的五条坐标:请求路径、线程快照、匹配改写、xDS 一致性、上游资源。版本钉 Envoy v1.39.0

Envoy Gateway 只提供进入该方言的入口:

不要先做:在轴一至三未否证时改 HCM 超时;把 Envoy 503 一律写成「Gateway 控制器 hang」。

轴四出口:数据面已按当前快照正确服务,请求仍在后端失败,进入轴五。


六、轴五:东西向(指针到第 15 篇)

Gateway 返回 200 之后,包成为集群内的东西向流。失败可能是 identity 策略、Service BPF、加密路径,而南北向五轴全绿。把 Hubble Policy denied 写进 HTTPRoute 工单,或反过来用 Gateway status 解释跨节点黑洞,都会污染坐标系。

本篇只留口令:出了 Envoy Gateway 的 hop,换一套轴,不要扩写本篇的 status/IR/xDS。 北段/南段证据包、两套口令、CNI/KPR/加密/Gateway 四元组,在第 15 篇 回收 Cilium 15。本系列不重写 identity/map。


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

排障五轴走在编译器诊断传统上:先把失败钉到阶段(附着、中间表示、代码生成、运行时、下游环境),再打开该阶段的工具。Gateway API 把「配置已生效」拆成 Accepted / Programmed / ResolvedRefs(GEP-1364),就是在规范层拒绝单一 Ready。Envoy Gateway 再插入 IR 与 xDS 两跳,值班若把所有 404 写成「路由写错」,等于丢掉阶段名。

争论不在「要不要 status」,而在 status 绿是否足以当 SLO:轴二、轴三可以在条件看似成立时仍让流量走空 IR 或旧快照。开放问题交给第 16 篇:IR 对账是否一等公民、xds_nack_total 能否进发布门禁。


参考资料

规范 / 官方文档 / 源码(A)

站内对照

实验台账

上一篇:运维与升级 · 系列目录 · 下一篇:对照替代路径

读完这篇,下一步读什么

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

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 .