Skip to content

Service Mesh从零到生产级:Envoy、xDS、mTLS与流量治理原理 ​

Service Mesh把服务间通信中的一部分通用能力从业务SDK下沉到代理和控制面:服务发现、四层/七层路由、mTLS、重试、超时、熔断、异常实例剔除和遥测。它解决的是“服务怎样安全、可观测、可治理地互相通信”,并不替代业务幂等、数据库事务、消息最终一致、用户权限或领域错误处理。

本页以Envoy和Istio常见模型解释原理,同时标明Consul Connect、Linkerd和Sidecar/Ambient形态的边界。产品字段随版本演进,生产配置必须以目标版本文档和实际代理配置为准;这里讲的是稳定的对象关系和失败模型。

学完本页后继续进入 Service Mesh 内部原理与生产治理:从 Envoy Worker、Listener Filter、HCM、Route、Cluster、Endpoint 和连接池一路追到 xDS 双向流、Warming、Panic Mode、Outlier Detection、SDS、Ambient、商业配置 Demo 与逐层 Runbook。面试标准回答单独放在 Service Mesh 独立面试题。

一、学习目标 ​

学完后应能:

  1. 区分Mesh控制面与数据面,解释控制面异常时已有流量为什么可能继续。
  2. 解释Envoy Listener、FilterChain、Route、Cluster、Endpoint和Secret的关系。
  3. 解释LDS、RDS、CDS、EDS、SDS分别下发什么。
  4. 说清xDS的版本、nonce、ACK、NACK和Last Known Good配置。
  5. 画出Sidecar出站、入站和mTLS完整调用链。
  6. 解释工作负载身份、证书签发、轮换、信任域和授权边界。
  7. 区分连接超时、请求超时、每次尝试超时、总Deadline和空闲超时。
  8. 解释重试乘法、熔断、异常实例剔除、局部性路由和灰度发布。
  9. 区分Sidecar、Ambient、Spring Cloud SDK和API Gateway的职责。
  10. 按503 NR/UH/UF、xDS NACK、mTLS失败和配置陈旧执行Runbook。

二、Mesh解决什么,不解决什么 ​

能力Mesh可以做什么仍由业务负责什么
服务发现把平台端点转换为代理可用后端业务服务身份和版本契约
路由按Host、Header、权重、路径分流灰度数据兼容和回滚决策
mTLS工作负载双向认证和链路加密用户认证、字段加密、业务授权
重试对选定失败类型执行有界重试幂等键、结果查询、补偿
超时在代理层终止过慢调用业务Deadline传播和取消语义
熔断限制连接、请求、Pending和重试容量规划和业务降级结果
遥测记录代理看到的流量、延迟和状态业务事件、订单号和领域结果

不使用Mesh也可以做微服务;使用Mesh也不会自动得到“Exactly Once”。代理看到上游超时,不知道下游数据库是否已经提交。涉及支付、库存和退款时,调用方仍需稳定业务号、幂等和事实查询。

三、控制面与数据面 ​

mermaid
flowchart TD
    A["Kubernetes Service与EndpointSlice"] --> B["Mesh控制面构建期望配置"]
    C["路由、安全与授权策略"] --> B
    B --> D["通过xDS下发给代理"]
    D --> E["调用方数据面代理"]
    D --> F["服务方数据面代理"]
    E --> G["真实业务请求不经过控制面"]
    G --> F
    F --> H["业务容器"]

3.1 控制面 ​

控制面观察服务注册、端点、配置和安全策略,计算每个代理应该看到的监听器、路由、集群、端点和证书。它是配置分发者,不应位于每次业务请求的数据路径中。

3.2 数据面 ​

数据面代理实际接收、建立连接、路由、加密、重试和记录指标。Sidecar模式通常每个Pod一个代理;其他模式可能在节点或专用网关中承担部分能力。

3.3 为什么控制面挂了流量可能继续 ​

