想象你是刚入职网约车公司的新手司机。公司没有发给你一本厚厚的纸质地图,因为这座城市每天都在变:老路封修、新楼交付、商圈营业时间调整。你靠的是车载终端——调度中心随时发来指令:去哪里接客、走哪条路送达、目的地换到了哪栋楼。你不需要背地图,只需要听懂指令、实时执行。 这里的「调度中心」是控制平面,「司机」是 Envoy,「车载终端的指令流」就是 xDS 协议。指令一共有四类:LDS 告诉你「在哪个路口等客」(监听器),RDS 告诉你「接到乘客走哪条路」(路由),CDS 告诉你「哪些目的地可选」(集群),EDS 告诉你「目的地的精确门牌号」(端点)。当城市变化时,调度中心实时推送新指令;司机回复「收到」或「指令有误」。这套机制让千万辆车在不重启、不迷路的前提下,始终把乘客准确送到目的地。

岗位关联

掌握 xDS 协议,就掌握了 Service Mesh 中控制平面与数据平面对话的通用语言,是理解服务网格、排查流量问题、设计云原生架构的基本功。

目录
  1. 可视化演示
  2. xDS 协议概述
  3. 控制与数据平面
  4. LDS 监听发现
  5. RDS 路由发现
  6. CDS 集群发现
  7. EDS 端点发现
  8. 动态更新一致性
  9. 工程实践与优化
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

演示Envoy通过xDS协议动态获取监听器、路由、集群与端点配置,依次经LDS、RDS、CDS、EDS四个阶段完成配置下发与流量治理。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Envoy xDS流程 LDS RDS CDS EDS 动态配置完成流量治理

xDS 协议概述

司机李明第一天出车很忐忑,怕记不住全城路线。调度中心告诉他:「你不需要背地图,只要保持车载终端在线,所有指令都会通过同一个频道下发。」在城市里,只要接入这个频道,就能收到接单、路线、目的地等一切信息。这个「统一频道」就是 xDS 协议。

在微服务架构中,服务数量动辄上百,实例随时扩缩容。如果每个 Envoy 都依赖静态配置文件,改一次配置就要重启一堆代理,线上流量瞬间抖动。xDS 把「配置下发」抽象成一套标准协议,让动态配置成为可能。无论是新增监听端口、调整路由比例,还是摘除故障实例,都通过同一套机制实时生效。

xDS 全称 x Discovery Service,即「x 发现服务」,其中 x 是通配符,代表一系列发现服务的集合。最常见的是 LDS(Listener Discovery Service,监听器发现)、RDS(Route Discovery Service,路由发现)、CDS(Cluster Discovery Service,集群发现)、EDS(Endpoint Discovery Service,端点发现)。它们相互独立又协同工作,覆盖流量从进入到转发的完整链路。

就像司机只需要认准车载终端这一个入口,无论来的是接单规则还是路线调整——Envoy 也只需通过 xDS 这一个频道,就能拿到运行所需的全部「行车指南」。这就是 xDS 协议的核心价值:统一、动态、可扩展。

xDS={LDS,RDS,CDS,EDS,⋯ }\displaystyle \text{xDS} = \{ \text{LDS}, \text{RDS}, \text{CDS}, \text{EDS}, \cdots \}
该公式表示:xDS 不是单一协议,而是一族配置发现协议的集合,未来还会持续扩展新成员。
  1. 集合符号(大括号)xDS 是一族协议的统称,大括号表示「包含以下成员」,成员之间是并列关系。
    {⋯ }\displaystyle \{ \cdots \}
  2. x 通配符字母 x 像方程中的未知数,可被替换为 L、R、C、E 等具体字母,代表各类发现服务。
    x∈{L,R,C,E,⋯ }\displaystyle x \in \{ L, R, C, E, \cdots \}
  3. 四类核心资源LDS 负责监听器发现、RDS 负责路由发现、CDS 负责集群发现、EDS 负责端点发现。
    {LDS,RDS,CDS,EDS}\displaystyle \{ \text{LDS}, \text{RDS}, \text{CDS}, \text{EDS} \}

