服务网格 07:xDS 更新、依赖与拒绝
ACK 到了,为什么这条请求仍走旧路由
第 06 篇区分路由声明、Istiod 处理、代理状态和实际请求。现在要观察代理同控制面协商资源的过程:Envoy 对一次 xDS 响应确认(ACK),究竟确认了什么?路由(RDS)可能引用 cluster(CDS),cluster 可能引用端点集合(EDS);更新不是把一份“最终 YAML”原子广播给所有代理。适合已经认识 listener、route、cluster、endpoint 的读者。
图里的 ACK/NACK 属于特定流和资源类型的控制反馈;图下方的请求沿代理活跃配置执行。两条时间线需要同一代理标识和时间戳连接,不能把 Istiod 画在普通业务请求的中途。
ACK/NACK、资源依赖分别约束什么
控制面可使用聚合发现服务 ADS 在一个 gRPC 流内交换多类发现资源。SotW(state of the world)响应提供相应订阅范围的一组当前资源;Delta xDS 按增量订阅和新增/移除表达变化,两者资源版本的含义和删除方式不能机械套用。具体使用哪种模式须读取实际代理/控制面的协商与日志,不因文档提供两种协议就断言当前集群启用了 Delta。
代理收到响应,要按资源类型校验配置并以与响应关联的标识回传 ACK 或 NACK;NACK 有拒绝原因。它说明这次响应在该协议阶段未被接受,不能推出此前已接受的所有配置都被删除;也不能把“已有监听继续工作”写成“新资源已生效”。资源版本、响应 nonce、关联 proxy ID 和时间顺序应一起保存,单取一行 SYNCED 丢失了依赖和路径信息。
更新可能存在依赖:listener 引用尚未可用的 route,route 选择的 cluster 尚在构造,或 cluster 要等 endpoint/健康状态才能具备预期转发能力。Envoy 有活跃、warming 和排空等状态;即使对某资源发送 ACK,仍须检查本次请求将使用的活跃 listener/route/cluster/endpoint。旧连接可能仍使用旧配置或旧后端,配置推进与业务结果的时序不能跳步。
尤其要防止两种误诊:一是代理 NACK 某条错误 route,却把后端连接失败归咎于“全部端点被清空”;二是 route 已更新且有 ACK,但本次请求的 Host、路径或代理实例根本没命中这条路由。故障归因要跨越确认消息、当前配置、代理请求日志和真实应用结果。
用独立控制面观察 ACK、NACK 与保留配置
E08 提供真实 ADS 控制面与真实 Envoy 客户端。从 examples/service-mesh/ 执行 ENVOY_BIN=/path/to/envoy bash scripts/run-E08.sh --envoy;不带 --envoy 只运行协议测试,不能产生代理验收结论。此实验独立于 Istio,控制面源码位于 internal/teachingxds/,资源更新由 cmd/teaching-xds 接收。
观察链为 控制面发送版本/nonce → Envoy DiscoveryRequest 的 ACK 或 error_detail → 代理活跃配置 → /quote 响应版本。脚本先验证 v1,再更新到 v2;随后发送无效配置,要求控制面捕获 NACK,业务请求仍由最后有效的 v2 配置处理。最后恢复合法 v1,分别验证同一 node 重连和新 node 订阅。
为什么同时保留响应与协议日志?NACK 表示相应响应未被接受,不能单独证明全部业务资源仍可用;ACK 则不能证明该路径存在健康端点。必须把拒绝的 sent_version、请求携带的已接受 version、nonce 和 error_detail 对应到同一次会话。离线构造 DiscoveryRequest 的测试也不能冒充 Envoy 自己发出的 NACK。
evidence/E08/<时间>-<PID>/ 保存协议日志、控制面输出、Envoy 配置快照和各阶段 HTTP 结果。Istio 对象经 Istiod 翻译到 xDS 的链路由第 06 篇另外验证;此处不宣称覆盖 Istiod 的资源生成、增量 xDS 或生产安全配置。
2026-10-03 Linux 实测记录在 examples/service-mesh/evidence/E08/20261003T090715Z-2/,本轮运行通过;原始命令、退出码和日志限定结论适用范围。
[PATTERN] 版本化状态同步通过响应关联和最后有效配置减少失败更新的影响,但资源依赖仍要求独立校验。
| 原则 | 观测对象 |
|---|---|
| 确认按会话关联 | node、type、version、nonce |
| 拒绝后检查业务状态 | NACK 后继续请求最后有效后端 |
| 恢复需要新证据 | 合法更新后 ACK 与响应均回到 v1 |
练习与参考解答
- 有 RDS 的 ACK,两个 orders Pod 中只有一个返回 v2。怎样判断是收敛还是请求匹配?参考解答:先按代理 ID 分别检查当前活跃 route、cluster/endpoint 与资源时间线,再发送相同 host/头、不同请求 ID,通过两个代理日志与后端记录分别核对;只从一个 ACK 无法推断另一代理状态,更不能推出两次请求是否使用同一连接。
- 构造“配置被拒却业务暂时仍成功”的反例。参考解答:在实验环境尝试一条会产生确切 xDS NACK 的受控更新,并保留此前工作正常的旧版配置;若 API 层先拒绝,则改记 API 拒绝而不冒充 NACK。若实际观察到 NACK 后旧 route 仍被用于同一请求 ID 的成功返回,说明新响应被拒不等于旧资源立刻消失;必须用时间线验证,不能从规范文字虚构结果。
官方资料与系列导航
- Envoy v1.37.0 xDS 协议:ADS、SotW/Delta、ACK/NACK 与资源依赖;这里按固定候选文档版本阅读。
- Envoy v1.37.0 初始化与 warming:活跃前的配置阶段,具体可观测字段需实测。
- Istio proxy-status:同步诊断工具入口,不代替 proxy 的 config dump 和请求路径。
系列导航:00 基线 → 01 治理 → 02 Service → 03 Envoy → 04 Sidecar → 05 启停 → 06 路由 → 07 xDS 更新、依赖与拒绝(本文)→ 08 服务发现、DNS 与端点更新。