代理通常保留已经接受的Last Known Good配置。控制面短暂不可用时:

  • 已有Listener、Route、Cluster和Endpoint仍能处理流量。
  • 已建立连接可以继续使用。
  • 新服务、新端点、路由变更和证书轮换可能无法及时生效。
  • 配置过旧、证书到期或端点全部变化后,数据面仍会逐渐失效。

所以“控制面挂了业务完全没事”与“控制面挂了所有流量立刻断”都不准确。答案取决于缓存配置、证书剩余时间、端点变化和代理重启。

四、Envoy核心对象 ​

对象作用可类比理解
Listener监听地址和端口,接收进入代理的连接入口插座
FilterChain按传输协议、SNI等选择一组处理链入口分流规则
Network Filter处理TCP层协议四层处理器
HTTP Connection Manager解析HTTP并承载HTTP过滤器和路由七层总入口
Route Configuration按域名、路径、Header匹配目标Cluster路由表
Cluster一个逻辑上游服务及连接、LB、健康配置服务目标
EndpointCluster中的实际IP、端口、优先级和地域服务实例
SecretTLS证书、私钥和信任根等动态安全材料

一次HTTP出站调用的对象关系:

mermaid
flowchart TD
    A["连接进入Outbound Listener"] --> B["FilterChain选择协议处理"]
    B --> C["HTTP Connection Manager解析请求"]
    C --> D["VirtualHost与Route匹配"]
    D --> E["Route选择目标Cluster"]
    E --> F["Load Balancer选择Endpoint"]
    F --> G["连接池取得或建立上游连接"]
    G --> H["TLS过滤器执行mTLS"]
    H --> I["请求发送到服务方代理"]

常见误区是把Cluster等同于一个IP。Cluster是逻辑目标,内部有多个Endpoint、连接池、健康和负载策略。路由先选Cluster,负载均衡再从Cluster中选Endpoint。

五、xDS:控制面怎样把配置交给Envoy ​

xDS是动态配置API族,不是单个“注册中心协议”。常见资源:

API下发内容缺失或错误的表现
LDSListener和FilterChain端口未监听、入站/出站无法接收
RDSHTTP Route、VirtualHost、匹配规则404或NR,流量到错版本
CDS上游Cluster、连接和LB策略找不到目标Cluster
EDSCluster的Endpoint和局部性信息UH、无健康后端、旧地址
SDS证书、私钥、信任根TLS握手失败或证书过期

有些配置可内联在其他资源中,产品也可能使用聚合发现服务统一承载多个资源流。理解重点不是背缩写,而是明确“监听、路由、逻辑服务、实例、安全材料”是不同生命周期的资源。

六、一次xDS配置更新完整过程 ​

mermaid
flowchart TD
    A["平台端点或策略发生变化"] --> B["控制面计算代理目标配置"]
    B --> C["xDS响应携带资源、version与nonce"]
    C --> D["代理解析并做语义校验"]
    D --> E{"配置是否可接受"}
    E -- "是" --> F["原子发布新配置并ACK"]
    E -- "否" --> G["保留Last Known Good并NACK"]
    F --> H["后续新流量使用新快照"]
    G --> I["控制面记录错误并修正"]

6.1 version与nonce不是同一个概念 ​

  • version_info用于标识控制面所表达的资源版本或快照版本。
  • response_nonce标识某次具体响应,代理在下一次请求中回显,便于控制面关联ACK/NACK。
  • NACK通常会携带错误详情,表示代理未接受那次响应。
  • ACK表示代理接受配置,不等于真实业务一定成功,也不等于所有代理都已ACK。

控制面不能只看“配置对象已保存”,还要观察目标代理的下发状态、ACK/NACK、版本分布和收敛时间。

6.2 State of the World与Delta ​

State of the World响应通常表达某类资源的完整目标集合,客户端按整体快照更新;Delta xDS按资源增删变化传递并维护订阅状态。两者的协议字段和恢复方式不同,但工程目标相同:代理必须从有版本的资源流收敛到一致、可验证的本地配置。