控制与数据平面

调度中心高高在上,能看见全城实时路况,但它自己不开车;司机分布在城市每个角落,一辆车只为车上的乘客服务,行动却必须听从调度。这种「大脑决策、双手执行」的分工,对应到 Service Mesh 里就是控制平面与数据平面的职责分离。

在 Service Mesh 架构中,Istio 这类控制平面负责收集全局状态、制定流量策略;Envoy 这类数据平面代理专注于流量转发。两者通过 gRPC 长连接保持通信:Envoy 启动时向控制平面发起 xDS 订阅请求,之后持续监听配置更新。控制平面不再需要 SSH 到每台机器改配置,而是通过统一的下发通道完成。

控制平面维护着目标状态(Target State),它对比每个 Envoy 当前已生效的配置状态,计算出差异,并把差异封装成 xDS 响应推送下去。Envoy 收到后应用变更、回复确认,状态同步完成。这个「计算差异、增量下发」的模型,让大规模集群的配置管理变得可控、可追踪。

司机永远不会自己修改车载地图——他只负责执行调度中心发来的增量指令。这正是 xDS 高效的原因:每次只发「变化的部分」,而不是重传整个城市地图。

Snew=Apply(Sold,Δ)\displaystyle S_{\text{new}} = \text{Apply}( S_{\text{old}}, \Delta )
该公式描述配置更新过程:新的配置状态等于「旧状态 + 增量变更」经过应用函数作用后的结果。
  1. S_old(旧配置状态)Envoy 当前正在生效的配置快照,例如监听端口、路由表、端点列表。
    Sold\displaystyle S_{\text{old}}
  2. Δ(增量变更)控制平面计算出的目标状态与当前状态的差异,是推送的最小单元。
    Δ=Starget−Sold\displaystyle \Delta = S_{\text{target}} - S_{\text{old}}
  3. Apply(应用函数)Envoy 把增量合并到旧配置的确定性操作,生成新的完整状态。
    Snew=Apply(Sold,Δ)\displaystyle S_{\text{new}} = \text{Apply}( S_{\text{old}}, \Delta )

LDS 监听发现

调度中心告诉李明:「今晚你在火车站东广场 3 号车道上客。」对 Envoy 来说,这句话就是一条 LDS 指令:监听器(Listener)决定代理在哪个 IP 和端口「蹲守」流量。没有它,后续所有路由和转发都无从谈起。

LDS 是 xDS 资源中最先就位的一类。所有进入 Envoy 的请求,第一站必须是监听器。如果把请求比作乘客,监听器就是乘客上车「必须经过的车门」。没有门,乘客进不了车,后面的服务再完善也没有用。

一个监听器配置包含四要素:address(监听地址)、port(端口)、protocol(协议)和 filters(过滤器链)。Envoy 收到 LDS 更新后可以动态新增、修改、删除监听器,全程无需重启进程。例如把服务端口从 8080 热切换到 9090,已建立的连接不会中断,这在传统 Nginx 静态配置时代是难以想象的。

司机换接客点只需要调度中心一句话,车不用熄火——Envoy 的端口热更新同理。LDS 让代理在流量入口层面具备了「动态应变」的能力。

