Day 11 / 共 20 天 · 第 3 周 xDS 与上游
xDS 动态配置总览
Envoy 最强大的能力:配置从远程"管理服务器"动态下发、热更新、不重启。这就是 Istio/Higress 控制面控制 Envoy 数据面的方式。今天讲清 xDS 是什么、五大发现服务、握手协议。
📍 你在整门课的位置 · 第 3 周「xDS 与上游」(W1 架构线程 → W2 过滤器/请求 → W3 动态配置与后端 → W4 扩展生态)
D11 xDS 总览→
D12 配置订阅→
D13 集群管理→
D14 负载均衡→
D15 健康检查/发现
L01
xDS 是什么
xDS = "x" Discovery Service,"x" 是占位符,代表一类"发现服务"的统称。Envoy 启动时不需要知道全部配置,而是运行时通过网络从一个管理服务器(Management Server / 控制面)动态拉取配置。
xDS = "配置的外卖服务"
传统程序改配置要改文件、重启。Envoy 不这样——它像点外卖:启动时几乎"空着肚子",然后连上一个"配置外卖平台"(管理服务器),说"给我监听器配置、集群配置…",平台就把配置"送"过来;配置变了,平台主动推送新的,Envoy 热更新、全程不重启。Istio 的 istiod、Higress 的控制面就是这个"外卖平台"。这让海量 Envoy 实例能被一个控制面统一、实时地管理——这是服务网格的根基。
🤔 痛点:改一条配置,要挨个重启几百台代理
传统代理(如早期 Nginx)改配置得改文件、再 reload/重启进程。你线上有 300 个代理实例,改一条路由规则要挨个操作——慢、易错、还可能抖动断流。有没有"改一次,全网秒级同步、且不重启"的办法?
💡 本质:xDS = 连锁总部"实时下发规章"
把每个 Envoy 想成一家连锁门店,控制面(Istio/Higress)是总部。门店只管营业(转发流量),总部通过一根"对讲机长连接"(xDS)把最新规章(监听/路由/集群/证书)实时播报给每家门店,门店立刻照做——不用关店重装修(不重启进程)。一处修改,全网门店秒级同步。这就是本周所有内容的世界观。
📝 举个例子:一次灰度发布
运维在控制面把
/api 的流量从 v1 切到 v2 → 控制面通过 RDS 下发一个新的 DiscoveryResponse(内含新路由表)→ 所有相关 Envoy 收到后调 onConfigUpdate 应用 → 再 curl /api 就打到 v2 了。全程 0 次重启、秒级生效。总部(控制面)通过 xDS 把各类"规章"实时推给成百上千个 Envoy 门店,全网秒级同步、无需重启。
L02
五大发现服务
| 缩写 | 全称 | 下发什么 |
|---|---|---|
| LDS | Listener Discovery | 监听器(端口 + 过滤器链) |
| CDS | Cluster Discovery | 集群(上游服务定义) |
| RDS | Route Discovery | 路由表(HTTP 路由规则) |
| EDS | Endpoint Discovery | 端点(集群下的具体 IP:Port) |
| SDS | Secret Discovery | 密钥/证书(TLS 材料) |
读法:每一类可动态下发的配置,都被抽象成一种 Discovery Service。proto 资源类型定义在
api/envoy/config/(如 Listener/Cluster/RouteConfiguration/ClusterLoadAssignment)。记住这五个缩写,xDS 世界就有了地图。L03
管理服务器模型
控制面 vs 数据面
数据面(data plane)= Envoy 本身,真正转发流量。控制面(control plane)= 管理服务器,决定"流量该怎么转"并下发配置。两者分离是现代网络基础设施的核心思想:成百上千个 Envoy(数据面)各自扛流量,一个控制面(istiod/Higress)统一给它们下发规则。你改一条路由规则,控制面通过 xDS 推给所有相关 Envoy,秒级生效、零重启。本课学 Envoy 是学"数据面怎么接收和应用配置";Day 后面的 Istio 子项目会讲"控制面怎么生成配置"。
L04
层级引用链
五大服务不是孤立的,它们串成一条解析链:
LDS(监听器)→ RDS(路由表)→ CDS(集群)→ EDS(端点)
# 一个请求进来:
# LDS 决定命中哪个 Listener
# RDS 决定路由到哪个 Cluster
# CDS 定义该 Cluster 的属性(LB 策略/健康检查/发现类型)
# EDS 提供该 Cluster 当前有哪些健康端点
读法:这条链是整个动态配置体系的主线(Day 15 会用它收尾串讲)。从"入口监听"一路解析到"后端具体端点"。理解这条链,就理解了 Envoy 配置的全貌。
L05
DiscoveryRequest / Response
xDS 的通信消息定义在 api/envoy/service/discovery/v3/discovery.proto:
message DiscoveryRequest { // discovery.proto:58
string version_info = 1; // 我当前应用的配置版本
core.v3.Node node = 2; // 我是谁(Envoy 实例标识)
repeated string resource_names = 3; // 我想要哪些资源
string type_url = 4; // 想要哪类资源(LDS/CDS/…)
string response_nonce = 5; // 对应哪次响应
}
message DiscoveryResponse { // discovery.proto:117
string version_info = 1;
repeated google.protobuf.Any resources = 2; // 下发的配置
string type_url = 4;
}
读法:Envoy 发 Request 说"我要 type_url 这类资源里的这些 resource_names";Server 回 Response 带
resources + version_info + nonce。type_url 区分是哪类 xDS。聚合发现服务 ADS 的 gRPC 接口在 ads.proto:29(StreamAggregatedResources 双向流)。L06
ACK / NACK 握手
xDS 是最终一致性协议,靠 ACK/NACK 确认:
1. Envoy 发 Request(type_url + resource_names)
2. Server 回 Response(resources + version_info + nonce)
3. Envoy 应用配置:
- 成功 → 回一个带相同 version_info + nonce 的 Request(ACK 确认)
- 失败 → 回带 error_detail 的 Request(NACK 拒绝,保留旧配置)
为什么要 ACK/NACK?
下发的新配置可能有错(比如引用了不存在的集群)。如果 Envoy 无脑应用坏配置,可能整个挂掉。ACK/NACK 让 Envoy 能"应用成功才确认、应用失败就拒绝并保留旧配置继续跑"。控制面看到 NACK 就知道"这份配置这个 Envoy 没接受",可以告警。nonce(一次性随机数)用来对上"这个确认是针对哪次下发的",避免新旧响应错乱。这套协议保证了动态配置既灵活又安全——坏配置不会搞垮数据面。
💬 小白 vs 老师:ACK/NACK 到底在防什么?
👶 小白:配置来了直接用不就行,为什么还要"确认"一下?
👨🏫 老师:因为下发的配置可能有错(比如路由指向一个不存在的集群)。要是无脑应用,整台 Envoy 可能崩掉、流量全断。
👶 小白:那 NACK 之后会怎样?
👨🏫 老师:Envoy 拒绝坏配置、继续用旧的正常配置跑着,同时告诉控制面"这份我没收下"。坏配置搞不垮数据面——这就是动态配置既灵活又安全的关键。
👨🏫 老师:因为下发的配置可能有错(比如路由指向一个不存在的集群)。要是无脑应用,整台 Envoy 可能崩掉、流量全断。
👶 小白:那 NACK 之后会怎样?
👨🏫 老师:Envoy 拒绝坏配置、继续用旧的正常配置跑着,同时告诉控制面"这份我没收下"。坏配置搞不垮数据面——这就是动态配置既灵活又安全的关键。
⚠️ 常见误解:以为 nonce 是"配置版本号"。其实 version_info 才是版本号;nonce 是一次性随机数,只用来对上"这个 ACK/NACK 是回应哪一次下发的",避免新旧响应错乱。
L07
源码分布
| 层 | 位置 |
|---|---|
| 接口层(纯虚) | envoy/config/:subscription.h、grpc_mux.h、subscription_factory.h |
| 通用逻辑 | source/common/config/:订阅工厂、type_url 映射(type_to_endpoint.cc:21) |
| 具体订阅实现 | source/extensions/config_subscription/:filesystem / grpc / rest 三种传输 |
读法:又是"接口 + 多实现":抽象订阅接口在
envoy/config/,三种传输方式(文件监听 / gRPC 流 / REST 轮询)作为扩展在 config_subscription/。生产主力是 gRPC(Day 12 详讲)。L08
今日小结 + 动手
🧠 今天你应该能回答
- xDS 是什么?解决"改配置要重启"的什么痛点?
- 五大发现服务 LDS/CDS/RDS/EDS/SDS 各下发什么?
- 控制面 vs 数据面的分工?
- LDS→RDS→CDS→EDS 层级引用链?
- ACK/NACK 握手保证了什么?nonce 干嘛?
✋ 动手
cd /Users/bitmart/work/codes/github/higress-group/envoy
sed -n '58,130p' api/envoy/service/discovery/v3/discovery.proto
sed -n '29,40p' api/envoy/service/discovery/v3/ads.proto
ls source/extensions/config_subscription/
明天预告 · Day 12:配置订阅机制——gRPC 订阅怎么实现?
Subscription/SubscriptionCallbacks 接口、GrpcMux 多路复用(ADS 复用一条流)、sendDiscoveryRequest/onDiscoveryResponse 的热更新闭环。