不要自己拼接半份Route或Endpoint直接覆盖生产代理。资源之间有依赖顺序,例如Route引用的Cluster必须存在,Cluster使用的Secret必须可用。成熟控制面需要依赖分析、增量推送、回滚和状态观测。

6.3 ACK不等于全局生效 ​

一次发布可能处于这些状态:

  1. 配置已写入控制面存储。
  2. 控制面已计算目标代理配置。
  3. 一部分代理收到响应。
  4. 一部分ACK,一部分NACK或断连。
  5. ACK代理开始处理新连接,旧连接仍按旧路由或旧TLS会话存在。

因此灰度平台应按代理和工作负载统计配置版本,不应在“API返回200”后立即认为全网切换完成。

七、Sidecar流量怎样进入代理 ​

Sidecar模式常通过Pod网络命名空间中的iptables或eBPF规则透明拦截流量:

  • 出站:业务容器连接目标地址,规则重定向到本地出站Listener。
  • 入站:进入Pod端口的连接先被重定向到入站Listener,再转发给业务容器。
  • 排除:代理自身UID、健康检查端口、控制面地址等必须避免循环拦截。
mermaid
flowchart TD
    A["调用方业务容器发起请求"] --> B["Pod重定向规则捕获出站连接"]
    B --> C["调用方Sidecar匹配Route和Cluster"]
    C --> D["选择Endpoint并建立mTLS连接"]
    D --> E["服务方Sidecar接受并校验身份"]
    E --> F["入站授权和遥测过滤器"]
    F --> G["转发到服务方业务容器"]

透明拦截不是魔法:

  • UDP、原始Socket、HostNetwork和特殊协议可能有额外边界。
  • 应用自己发起TLS时,代理能否做L7路由取决于是否终止或理解该连接。
  • 端口协议识别错误会让HTTP治理退化为TCP或解析失败。
  • 排除规则错误可能形成代理自连接循环。

八、mTLS与工作负载身份 ​

普通单向TLS主要让客户端验证服务端;mTLS还让服务端验证客户端证书。Mesh通常为工作负载颁发短期身份凭据,由代理完成握手。

mermaid
flowchart TD
    A["工作负载获得平台身份"] --> B["CA验证身份并签发短期证书"]
    B --> C["SDS把证书和信任根交给代理"]
    C --> D["调用方代理发起TLS握手"]
    D --> E["双方验证证书链、身份和有效期"]
    E --> F["协商会话密钥并加密传输"]
    F --> G["服务方按来源身份执行授权策略"]

8.1 身份不是Pod IP ​

Pod IP会变化,不能作为稳定身份。Mesh身份通常绑定命名空间、ServiceAccount或工作负载标识,并编码到证书SAN中。授权策略应判断经过验证的身份,而不是只信任请求Header中由调用者随意填写的用户名。

8.2 证书生命周期 ​

  1. 工作负载启动并证明平台身份。
  2. CA或身份服务签发短期证书。
  3. SDS等机制把证书交给代理,避免业务代码直接管理私钥。
  4. 到期前主动轮换,新旧材料可在有限窗口重叠。
  5. 代理新连接使用新证书,已有TLS连接可能继续到关闭。

轮换失败不会一定立即中断;通常要等证书到期或新连接建立才暴露。必须监控证书剩余时间、SDS推送和握手错误。

8.3 STRICT、PERMISSIVE与迁移窗口 ​

  • STRICT:入站只接受符合Mesh mTLS要求的连接。
  • PERMISSIVE:迁移阶段可能同时接受明文和mTLS。
  • DISABLE或明文策略:只应在明确边界使用。

PERMISSIVE便于渐进迁移,但扩大明文窗口;STRICT过早启用会让未注入Sidecar、旧VM或探针调用失败。应先清点调用方、观察遥测、灰度策略,再收紧。

8.4 mTLS不等于业务授权 ​