L=(address,port,protocol,filters)\displaystyle L = ( \text{address}, \text{port}, \text{protocol}, \text{filters} )
监听器是一个四元组,完整描述「从哪里收流量、用什么协议解析、经过哪些过滤器」。
  1. address(监听地址)Envoy 绑定的 IP 地址,通常写 0.0.0.0 表示接收所有网卡的流量。
    address=0.0.0.0\displaystyle \text{address} = \text{0.0.0.0}
  2. port(监听端口)接收流量的 TCP 端口号,例如 8080,是请求进入的「门牌号」。
    port=8080\displaystyle \text{port} = 8080
  3. protocol(协议)决定 Envoy 如何解析原始字节流,常见有 HTTP/2、TCP、gRPC。
    protocol∈{HTTP/2,TCP,gRPC}\displaystyle \text{protocol} \in \{ \text{HTTP/2}, \text{TCP}, \text{gRPC} \}
  4. filters(过滤器链)流量进入后依次经过的过滤器列表,如 CORS、限流、故障注入。
    filters=[f1,f2,⋯ ,fk]\displaystyle \text{filters} = [ f_1, f_2, \cdots, f_k ]

RDS 路由发现

乘客上车说「去科技园」。司机不可能把科技园每个门都送一遍,他需要调度中心的路线指令:到底是哪个门、走哪条路。RDS(Route Discovery Service)就是这本「路线指引」:请求进入监听器后,该往哪个服务集群送。

RDS 是 HTTP 流量治理最核心的环节。凡是涉及 URL 到服务的映射、版本分流、灰度策略,都在这层完成。没有 RDS,监听器只是一个「只收不发」的哑端口,接进来的流量无法被转送到任何地方。

路由表由虚拟主机(Virtual Host)组织,每个虚拟主机按域名区分,内部包含多条路由规则。Envoy 采用最长前缀匹配:当请求路径为 /api/v1/users,而路由表中同时有 /api 和 /api/v1 两条规则时,会选择更具体、前缀更长的 /api/v1。金丝雀发布也依赖 RDS:给 v1 集群配权重 90、v2 集群配权重 10,流量就按比例分流。

路线不是一成不变的,调度中心会动态优化——RDS 让流量可以在不重启代理的前提下,随时调整目的地与分流比例,这就是金丝雀发布等技术得以落地的根基。

match(path)=arg⁡max⁡prefix∈P{len(prefix)  |  prefix⪯path}\displaystyle \text{match}(\text{path}) = \arg\max_{\text{prefix} \in P} \left\{ \text{len}(\text{prefix}) \;\middle|\; \text{prefix} \preceq \text{path} \right\}
该公式描述路由匹配:请求路径会命中「所有前缀匹配的规则中长度最长的那一条」。
  1. path(请求路径)客户端请求 URL 中的路径部分,是路由匹配的输入。
    path="/api/v1/users"\displaystyle \text{path} = \text{"/api/v1/users"}
  2. P(前缀候选集合)路由表中预定义的所有匹配前缀,例如根路径「/」和业务前缀「/api」。
    P={"/","/api","/api/v1"}\displaystyle P = \{ \text{"/"}, \text{"/api"}, \text{"/api/v1"} \}
  3. 前缀关系(≼)表示 prefix 是 path 的前缀,即路径以该前缀开头。
    prefix⪯path\displaystyle \text{prefix} \preceq \text{path}
  4. argmax 最长匹配在满足前缀关系的候选中,选择长度最长的那一条,确保更具体的规则优先。
    arg⁡max⁡prefix∈Plen(prefix)\displaystyle \arg\max_{\text{prefix} \in P} \text{len}(\text{prefix})

CDS 集群发现

司机心里需要一张「商圈名录」:哪些商圈在营业、评分如何、距离多远。CDS(Cluster Discovery Service)就是 Envoy 的商圈名录,列出了所有可访问的上游服务集群。

集群(Cluster)是一组逻辑上等价的服务实例的抽象。例如「user-service 集群」可能包含 3 个副本,但对外只暴露一个逻辑名称。CDS 负责下发集群级配置:连接超时、负载均衡算法(轮询、最小请求、一致性哈希)、健康检查方式等。这些配置决定了 Envoy 如何与上游服务建立连接池。

