关掉 Istiod,业务请求会立即中断吗

不能从“控制面不可用”直接推出一个统一结论。第 06 篇的链路是规则提交、Istiod 等控制器处理、xDS 下发、代理当前配置、业务请求经过代理、应用返回;Istiod 不处于普通 orders → inventory 请求的数据面转发路径上。已有连接和已安装资源的代理可能继续转发,新代理能否取得 listener/cluster/endpoint、新版本 Pod 是否被发现、证书到期后能否续期是不同问题,不能用某个时刻的 HTTP 200 概括整个故障窗口。

控制面不可用期间,存量连接与缓存配置仍可能工作;新端点、新代理和证书续期各有独立失败窗口

旧 TCP 连接继续传输依赖其当前对端和连接状态;新 TCP 连接若代理仍拥有可用目标配置,未必立即失败。若库存扩容为 v2 或替换 v1 Pod,原有 endpoint 不一定仍有效;代理收到哪些变化、是否对新的 Pod 完成身份/证书初始化,必须读状态和实际请求。xDS ACK 说明控制面/代理曾就某个资源版本交互,不保证该资源此刻仍是全部必要配置,不保证请求成功;反过来短暂失去 Istiod 也不能证明现有业务连接必然断开。

按时间与资源划分故障域

测试对象 故障前保存的基线 失联时必须单独检查
存量连接 orders → inventory-v1 长连接、请求 ID、当前路由 连续流是否完成,代理和应用谁先报告失败
新连接/新请求 相同 SKU、新客户端连接 是否仍命中已知健康端点;是否重新解析/取配置
新 Pod 与端点 EndpointSlice、代理当前 EDS、库存版本 扩容/替换后请求是否可达,代理状态何时更新
新代理和身份 新 Pod 的 sidecar 或 ztunnel 准备状态 没有控制面时能否接收路由/证书,拒绝在哪里
证书轮换与恢复 公共证书到期时间、代理续期记录 临界时刻握手失败、恢复后是否重新收敛

表中的“故障前”不等于保证“故障中可用”:代理可能重启、路由依赖变更、证书失效或 kube 控制器发生并发故障。对 sidecar 和 ambient 都应分别测,上述表也不能拿 ambient 的某一节点成功外推所有节点健康。云端没有 Istiod 时,不得凭理论算出“能撑多少分钟”,有效期与缓存清理依赖实际发布版本和现场证据。

只在具名隔离环境做故障实验

先从 examples/service-mesh/ 执行只读检查;未确认当前 context、 namespace 和实际工作负载为合成实验前,不得停任何控制面:

1
SM_CONTEXT=service-mesh-lab SM_NAMESPACE=service-mesh-lab bash scripts/check-02.sh

具备专用集群后,先冻结 Kubernetes/Istio/Envoy 和 ztunnel 版本及镜像 digest、保存控制面运行状态、工作负载公开证书元数据、代理活跃配置与新旧连接日志。仅在有明确恢复手段的隔离实验控制面模拟中断,不碰生产或其他任务集群;记录真实开始/结束时刻。向同一 frontend → orders → inventory-v1/v2 服务链发固定负载,以不同请求 ID 区分存量连接、新连接、扩容后新实例及尝试变更目标规则,并把客户端退出码与库存应用日志对齐。单测正常连接仍可处理作为正例;负例让旧 endpoint 下线并在新 endpoint 上发送请求,若控制面不可用导致未更新,断言按期望报告非零,恢复后重测。证书续期需要在安全的短期实验凭据下单列观察,绝不提交私钥。

尚未建立独立实验集群,也未断开真实 Istiod。存量/新连接、端点变化、新工作负载、证书续期与恢复时间全部 NOT_RUN。第 13 篇本地进程超时不是控制面不可用的证据。

把故障分成三个时间窗口