mTLS回答“哪个工作负载建立了连接”,不能回答“这个用户能否退款1000元”。服务间授权可按工作负载身份限制调用关系;用户权限、订单归属、字段级权限仍由业务认证授权处理。

九、一次Mesh HTTP调用全过程 ​

  1. 业务线程根据Service DNS或原地址发起请求。
  2. 出站重定向规则把连接交给调用方代理。
  3. Listener和FilterChain识别端口、协议和TLS模式。
  4. HTTP Connection Manager解析Host、Path和Header。
  5. Route匹配目标Cluster,并计算超时、重试、Header改写和权重。
  6. Cluster负载均衡从当前健康Endpoint快照选择目标。
  7. 连接池复用或建立到服务方代理的连接。
  8. 双方代理执行mTLS并验证证书链和工作负载身份。
  9. 服务方代理执行入站授权、限流或遥测过滤器。
  10. 请求转发给业务容器,业务线程访问数据库并产生结果。
  11. 响应沿代理链返回,各层记录状态码、延迟和字节数。
  12. 若触发可重试条件,调用方代理在总预算内选择另一个Endpoint再尝试。

代理重试发生在第12步时,第一次请求可能已经提交数据库但响应丢失。因此支付创建、库存扣减等写接口必须使用幂等键,不能依赖“Mesh只会在安全情况下重试”的想象。

十、超时与Deadline为什么必须分层 ​

超时约束对象配置过大后果配置过小后果
Connect timeout建立上游连接故障地址拖住资源网络稍慢即失败
Per-try timeout单次尝试第一次耗尽总预算慢请求被过早放弃
Request timeout代理处理整个请求在途请求长期占用合法长操作被截断
Idle timeout连接或流空闲僵尸连接长期存在正常长连接频繁断开
应用业务Deadline端到端业务剩余时间下游做无效工作无法完成业务最小步骤

正确关系通常是:调用方总Deadline大于单次尝试时间,但小于上游允许等待时间;每次向下游传播“剩余预算”,而不是每层重新获得完整10秒。

假设网关10秒、订单服务10秒、库存服务10秒、数据库10秒,最坏不是10秒,而可能层层耗尽并让上游早已放弃后下游仍继续工作。生产要使用端到端Deadline并预留序列化、排队和响应返回时间。

十一、重试、重试乘法与结果未知 ​

mermaid
flowchart TD
    A["一次用户请求"] --> B["网关最多2次尝试"]
    B --> C["Sidecar每次最多2次尝试"]
    C --> D["HTTP客户端每次最多3次尝试"]
    D --> E["最坏可能形成12次下游尝试"]
    E --> F["下游故障被重试流量进一步压垮"]

重试设计必须同时满足:

  • 明确可重试错误:连接前失败、特定网关错误等。
  • 请求具备幂等语义或稳定幂等键。
  • 有总Deadline、最大次数、退避和抖动。
  • 有全链路重试预算,避免每层独立放大。
  • 观察Attempt数量,而不只看用户请求数。
  • 下游过载时优先快速失败,而不是继续重试。

HTTP GET也不天然安全:如果接口错误地在GET中产生副作用,代理无法替业务修正。POST也可以在业务幂等协议保护下安全重试。

十二、负载均衡、局部性与慢启动 ​

常见策略包括Round Robin、Least Request、Random、Ring Hash或Maglev等一致性选择。选型取决于请求耗时分布、连接模型、会话亲和和扩缩容频率。

  • Round Robin简单,但不感知某Pod上已有大量慢请求。
  • Least Request倾向当前较空闲实例,但指标和采样有滞后。
  • 一致性哈希可提高同Key命中同实例概率,却会形成热点且成员变化会迁移Key。
  • Locality优先可减少跨区成本,但本区容量不足时需要受控溢出。
  • 新Pod需要Warmup或Slow Start,避免刚Ready就承接等比例大流量。

Mesh LB通常基于代理当前EDS快照和本地统计,不是全局精确调度器。每个调用方代理可能做出不同选择。

十三、熔断、并发限制与异常实例剔除 ​