当 CDS 推送新的集群定义时,Envoy 会动态重建连接池。但重建过程采用「优雅排空」策略:旧连接继续处理完在途请求,新请求走新连接池,用户几乎无感知。这比传统「改配置 → reload → 断连」的模式平滑得多。

商圈名录如果只写一个店名,司机就无法择优选择。CDS 提供多个可选集群,配合权重配置,流量就能像司机挑商圈一样灵活调度,忙的商圈多派单、闲的商圈少派单。

P(选择集群 i)=wi∑j=1nwj\displaystyle P(\text{选择集群 } i) = \frac{w_i}{\sum_{j=1}^{n} w_j}
该公式表示加权负载均衡:集群 i 被选中的概率等于它的权重占所有集群权重总和的比例。
  1. w_i(集群权重)人为配置的权重值,代表该集群应承担流量的相对比例。
    wi\displaystyle w_i
  2. 分母(总权重)所有候选集群权重之和,用于把权重归一化为概率。
    ∑j=1nwj\displaystyle \sum_{j=1}^{n} w_j
  3. 概率(分配比例)单个集群分得的流量比例,权重越大,分到的流量越多。
    wi∑j=1nwj\displaystyle \frac{w_i}{\sum_{j=1}^{n} w_j}

EDS 端点发现

商圈确定后,还得知道店在几栋几层。EDS(Endpoint Discovery Service)就是那串精确的门牌号和楼层:集群里到底有哪些具体实例在运行、地址是什么。

集群只是逻辑分组,真正处理请求的是端点(Endpoint)。EDS 把「集群」映射到「具体的 IP:Port 列表」,并携带权重与健康状态。这一步是服务发现的最后一公里:从逻辑服务名到真实物理地址。

云原生环境里,Pod 重建后 IP 必然变化。控制平面实时监听 Kubernetes Service 的 Endpoints,一旦发现变化就通过 EDS 推送给 Envoy。任何不健康的端点都会被标记并从负载池中移除,流量自动绕开故障实例。这意味着连冷启动时的新 Pod 都能在几秒内被纳入流量调度。

司机按导航到店门口才发现装修闭店,会很恼火。有了 EDS 的实时健康状态,导航会在出发前就把这家店标灰,自动绕开——这就是 EDS 让流量自动避开故障实例的价值。

e=(ip,port,weight,healthy)\displaystyle e = ( \text{ip}, \text{port}, \text{weight}, \text{healthy} )
端点是一个四元组:物理地址加端口,附带权重分值,以及一个表示是否健康的布尔标记。
  1. ip(实例地址)Pod 或容器的内网 IP,是请求最终到达的物理位置。
    ip="10.0.0.1"\displaystyle \text{ip} = \text{"10.0.0.1"}
  2. port(服务端口)实例上监听业务流量的端口号。
    port=8080\displaystyle \text{port} = 8080
  3. weight(端点权重)用于端点间的加权负载均衡,权重高的端点分到更多请求。
    weight=100\displaystyle \text{weight} = 100
  4. healthy(健康状态)布尔值,标记该端点是否可用,false 时 Envoy 不再向其转发新请求。
    healthy∈{true,false}\displaystyle \text{healthy} \in \{ \text{true}, \text{false} \}

动态更新一致性

调度中心发布新路线后,不能假设所有司机都收到了。司机收到指令会说「收到」;如果指令自相矛盾,他会回复「指令有误,请求重发」。这套回执机制,在 xDS 里就是 ACK/NACK。

xDS 客户端每次收到配置都必须做出回应,否则控制平面无法判断集群内配置是否一致。ACK 表示接受并应用成功;NACK 表示拒绝,并附带错误原因。这个设计保证了「下发」不是单向广播,而是有确认的可靠通信。

xDS 有两种推送模式:SotW(State of the World)全量推送,即每次把当前所有资源完整发送一遍;增量 xDS(incremental)只推送差异部分,更节省带宽,是大规模集群的推荐做法。Envoy 用 version_info 字段标识当前配置版本,控制平面据此跟踪每个 Envoy 已同步到哪个版本。当 Envoy NACK 时,它会保留旧配置继续工作,而不是用错误配置自毁。