已有代理持有配置和未过期证书时,控制面短暂不可用不一定中断业务。新 Pod 则可能在 admission webhook 阶段创建失败,也可能在已有注入结果下启动却拿不到配置或证书。更长的故障跨过证书续期、到期窗口后,原先正常的代理也可能无法建立新 mTLS 连接。这是三种不同实验,不能用一分钟故障推导一天后表现。

mainline/29/outage.sh 只执行第一种短时故障,并采新 Pod 创建结果。限定 kind-service-mesh-sidecar、默认 revision 的 istiod;不要在第 30 篇多 revision 状态下直接使用,否则仍存活的控制面会改变实验条件。先创建第 26 篇探针,读取证书到期信息,保存原 istiod 副本数。

1
2
3
4
bash scripts/setup-kind.sh sidecar
SM_CONTEXT=kind-service-mesh-sidecar bash mainline/26/run.sh apply
istioctl --context kind-service-mesh-sidecar proxy-config secret deployment/inventory-v1 -n service-mesh-lab
SM_CONTEXT=kind-service-mesh-sidecar bash mainline/29/outage.sh

脚本把 istiod 缩到零,对已有 mesh-probe 发起十次独立 curl,再尝试创建 cold-probe;创建失败会原样保存退出码和 webhook 错误,不能把失败吞掉后称新 Pod 运行正常。退出 trap 恢复原副本数,正常流程再等控制面 Ready,并发恢复请求。existing-proxy-new-connections.log 的准确含义是“已有代理建立新连接”,不是一条故障前 TCP 连接持续可用。

若要测试存量连接,先用支持持久连接的客户端建立流,再跨越故障时刻持续发送,记录连接四元组、HTTP/2 stream 或长连接标识;代理进程不重启。第 33 篇发生器 --keepalive 可提供复用输入,但连接是否重连仍需连接日志证明。无此证据,存量 TCP 场景保持 NOT_RUN。

续期实验需要记录证书 notBefore/notAfter、实际续期尝试和失败、到期后的新握手。为了缩短实验而修改证书寿命时,配置必须在签发前生效且实际新证书已验证;不能只修改环境变量然后按墙钟等待。主脚本不会长时间停控制面,也不伪造到期结果,该窗口明确留作独立实验。

1
2
3
4
kubectl --context kind-service-mesh-sidecar -n istio-system get deployment istiod -o yaml
kubectl --context kind-service-mesh-sidecar -n service-mesh-lab get events --sort-by=.lastTimestamp
istioctl --context kind-service-mesh-sidecar proxy-status
SM_CONTEXT=kind-service-mesh-sidecar bash mainline/26/run.sh cleanup

恢复判据包括 istiod Ready、代理重新连接控制面、此前配置缺失的新工作负载完成初始化、允许请求成功且错误身份仍拒绝。仅把副本数改回原值属于恢复动作,不等于恢复完成。若脚本被强制终止导致 trap 未执行,应依据输出中的原始 Deployment 快照恢复副本数,而非猜成 1。

本章集群实验均为 NOT_RUN,脚本完成时也只写 CAPTURED。原则是将故障持续时间与状态有效期放在同一条时间轴上。Istio 1.27 SDS 实现 与 证书缓存实现 是续期路径的固定源码入口。

练习与参考解答

  1. Istiod 不可用时,一条长连接仍成功,能证明发布新的 inventory-v2 没风险吗?参考解答:不能。该请求可沿已知旧连接和缓存配置成功;另外检查新端点是否进入代理当前配置、新实例身份和证书是否就绪、新请求是否真命中 v2,再看失败恢复窗口。
  2. 保持旧连接,实验中只替换 v1 Pod IP;如何反驳“只要不改路由,控制面掉线便完全无影响”?参考解答:分别记录旧连接与新连接目标、EndpointSlice 更新、代理当前 endpoint、客户请求 ID 和库存实际版本;若旧连接断而代理又无新端点,新请求会失败。恢复控制面后还要验证收敛,而不是只观察一次错误码。

官方参考与系列导航

系列导航:07 xDS 更新与拒绝 → 28 ambient 迁移 → 29 控制面故障(本文)→ 30 升级与回退。