13.1 Envoy语境中的Circuit Breaking ​

Envoy Cluster的熔断阈值常用于限制最大连接、最大Pending请求、最大并发请求和最大重试等资源。它与Resilience4j按失败率进入OPEN状态的“断路器状态机”不是完全同一个概念,面试时应说明语境。

13.2 Outlier Detection ​

异常实例检测根据连续5xx、成功率或本地连接错误等统计,暂时把Endpoint从该代理的可选集合中剔除,过一段时间再试探恢复。

边界:

  • 它通常是每个代理的本地判断,不保证全网同时剔除。
  • 样本少时容易误判。
  • 下游整体故障时不能把所有实例无限剔除,需最大剔除比例。
  • 业务4xx通常不应当作实例故障。
  • 慢请求、连接失败和5xx的权重应按业务校准。

13.3 熔断不是降级结果 ​

代理可以快速拒绝,却不知道该返回“库存未知”“稍后重试”还是“进入待确认”。业务服务仍需把基础设施错误映射为稳定领域状态。

十四、灰度、金丝雀与镜像流量 ​

按权重把90%流量给v1、10%给v2,只说明代理路由概率,不保证每个小时间窗精确90/10。连接复用、样本数和哈希都会造成波动。

生产灰度步骤:

  1. 先验证v2配置和证书已下发,目标代理无NACK。
  2. 用Header或内部账号做定向验证。
  3. 从极小权重开始,按版本观察业务成功率、P99、资源和下游影响。
  4. 确认数据库Schema、缓存Key和消息事件兼容。
  5. 逐步放量,每一步等待足够观察窗口。
  6. 回滚时同时考虑旧连接和配置传播,不把“权重改为0”当瞬时切断。

流量镜像会复制请求但通常丢弃镜像响应。若镜像请求能写数据库、发短信或扣库存,就会产生真实副作用。镜像目标必须只读、使用隔离数据或显式禁用副作用。

十五、代理遥测能看到什么 ​

建议至少观察:

  • 请求数、成功率、响应码和P50/P95/P99。
  • 上游连接建立、活动连接、连接失败和重置。
  • Pending请求、并发请求和熔断拒绝。
  • 重试Attempt、重试成功率和重试溢出。
  • 每Cluster、Endpoint、Zone和版本流量。
  • xDS连接、配置版本、ACK/NACK和同步状态。
  • mTLS握手失败、证书剩余时间和SDS更新。
  • Sidecar CPU、内存、文件描述符和事件循环延迟。

代理只知道网络视角。HTTP 200可能包含业务错误码,异步消息可能在响应后失败,数据库提交可能发生在客户端超时前。必须把traceId、业务流水号和应用指标关联起来。

十六、Sidecar与Ambient形态 ​

维度SidecarAmbient或节点共享形态
部署每个工作负载Pod一个代理节点级安全隧道加可选L7代理等
资源成本随Pod数增长可减少每Pod代理成本
故障域单Pod代理故障影响该Pod共享组件故障域可能更大
升级需滚动工作负载或特定热升级机制基础设施组件可独立升级
L7能力通常靠近应用完整处理可能按需经过L7Waypoint等组件

Ambient是产品演进方向之一,具体能力、限制和成熟度依版本而变。不能把Sidecar配置原样复制后就假设Ambient行为完全一致。迁移前要验证流量捕获、身份、L7策略、可观测性和故障域。

十七、Mesh、Spring Cloud、Gateway怎么分工 ​

组件最适合的职责不应单独承担
Spring Cloud客户端Java内调用、LoadBalancer、Feign、业务降级适配多语言统一mTLS
Service Mesh服务间mTLS、代理路由、通用遥测和网络治理领域幂等和事务
API Gateway南北向认证、API聚合、外部协议和配额所有东西向细粒度代理
Kubernetes Service稳定寻址和平台四层转发七层业务路由和工作负载证书
Nacos/Consul注册、健康、配置或服务网络控制面业务数据一致性