调度系统靠版本文号区分新旧指令,司机用回执保证指令不丢失、不混淆。xDS 的 ACK/NACK 与版本机制,让大规模服务网格的配置状态始终透明可控。

versionclient=versionserver  ⟹  state is consistent\displaystyle \text{version}_{\text{client}} = \text{version}_{\text{server}} \;\Longrightarrow\; \text{state is consistent}
该公式表示:当客户端与服务端版本号一致时,说明两者持有的配置状态相同,系统处于一致状态。
  1. version_client(客户端版本)Envoy 当前已成功应用的配置版本号。
    versionclient\displaystyle \text{version}_{\text{client}}
  2. version_server(服务端版本)控制平面最新生成的配置版本号。
    versionserver\displaystyle \text{version}_{\text{server}}
  3. 蕴涵关系(⇒)逻辑符号,表示「如果前半句成立,则后半句必然成立」。
    A  ⟹  B\displaystyle A \;\Longrightarrow\; B

工程实践与优化

晚高峰时调度中心也会手忙脚乱:推送延迟、指令出错、司机收不到更新。生产环境中的 xDS 同样会遇到问题,关键在于掌握排查与优化的方法。

排障时,第一步是检查 Envoy 日志中的 ACK/NACK 状态。NACK 出现时,日志会带上错误信息,例如「unknown field」或「invalid route」,据此快速定位是哪类资源出了问题。还可以用 config_dump 命令导出 Envoy 当前生效的完整配置,对比控制平面预期,找出漂移点。

优化方面有三大方向:第一,推送模式从全量改为增量,控制平面只下发变化资源;第二,降低无谓推送频率,例如在批量扩缩容后合并变更、延迟推送;第三,在控制平面侧做灰度推送——先向一小部分 Envoy 推送新配置,观察错误率和延迟,确认稳定后再全量推送。全量推送只在兜底场景使用。

调度中心每次升级路况规则,都先在小范围试运行,确认无误再全城广播。xDS 的上线实践遵循同样的灰度哲学:小步快跑、逐步放量、随时回滚。

T生效=T检测+T推送+T应用\displaystyle T_{\text{生效}} = T_{\text{检测}} + T_{\text{推送}} + T_{\text{应用}}
该公式表示配置生效总耗时由三段组成:控制平面检测变更的时间、推送传输的时间、Envoy 应用配置的时间,优化任一段都能加快生效。
  1. T_检测(检测延迟)控制平面从发现变更到生成新配置的时间,例如 watch 到 Pod 变化。
    T检测\displaystyle T_{\text{检测}}
  2. T_推送(推送延迟)配置从控制平面传输到 Envoy 的网络耗时。
    T推送\displaystyle T_{\text{推送}}
  3. T_应用(应用延迟)Envoy 解析、校验并切换配置的时间。
    T应用\displaystyle T_{\text{应用}}
  4. 求和(总延迟)三段串行叠加,构成端到端配置生效耗时。
    T生效=T检测+T推送+T应用\displaystyle T_{\text{生效}} = T_{\text{检测}} + T_{\text{推送}} + T_{\text{应用}}

AI 应用场景

金丝雀发布:让新版本先接受少量真实流量考验

阶段:云原生流量治理与发布

解决的问题:传统发布把所有流量一次性切换到新版本,一旦新版本有隐藏 Bug,所有用户同时遭殃。AI 辅助的智能发布系统需要精细控制流量比例,让新版本先接受少量真实流量考验,收集反馈后再决定是否放量。

具体案例:电商大促前,平台要把购物车服务 v2 灰度上线。运维通过 Istio 的 VirtualService(RDS)配置 90% 流量到 v1、10% 到 v2,同时用 EDS 为新版本扩容独立端点。观察 10 分钟黄金指标(错误率、延迟、CPU)后,逐步把比例调整到 50%、100%。全程 Envoy 动态加载配置,无需重启任何代理。

