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_FLAGSRESPONSE_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_dumpclusterscerts、访问日志、Trace 和业务事实确认。特别是 UTDCUF 这类网络失败不能证明写请求没有执行;订单、库存、支付仍要按幂等键查询事实。

二十二、生产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和业务结果,才算具备生产排查能力。