双栈治理最常见的问题是重复配置:Feign重试一次、Spring Cloud LoadBalancer重试一次、Sidecar再重试两次;应用超时3秒、代理超时15秒;SDK熔断认为实例不可用而代理仍继续发送。迁移时要建立能力所有权矩阵,逐项决定保留在哪一层。

十八、Java 8/Boot 2与Java 17+/Boot 3边界 ​

Mesh代理运行在独立进程或基础设施层,一般不依赖业务JDK版本。两条Java基线的差异主要在应用接入:

项目JDK 8 / Boot 2.7Java 17+ / Boot 3.x
命名空间Java EE依赖常见javax.*Jakarta依赖迁移到jakarta.*
观测Sleuth等旧链路体系常见Micrometer Observation/Tracing主线
健康Actuator探针可用,按2.x配置验证Actuator与Kubernetes探针按3.x配置验证
HTTP客户端旧Feign/RestTemplate生态较多新版Feign、RestClient/WebClient等组合
Spring Cloud选择与Boot 2.7兼容发行列选择与具体Boot 3.x兼容发行列

共同要求:传播trace上下文和业务Deadline、使用幂等键、实现SIGTERM优雅关闭、不要与Mesh重复重试、暴露业务指标。完整Boot差异见Java 17+与Spring Boot 3.x。

十九、JDK 8 Demo:证明多层重试会乘法放大 ​

java
public class RetryMultiplicationDemo {
    static int attempts;

    interface Call {
        boolean execute();
    }

    static boolean retry(int maxAttempts, Call call) {
        for (int i = 1; i <= maxAttempts; i++) {
            if (call.execute()) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        boolean result = retry(2, new Call() {              // 网关层
            public boolean execute() {
                return retry(2, new Call() {                // Sidecar层
                    public boolean execute() {
                        return retry(3, new Call() {        // HTTP客户端层
                            public boolean execute() {
                                attempts++;
                                System.out.println("downstream attempt=" + attempts);
                                return false;
                            }
                        });
                    }
                });
            }
        });
        System.out.println("result=" + result + ", attempts=" + attempts);
    }
}

输出会到12次下游尝试。它兼容JDK 8;Java 17+可用Lambda简化语法,但不会改变2 × 2 × 3的容量事实。生产应把重试集中在最了解错误语义的一层,其他层关闭或共享总预算。

二十、商业场景:支付调用库存与风控 ​

订单服务调用库存和风控时:

  1. 用户请求进入Gateway,完成用户认证和外部配额。
  2. 订单Sidecar根据Route选库存Cluster和Endpoint。
  3. 双方使用工作负载mTLS,库存入站策略只允许订单身份。
  4. 请求携带orderNo幂等键和端到端Deadline。
  5. 库存本地事务用唯一流水和条件更新扣减。
  6. 若响应丢失,代理不应无限重试;订单按orderNo查询库存事实。
  7. 新库存版本先按Header定向,再按1%、5%、20%逐步放量。
  8. 代理指标发现网络错误,业务指标确认扣减成功率,二者共同判断发布。

Mesh保证链路身份和通用流量治理,库存唯一约束保证重复请求不重复扣减,订单状态机处理结果未知。三个层次不能互相替代。

二十一、关键失败窗口 ​

窗口现象恢复方向
控制面已保存但代理未收到新路由只在部分实例生效查xDS连接与版本分布
代理收到但NACK保留旧配置查错误详情和资源依赖
EDS已更新但旧连接存在已摘除Pod仍有请求区分新旧连接并Drain
SDS轮换失败但旧证书未到期短期正常,之后集中握手失败监控剩余有效期并修复SDS
上游超时但下游已提交客户端认为失败,业务实际成功幂等键和事实查询
灰度权重回滚但连接复用v2仍短暂有流量观察连接并有界排空
Sidecar过载应用正常但代理延迟、拒绝查代理CPU、内存、FD和队列

二十一点五、Envoy Response Flag:从状态码反推失败层 ​

Service Mesh 排查里只看 HTTP 503 很容易走错方向。同样是 503,可能是没有路由、没有健康上游、连接失败、资源溢出、上游超时或重试耗尽。Envoy 访问日志里的 RESPONSE_FLAGS 和 RESPONSE_CODE_DETAILS 能帮助你先定位失败阶段。

常见标志可按调用链理解:

mermaid
flowchart TD
    A["请求进入代理"] --> B{"Route是否匹配"}
    B -- "否" --> C["NR<br/>No Route"]
    B -- "是" --> D{"Cluster是否存在且有Endpoint"}
    D -- "无健康上游" --> E["UH<br/>No Healthy Upstream"]
    D -- "有候选" --> F{"连接是否建立"}
    F -- "失败" --> G["UF<br/>Upstream Failure"]
    F -- "成功" --> H{"资源阈值是否溢出"}
    H -- "溢出" --> I["UO<br/>Overflow"]
    H -- "未溢出" --> J{"上游是否按时返回"}
    J -- "超时" --> K["UT<br/>Upstream Timeout"]
    J -- "重试耗尽" --> L["URX<br/>Retry Exhausted"]
Flag常见含义首要排查层常见证据
NR没有匹配路由或路由配置不可用Listener、HCM、VirtualHost、Route、RDSHost/Authority、Path、端口、协议识别、RDS同步状态
UH没有健康上游Cluster、EDS、Endpoint、Subset、健康检查Cluster名、Endpoint数量、Pod Ready、Outlier、Panic、Locality
UF上游连接失败网络、端口、TLS、服务方Sidecar连接拒绝、Reset、NetworkPolicy、mTLS握手、目标端口
UO上游资源溢出Cluster Circuit Breaker、连接池、Pending、重试max connections、pending requests、active requests、retry overflow
UT上游请求超时Route Timeout、Per-try Timeout、下游执行下游P99、线程池、DB锁、连接池等待、Attempt耗时
URX重试次数耗尽或重试相关失败Retry Policy、Retry Budget、DeadlineAttempt次数、重试条件、剩余预算、Retry Overflow
UC上游连接中途断开上游进程、连接池、HTTP/2、网络GOAWAY、Pod重启、连接年龄、节点网络
DC下游连接断开客户端、网关、调用方取消客户端超时、浏览器断开、Gateway取消、下游仍可能执行

排查顺序必须先定位“哪个代理打出的 Flag”。例如:

代理位置意义
Gateway Envoy 返回 NR入口路由没有匹配,业务服务可能完全没收到请求
调用方 Sidecar 返回 UH调用方看到的目标 Cluster 没有健康 Endpoint
调用方 Sidecar 返回 UF选到了 Endpoint,但连接或TLS失败
服务方 Sidecar 返回 403/401请求已经到达服务方代理,可能是身份或授权策略拒绝
应用容器返回 500Mesh已经把请求转给业务,重点看业务日志、数据库和异常

不要把 Flag 当成绝对根因。它是代理视角的失败分类,还要结合 config_dump、clusters、certs、访问日志、Trace 和业务事实确认。特别是 UT、DC、UF 这类网络失败不能证明写请求没有执行;订单、库存、支付仍要按幂等键查询事实。

二十二、生产Runbook ​

22.1 503 NR:No Route ​

  1. 确认503由哪个代理产生。
  2. 查看请求Host、SNI、Path和端口是否匹配Listener与VirtualHost。
  3. 查看代理实际RDS配置,不只看控制面声明。
  4. 检查路由资源是否已下发、是否NACK、版本是否陈旧。
  5. 检查命名空间导出、服务可见性和协议识别。

22.2 503 UH:No Healthy Upstream ​

  1. 查看目标Cluster是否存在。
  2. 查看EDS端点数量、健康、优先级和Locality。
  3. 对照Kubernetes EndpointSlice和Pod Ready。
  4. 检查异常实例检测是否剔除过多端点。
  5. 检查Subset或版本标签是否把候选筛成空集。

22.3 503 UF或连接失败 ​