弹性伸缩下的自动容灾:故障实例秒级摘除

阶段:可观测性与系统韧性

解决的问题:突发流量把某个服务实例打崩,传统方式要等监控系统报警、人工确认后再摘除,期间大量请求持续打到故障实例上。借助 xDS 的 EDS 动态更新,可以让故障实例从负载池中自动消失。

具体案例:Kubernetes 集群中,一个 Pod 因内存溢出被重启。控制平面 watch 到该 Pod 的状态变化,立即通过 EDS 把对应端点标记为不健康并推送出去。Envoy 在 1 秒内停止向该实例转发新请求,转而全部分发给健康实例,用户几乎无感知。整个流程完全自动化,无需人工介入。

Python 演示

python86 行
import time  class ControlPlane:    """控制平面: 维护全局配置, 通过 xDS 下发资源"""     def __init__(self):        self.listeners = {"8080": "http_listener"}        self.routes = {"/api": "user-service", "/order": "order-service"}        self.clusters = ["user-service", "order-service"]        self.endpoints = {            "user-service": ["10.0.0.1:8080", "10.0.0.2:8080"],            "order-service": ["10.0.0.3:8080"],        }        self.version = "v1"     def get_lds(self):        return self.listeners     def get_rds(self, listener):        return self.routes     def get_cds(self):        return self.clusters     def get_eds(self, cluster):        return self.endpoints[cluster]     def add_endpoint(self, cluster, endpoint):        self.endpoints[cluster].append(endpoint)        major = int(self.version[1:]) + 1        self.version = "v" + str(major)        return self.version  class Envoy:    """数据平面代理: 拉取 xDS 配置并转发请求"""     def __init__(self, cp):        self.cp = cp        self.listeners = {}        self.routes = {}        self.clusters = {}        self.endpoints = {}        self.version = ""     def sync(self):        """模拟 xDS 全量同步: 一次拉取四类配置"""        self.listeners = self.cp.get_lds()        self.routes = {}        for lis in self.listeners:            self.routes[lis] = self.cp.get_rds(lis)        self.clusters = self.cp.get_cds()        self.endpoints = {}        for cluster in self.clusters:            self.endpoints[cluster] = self.cp.get_eds(cluster)        self.version = self.cp.version        return self.version     def forward(self, path):        """根据路由规则把请求转发到目标实例"""        service = self.routes.get("8080", {}).get(path)        if service is None:            return "404 no route"        endpoints = self.endpoints.get(service, [])        if not endpoints:            return "503 no endpoint"        target = endpoints[0]        return "200 -> " + service + "@" + target  def main():    cp = ControlPlane()    envoy = Envoy(cp)    print("首次 xDS 同步, 版本:", envoy.sync())    print("请求 /api ->", envoy.forward("/api"))    print("请求 /pay ->", envoy.forward("/pay"))     new_version = cp.add_endpoint("user-service", "10.0.0.4:8080")    envoy.sync()    print("新实例上线, 版本更新为:", new_version)    print("同步后 user-service 端点:", envoy.endpoints["user-service"])  if __name__ == "__main__":    main()
目的:演示 Envoy 通过 xDS 从控制平面获取 LDS、RDS、CDS、EDS 四类配置,并在端点变化后重新同步、继续转发请求的完整流程。
  1. class ControlPlane:定义控制平面,持有监听器、路由、集群、端点四类配置,相当于交通调度中心。
  2. self.routes = {"/api": "user-service", ...}RDS 路由表,把请求路径映射到目标集群。
  3. def get_eds(self, cluster):EDS 查询接口,返回某个集群下的具体端点列表。
  4. def add_endpoint(self, ...):模拟新实例上线,端点变化后版本号递增。
  5. def sync(self):模拟 Envoy 的一次 xDS 全量同步,拉取全部配置并更新本地状态。
  6. def forward(self, path):模拟流量转发,根据路由找到集群,再从端点列表中选择目标。
  7. if __name__ == "__main__":程序入口,运行完整演示流程。

