要不要上网格,不能只比较代理的 p99

决策输入是需要哪些跨服务能力和统一治理、谁来承担证书/策略/升级/排障、现有 SDK/网关/网络策略能覆盖哪些边界,以及切换后产生的业务风险。第 33 篇的四种模式甚至没有天然等价的功能集合,不能仅用单个延迟数字选择产品。对于累计 frontend → orders 调用链(orders 先调用 inventory,成功后再调用 external-stub),先把请求头灰度、工作负载身份、入口出口约束、授权拒绝、超时重试、日志和回滚列成验收条目,另把 POST /reserve 的去重留给应用。网格可以执行跨进程策略,不能替代订单事务。

网格选择门禁:列需求与替代措施,对每项做正常/失败实验,再决定进入、保持或实际退出

场景 A:多个平台团队要对 Service 间身份与 HTTP 路由作一致治理,应用语言多、证书轮换由平台承担;网格可能减少应用重复实现,但要付控制面/数据面容量、版本偏差、策略作用域及故障排查成本。场景 B:少量同语言服务、只需 SDK 的超时与明确的入口限制,可能先用应用 SDK、网关和网络策略达到需求,不为不需要的 HTTP 授权引入共享 waypoint。两者都只是条件分支:当前没有网格真实实验和功能等价测量,不能替任何组织宣布“应该采用”或“应该退出”。

给每项能力找负责方

需要保留的能力 网格可执行的位置 退出时需另有的实现和失败判据
跨服务身份与传输保护 sidecar/ztunnel、证书轮换 应用/平台的 mTLS 与证书分发;错误身份不得成功
请求头灰度、超时、重试 七层代理及策略 SDK/网关或应用代码;v2 后端版本与 attempts 要对应
入口/出口边界 网关、代理路由和网络约束 替代入口 TLS/来源校验、出口 NetworkPolicy 等;直连不能绕过
方法授权与审计 目的 sidecar 或绑定的 waypoint 应用/网关明确拒绝,代理撤下后非法写入不增加账本
遥测/排障 代理与应用协作 应用保留请求 ID/追踪上下文,接收端收到 Span
业务去重 不属于网格能力 库存服务原子去重或补偿;超时重发不得重复副作用

表中“替代”不是一句“交给 SDK”:每一行必须有部署位置、负责团队、配置/证书版本、失败场景和可复跑的正反断言。NetworkPolicy 是否真能执行取决于 CNI;ServiceEntry 只是代理层目的地配置,不是出口防火墙。代理 Span 能产生也不等于应用传播上下文;退出后若只保留请求 ID,应明确尚未达到追踪门禁。

先验证退出,再决定卸载

从 examples/service-mesh/ 的只读前置脚本开始,只有确认具名隔离集群、替代控制和回退计划,才允许任何模式切换:

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

在隔离集群记录 sidecar 和 ambient 的当前请求/授权/证书/账本基线,对合成服务逐项启用替代能力:将 TLS 和身份验证放到指定实际连接段、将灰度转到应用/网关或先撤除该需求、将出站强制约束放到支持它的 CNI 和网络策略、把写入去重放在业务事务中。对每项分别发正常请求和错误身份/无效头/直连出口/重复操作 ID 的负例,保存配置、当前代理和请求路径、应用结果;应拒绝却成功或副作用重复时返回非零并回退替代方案。只有各项达标,才在事先批准的仅属于本实验的资源范围逐批移除注入、waypoint、ztunnel/CNI 等组件,期间验证长连接、新端点与证书变更。绝不在共享/生产集群执行网格卸载命令,也不能以删掉资源对象后的健康检查 200 替代真实退出证明。

尚未建立相容集群、测量网格运行成本或验证实际退出过程;采用判断与真实退出验证均待验收(NOT_RUN)。第 09 篇进程 TLS 名称校验不是应用间 mTLS;第 01 篇重复账本仍是示例的缺口,不能因为评估退出就自动修复。

退出必须先替换仍然需要的控制

mainline/35/exit.sh 只处理本系列的隔离 namespace。它要求提供替代控制的证据文件,但文件存在并不等于替代措施正确:内容应写清原来由网格提供的认证、授权、路由、超时、重试和遥测,由哪个组件接管,以及对应正负请求的原始记录位置。若业务决定取消某项控制,应记录正式需求变化,不能把缺失解释成迁移成功。