  1. 区分DNS、连接拒绝、超时、Reset和TLS握手失败。
  2. 直接检查服务方Sidecar监听与业务容器端口。
  3. 检查NetworkPolicy、节点网络、MTU和Conntrack。
  4. 检查连接池、最大连接和Pending熔断阈值。
  5. 按Node、Zone和Endpoint拆分,定位局部网络故障。

22.4 mTLS握手失败 ​

  1. 查看双方实际证书链、SAN身份、信任根和剩余有效期。
  2. 检查系统时间和证书轮换。
  3. 检查STRICT/PERMISSIVE和客户端TLS模式是否匹配。
  4. 检查信任域、跨集群信任和根证书迁移窗口。
  5. 查看SDS同步和Secret NACK,不输出私钥到日志。

22.5 xDS NACK ​

  1. 定位代理、资源类型、nonce、version和错误详情。
  2. 确认是LDS、RDS、CDS、EDS还是SDS。
  3. 检查引用资源是否存在、字段是否被当前代理版本支持。
  4. 保留Last Known Good,不要强制清空代理配置。
  5. 回滚或修正后观察全体代理ACK分布。

22.6 配置已改但流量没变 ​

  1. 区分控制面对象、目标代理配置和真实流量三个事实层。
  2. 查看配置是否选中了正确工作负载和命名空间。
  3. 查看目标代理是否连接控制面、是否ACK最新版本。
  4. 查看Route是否被更高优先级规则覆盖。
  5. 区分旧连接与新连接,检查连接池和HTTP/2。
  6. 用按版本请求数证明真实分流,不只看配置页面。

22.7 Sidecar CPU或内存过高 ​

  1. 按Listener、Cluster、连接、请求和统计基数拆分。
  2. 检查大量短连接、TLS握手、重试风暴和高基数指标。
  3. 检查配置规模、Endpoint数量和无效服务可见范围。
  4. 查看访问日志量、采样、Tracing和Filter成本。
  5. 调整资源前先消除重试和连接异常,否则只会推迟崩溃。

二十三、常见误区 ​

误区为什么错
上了Mesh就不需要SDK设计业务幂等、状态机和领域错误仍在应用层
mTLS等于用户授权它主要证明工作负载身份,不证明用户能退款
ACK表示全网生效只表示某代理接受某响应,旧连接和其他代理可能未切换
控制面不在请求路径所以不重要长期故障会阻断端点、路由和证书更新
重试越多越可靠多层重试会乘法放大并攻击故障下游
权重10%必然精确10%小样本、连接复用和哈希都会波动
Outlier Detection等于全局摘除通常是各代理本地判断
流量镜像没有风险写请求镜像可能产生真实副作用
Sidecar和Ambient配置完全一样捕获方式、L7路径和故障域不同

二十四、面试回答主线 ​

先说Mesh将通用通信能力下沉到代理;再区分控制面计算配置、数据面转发真实请求;用Listener → Route → Cluster → Endpoint说明Envoy调用链;用LDS/RDS/CDS/EDS/SDS说明xDS;补充ACK/NACK与Last Known Good;再讲工作负载mTLS、重试乘法、连接级负载、灰度传播和Runbook;最后明确业务幂等、事务和授权仍由应用负责。

标准回答与追问见Service Mesh面试题。

更深的运行时调用链、配置收敛、连接与失败窗口见 Service Mesh 内部原理与生产治理。

二十五、关联知识点 ​

本章小结 ​

Service Mesh的核心不是Sidecar这个形态,而是“控制面持续计算配置,数据面代理按本地已接受快照治理真实流量”。要真正理解它,必须同时掌握Envoy对象、xDS收敛、mTLS身份、连接和请求边界、重试与Deadline、配置传播窗口以及业务正确性边界。只有能从控制面对象一直追到代理实际配置、连接、Endpoint和业务结果,才算具备生产排查能力。