常见误区

误区以为 xDS 是 Istio 内部特有的协议,只能配合 Istio 使用,离开 Istio 就无从谈起。

正解xDS 是开源的通用配置发现协议,由 Envoy 社区定义,Istio、AWS App Mesh、Consul 等各种控制平面都可以实现并复用。就像交通调度中心的指令格式是全行业通用的,而不是某一家出租车公司的暗号。

为何常见:大多数教程都用 Istio 来演示 xDS,初学者很容易把「最常见的实现」当成「唯一的协议」。

误区以为每次配置变化,控制平面都要把所有配置重新推一遍,像重印整本地图手册一样。

正解xDS 既支持 SotW 全量推送,也支持增量推送。增量模式只下发变化的部分,大幅节省带宽、加快生效速度,生产环境通常优先使用增量模式。

为何常见:早期文档和教材以 SotW 为主,导致「全量」先入为主。

误区以为请求路径必须和路由规则完全一致才生效,例如配置了 /api 就只匹配 /api,/api/v1 会 404。

正解Envoy 采用的是最长前缀匹配。配置 /api 后,/api/v1、/api/v1/users 等以 /api 开头的路径都会命中它;如果同时配置了更长的 /api/v1,则精确命中后者。

为何常见:日常开发中哈希表、等于判断等精确匹配思维根深蒂固,忽略了「前缀」这一层语义。

误区以为端点列表是配置好后就不动的静态数据,服务扩容缩容时需要手动改配置。

正解云原生环境下 Pod 重建、扩缩容极其频繁,EDS 会实时追踪实例变化并推送给 Envoy。新实例上线几秒内即可开始接收流量,故障实例也会被自动摘除。

为何常见:习惯了传统「配置好就不动」的静态运维方式,对动态发现机制缺乏直觉。

误区以为监听器(LDS)负责把流量分发给具体服务实例,把它当成负载均衡器。

正解LDS 只决定「在哪里接收流量」以及「用什么协议解析」,真正决定流量去哪的是 RDS(路由到集群)和 EDS(集群到端点)。LDS 就像「车门」,RDS 是「路线」,EDS 是「门牌号」,它们各司其职。

为何常见:LDS 是 xDS 中第一个出现的资源,名字又带「发现」,容易被误解为全能调度入口。

面试题

Q1. xDS 协议中的「x」含义是?

单选题 · easy

  • A.表示某种加密算法代号
  • B.表示发现服务的通配符← 正确答案
  • C.表示 Envoy 的版本代号
  • D.表示控制平面名称后缀

答案:B。x 是通配符,代表 LDS、RDS、CDS、EDS 等所有发现服务(Discovery Service)的统称。正如「x 发现服务」可以代入任意字母,它不是固定协议名,而是协议族名。加密、版本、控制平面这些解释都偏离了「通配」的本意。

Q2. 在 Service Mesh 架构中,Envoy 属于哪个角色?

单选题 · easy

  • A.控制平面组件
  • B.数据平面代理← 正确答案
  • C.配置管理中心
  • D.服务注册中心

答案:B。Envoy 是数据平面代理,负责实际的流量转发与治理;控制平面(如 Istio)负责决策与配置下发。就像调度中心是大脑、司机是执行者,Envoy 是那个「司机」,不是发号施令的大脑。

Q3. 下列哪个 xDS 资源负责告诉 Envoy「在哪个端口接收流量」?

单选题 · easy

  • A.LDS 监听器发现← 正确答案
  • B.RDS 路由发现
  • C.CDS 集群发现
  • D.EDS 端点发现