无网格基线应用目前没有自行提供 mTLS。因此若需求仍要求工作负载双向认证,不能直接执行退出并宣称功能等价;需要应用 TLS、其他代理或平台网络方案先落地验证。性能下降或运维复杂度可以成为退出动机,但不替代安全与业务契约。

先保存资源和依赖清单,尤其是 Gateway、路由、授权策略、ServiceEntry、远端服务发现与证书来源。确认还有没有其他 namespace 依赖同一 waypoint、入口/出口网关或 istiod;共享组件的删除不能随一个业务退出自动触发。

1
2
SM_CONTEXT=kind-service-mesh-sidecar bash mainline/35/exit.sh capture
kubectl --context kind-service-mesh-sidecar -n service-mesh-lab get virtualservice,destinationrule,serviceentry,authorizationpolicy,peerauthentication -o yaml

替代路径准备好后,先把一小批流量导入它,分别测试正常报价、错误身份、禁止方法、慢库存、依赖断开和恢复。退网前后要比较相同业务结果与失败方式;例如原先代理超时后应用仍继续处理的行为,替代客户端是否也需要取消,不能只比较 200 正例。

1
SM_CONTEXT=kind-service-mesh-sidecar SM_REPLACEMENT_RECEIPT=/absolute/path/replacement-controls.txt bash mainline/35/exit.sh detach

脚本移除 namespace 注入/revision/ambient 标签与库存 waypoint 绑定,再按明确名单重建 frontend、orders、inventory-v1/v2、external-stub。已有 sidecar 不会因删除标签从运行中的 Pod 消失,所以必须重建并检查容器列表;ambient 则还需确认 CNI 接管状态与 ztunnel 工作负载视图。这里按维护窗口进行,不承诺五个 Deployment 的切换原子性。

若脱离后正例失败,先恢复原 namespace 模式标签及策略,再重建同一批 Deployment,复跑原正负门禁。sidecar 可重设 istio-injection=enabled;ambient 则恢复 istio.io/dataplane-mode=ambient 和原 waypoint Service 绑定。不同模式不能同时残留互相冲突的注入标签。回退成功前不要卸载控制面,证书与代理配置的恢复仍依赖它。

1
2
kubectl --context kind-service-mesh-sidecar -n service-mesh-lab get pods -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.spec.containers[*].name}{"\n"}{end}'
SM_CONTEXT=kind-service-mesh-sidecar bash mainline/35/exit.sh capture

退出判据至少包括预期 Pod 不再含 sidecar、真实请求经过替代路径、必须保留的正负业务契约通过,以及一个完整观察窗口内没有依赖旧网格组件的请求。主脚本只写 DETACHED,不会写功能通过。清理分两层:先删除已不再生效的本章业务实验资源,最后才在确认整个隔离集群无其他使用者后销毁 kind 集群;不把 istioctl uninstall --purge 作为业务退网的第一步。

当前真实退出与替代控制验收为 NOT_RUN。可复用原则是先迁走能力和依赖,再移除基础设施。只有功能与成本条件都满足时,采用或退出才是可检验的工程决策。Istio 1.27 注入实现 可核对注入标签为何影响新建 Pod 而不是修改存量容器。

练习与参考解答

  1. 只把 sidecar 从 Pod 移走,业务 GET 200,能判“退出网格成功”吗?参考解答:不能。还需确认此前的 mTLS/错误身份、请求头路由、方法授权、出口直连阻断与追踪收到数据都有替代执行点;同时检查应用进程与长连接、副作用账本,并验证 ambient CNI/waypoint 等组件是否仍在接管。
  2. 保留网格路由 v2 的能力需求,却只有 SDK 可以按固定地址重试,没有版本选择;决策表如何填写?参考解答:该行替代不等价,标未满足门禁,不能按“功能已迁移”退出。可明确取消 v2 灰度需求并经审批,或实现并实测替代路由;再用带/不带 canary 头、错误 subset 的合成请求与真实后端版本验证。

官方参考与系列导航

系列导航:00 无网格调用 → 33 性能对照 → 34 综合发布 → 35 采用或退出(本文)。选修随后按先修顺序展开。