答案:A。LDS(Listener Discovery Service)定义监听器的地址与端口,是流量的入口。RDS 决定流量往哪个集群走,CDS 提供集群列表,EDS 提供具体实例地址,它们负责入口之后的事,只有 LDS 管「门开在哪」。

Q4. Envoy 在做路由匹配时使用的规则是?

单选题 · mid

  • A.完全精确匹配规则
  • B.哈希一致性匹配规则
  • C.最长前缀匹配规则← 正确答案
  • D.随机概率匹配规则

答案:C。Envoy 使用最长前缀匹配:请求 /api/v1/users 同时命中 /api 与 /api/v1 时,会选更长的 /api/v1。这确保更具体的路由规则优先,同时也允许短前缀作为兜底规则。

Q5. RDS 路由规则最终把请求转发到的目标是?

单选题 · mid

  • A.具体 Pod 的 IP 地址
  • B.上游集群名称← 正确答案
  • C.EDS 端点列表
  • D.DNS 域名记录

答案:B。RDS 把请求路由到集群(Cluster),而不是直接到 IP。集群是逻辑抽象,具体实例由 EDS 进一步解析。就像司机先决定「去科技园」(集群),再导航到具体门牌(端点)。

Q6. EDS 端点信息中「healthy」字段的作用是?

单选题 · mid

  • A.表示端点是否在线可用← 正确答案
  • B.表示端点流量的权重值
  • C.表示端点的协议版本
  • D.表示端点所在的地域

答案:A。healthy 是布尔标记,表示该端点是否健康可用。为 false 的端点会被 Envoy 从负载池中剔除,不再转发新请求。它不负责权重、版本或地域信息。

Q7. 下列哪些属于 xDS 协议族的核心资源?

多选题 · mid

  • A.LDS 监听器发现← 正确答案
  • B.RDS 路由发现← 正确答案
  • C.CDS 集群发现← 正确答案
  • D.EDS 端点发现← 正确答案

答案:ABCD。xDS 协议族包含 LDS(监听器发现)、RDS(路由发现)、CDS(集群发现)、EDS(端点发现)四类核心资源,它们覆盖了「在哪收流量 → 往哪送 → 有哪些可选 → 具体地址」的完整链路。

Q8. 金丝雀发布中「90% 流量到 v1、10% 到 v2」的比例控制主要由哪个环节实现?

单选题 · hard

  • A.LDS 监听器数量
  • B.RDS/CDS 权重路由← 正确答案
  • C.EDS 健康检查频率
  • D.业务应用自身逻辑代码

答案:B。流量比例的权重配置位于 RDS 的加权集群(Weighted Cluster)或 CDS 集群权重中。Envoy 依据权重把请求按比例分发到 v1/v2 集群。LDS 只管入口,EDS 只管具体端点,都不参与比例决策。

Q9. 关于增量 xDS 推送,下列说法正确的是?

多选题 · hard

  • A.只需推送变化的资源← 正确答案
  • B.相比全量推送更节省带宽← 正确答案
  • C.和全量推送效果完全等价
  • D.无需任何版本号校验

答案:AB。增量推送只发送差异部分,带宽占用更小、生效更快。但它不是完全独立的协议——需要一个初始全量快照作为基线,且同样依赖版本号与 ACK/NACK 保证一致性。D 说「无需版本号」是错的,C 说「完全等价」也过于绝对。

Q10. Envoy 对 xDS 配置回复 NACK 之后,会发生什么?

多选题 · hard

  • A.保留旧配置继续工作← 正确答案
  • B.向控制平面反馈错误原因← 正确答案
  • C.立即重启进程重新加载
  • D.不影响在线流量转发← 正确答案

答案:ABD。NACK 表示新配置校验失败,Envoy 会保留旧配置继续服务,同时把错误信息返回控制平面供排查,整个过程中在线流量不受影响。它不会重启进程,重启属于极端兜底手段,正常流程中不会发生。