首页
/ etcd 3.5 版本变更全景解析:从 v3.5.0 破坏性变更到 3.5.x 补丁系列的安全与稳定性演进

etcd 3.5 版本变更全景解析:从 v3.5.0 破坏性变更到 3.5.x 补丁系列的安全与稳定性演进

2026-09-05 20:52:53作者:裴锟轩Denise

本文以仓库中的 CHANGELOG/CHANGELOG-3.5.md 为核心素材,系统梳理 etcd 3.5 分支从 v3.5.0 正式版到 v3.5.34 的完整变更脉络:v3.5.0 的破坏性变更(Go 模块迁移、日志体系切换、V2 API 废弃、存储格式变化)、各补丁版本新增的关键配置项与命令(如 --listen-client-http-urls--max-concurrent-streamsetcdutl snapshot restore 新标志、etcdutl check v2store 等),以及贯穿整个 3.5 系列的安全加固与稳定性修复。读完本文,你可以据此完成从 3.4 到 3.5 的升级评估,并在生产环境中正确选择、验证 3.5.x 的具体补丁版本。

一、变更日志的组织方式与版本时间线

CHANGELOG/CHANGELOG-3.5.md 按版本倒序排列,每条记录标注发布日期、所属组件(etcd server / clientv3 / etcdctl / etcdutl / grpc-proxy / Dependencies)以及对应 PR。3.5 系列自 2021 年 6 月 v3.5.0 GA 起,到本文档记录的 v3.5.34(TBC),覆盖了约五年、30+ 个补丁版本,是 etcd 生命周期最长的稳定分支之一。更早的版本记录见 CHANGELOG/CHANGELOG-3.4.md

3.5 系列各版本的关键节点(日期均出自变更日志原文):

版本 日期 标志性变更
v3.5.0 2021-06 GA:Go modules 迁移、zap 日志默认化、V2 API 废弃、arm64 官方支持
v3.5.8 2023-04-13 --tls-min-version/--tls-max-version--listen-client-http-urls 独立 HTTP 监听
v3.5.10 2023-10-27 snapshot restore 支持 --bump-revision/--mark-compacted
v3.5.11 2023-12-07 livez/readyz HTTP 健康端点
v3.5.16 2024-09-10 --experimental-compaction-sleep-interval 新增
v3.5.18 2025-01-24 etcdutl check v2store 离线检查命令
v3.5.28 2026-03-20 两个 RBAC 绕过型 CVE 的修复
v3.5.33 2026-07-23 watch 权限泄漏安全修复、client http.Server 设置 ReadHeaderTimeout

排查升级问题时,建议先用 etcd --version/version 端点确认当前小版本,再对照上表定位需要覆盖的修复。

二、v3.5.0 破坏性变更:升级前必读

v3.5.0 是 3.x 系列中破坏性变更最集中的一次,变更日志用独立的 "Breaking Changes" 小节列出。以下要点在从 3.4 升级时必须逐一核对。

Go 包路径迁移到模块惯例

go.etcd.io/etcd 下的 Go 包迁移到带 /v3 后缀的路径:go.etcd.io/etcd/{api,pkg,raft,client,etcdctl,server,raft,tests}/v3,以符合 Go modules 惯例。其中:

  • go.etcd.io/clientv3/snapshot 的 SnapshotManager 类移入 go.etcd.io/clientv3/etcdctl,下载远端快照的 snapshot.Save 方法保留在 go.etcd.io/clientv3/snapshot
  • go.etcd.io/client 包迁移到 go.etcd.io/client/v2

在当前仓库中可以直观看到这一布局:api、client/v3、server、pkg 均为独立 module,见 api/go.modclient/v3/go.modserver/go.modpkg/go.mod,工作区由 go.work 统一管理。

客户端行为变更

  • MemberList API 改为线性化读取:以前直接返回服务端本地(可能过期)数据,现在带线性化保证;如果服务器与 quorum 失联,调用会失败(PR 11639)。
  • ClientV3 支持 gRPC resolver API,端点管理改用 endpoints.Manager,原先的 GRPCResolver 已下线;端点自我标识格式变为 etcd-endpoints://{id}/{authority}(例如 etcd-endpoints://0xc0009d8540/localhost:2079)。
  • 客户端错误中 context cancelled / context deadline exceeded 现在映射为 codes.Canceledcodes.DeadlineExceeded,而不是 codes.Unknown——依赖旧行为做错误判断的应用代码需要调整。
  • ETCD_CLIENT_DEBUG 环境变量现在支持日志级别(debug, info, warn, error, dpanic, panic, fatal),仅在显式设置时覆盖应用全局的 gRPC 日志配置。
  • 内嵌使用方(embed):Etcd.Close() 必须恰好调用一次;embed.Config 不再覆盖全局 gRPC 日志器,如需旧行为须显式调用 SetupGlobalLoggers()

废弃的命令行标志与默认值变化

旧标志/行为 v3.5 处理方式
--debug 废弃,改用 --log-level=debug
--log-output 废弃,改用 --log-outputs
--logger=capnslog 废弃;--logger=zap --log-outputs=stderr 成为默认
--log-outputs=default 不再支持;journal 输出须显式写 --log-outputs=systemd/journal
/config/local/log 端点 废弃,无法再运行时调整日志级别
--experimental-backend-bbolt-freelist-type 废弃,稳定版 --backend-bbolt-freelist-type 取代,默认 hashmap
--enable-v2 / --experimental-enable-v2v3 废弃;etcd 3.5 是最后一个支持 V2 API 的版本
gRPC gateway /v3beta 端点 仅支持 /v3curl -L http://localhost:2379/v3beta/kv/put ... 不再可用,改用 /v3/kv/put

日志方面的变更值得单独说明:以前 etcd 父进程 PID 为 1(systemd 运行)时默认写 journal,写失败再回退 stderr;由于回退路径低效,v3.5 改为默认 --logger=zap --log-outputs=stderr,需要 journal 时显式配置 --log-outputs=systemd/journal

Prometheus 指标同步更新:etcd_debugging_mvcc_db_total_size_in_bytesetcd_debugging_mvcc_put_totaletcd_debugging_mvcc_delete_totaletcd_debugging_mvcc_txn_totaletcd_debugging_mvcc_range_total 均被废弃,分别改用 etcd_mvcc_* 对应指标;新增 etcd_debugging_mvcc_current_revisionetcd_debugging_mvcc_compact_revisionetcd_wal_write_bytes_totalos_fd_used/os_fd_limitetcd_disk_defrag_inflight 等。注意任何 etcd_debugging_* 指标都是实验性的,可能变化。

存储格式变化(影响快照与降级)

  • WAL 日志快照持久化 raftpb.ConfState
  • backend 在 meta bucket 的 confState key 持久化 raftpb.ConfState
  • backend 在 meta bucket 持久化 applied term;
  • backend 在 cluster bucket 持久化 downgrade 信息。

这意味着 3.5 的快照无法直接用于 3.4 节点,而 v3.5 同时提供了 downgrade API(cluster bucket 中的 downgrade 标记即为其存储基础),支持 3.5 集群回退到 3.4——仓库中 server/etcdserver/snapshot_merge.go 即处理这类快照合并逻辑的实现所在。

三、v3.5.0 引入的新功能与新标志

分布式追踪(OpenTelemetry)

v3.5.0 首次引入实验性分布式追踪,四个配套标志(后续 v3.5.11 修复了采样率配置):

  • --experimental-enable-distributed-tracing:启用追踪的布尔开关;
  • --experimental-distributed-tracing-address:OpenTelemetry collector 地址;
  • --experimental-distributed-tracing-service-name:服务名(默认 "etcd");
  • --experimental-distributed-tracing-instance-id:每实例必须唯一的 ID。

embed 侧对应 embed.Config.ExperimentalEnableDistributedTracing 等字段,定义见 server/embed/config.go

运维与可靠性类标志

  • --unsafe-no-fsync:禁用所有 fsync,会丢数据,仅用于测试/开发环境降低文件系统压力;
  • --auth-token-ttl:自定义 simple token 的 TTL;
  • --self-signed-cert-validity:指定 auto-tls 生成的自签证书有效期(默认 1 年);
  • --experimental-warning-apply-duration:apply 耗时告警阈值可配置;
  • --experimental-memory-mlock:防止 etcd 内存页被换出;
  • --socket-reuse-port:启用 SO_REUSEPORT,允许绑定已占用的端口,变更日志特别提醒需自行保证 flock 语义正确;
  • --socket-reuse-address:启用 SO_REUSEADDR,允许绑定处于 TIME_WAIT 的地址,加快重启速度;
  • --enable-log-rotation--log-rotation-config-json:启用日志轮转并向 file sink 透传 JSON 轮转配置;
  • --bootstrap-defrag-threshold-megabytes:bootstrap 时数据库未用空间超过阈值自动 defrag,值 0 表示禁用。

源码中可以看到这些标志在 server/embed/config.go 中注册,例如 socket-reuse-port 的注册与说明("Enable to set socket option SO_REUSEPORT on listeners allowing rebinding of a port already in use.")。

客户端与工具侧

  • clientv3/concurrency.Mutex 新增非阻塞的 TryLock 方法;
  • etcdctl 新增:watch --progress-notifyauth status(检查认证是否启用,对应 /v3/auth/status 端点)、get --count-only(fields 输出)、member list -w=json --hexetcdctl lock 改为返回被锁命令的退出码;
  • 新工具 etcdutl 诞生:吸收 etcdctl snapshot status|restoreetcdctl backupetcdctl defrag --data-dir ... 的功能;ETCDCTL_API=3 etcdctl migrate 同时下线,恢复 v2 存储需用 etcd <= 3.4。仓库中 etcdutl/ 目录即其实现,快照命令在 etcdutl/snapshot/v3_snapshot.go
  • gRPC gateway 通过配置文件使用时,需显式设置 enable-grpc-gateway 为 true 以与命令行默认行为保持一致。
  • 平台:官方支持 arm64,并新增 s390x 构建。

四、3.5.x 补丁系列的能力演进(按版本梳理)

v3.5 补丁系列几乎每月一个小版本,以下按"对运维者最有操作价值"的条目归纳,完整细节以 CHANGELOG/CHANGELOG-3.5.md 原文为准。

v3.5.5 / v3.5.8:连接与传输层控制

  • --max-concurrent-streams(v3.5.5):限制每个客户端同时打开的 gRPC 流数量,默认 math.MaxUint32。在 server/embed/config.go 中可看到其定义与帮助文案 "Maximum concurrent streams that each client can open at a time."
  • --tls-min-version / --tls-max-version(v3.5.8):支持 TLS 1.3。server/embed/config.go 中默认最小版本为 TLS1.2,可取 TLS1.2TLS1.3
  • --listen-client-http-urls(v3.5.8):把 HTTP 服务端从 gRPC server 上分离出来单独监听,彻底规避高读负载下 watch 流饥饿问题。源码约束见 server/embed/etcd.go--listen-client-urls--listen-client-http-urls 不允许绑定同一 URL。
  • --cipher-suites 增加 ChaCha20-Poly1305 两个套件(v3.5.0)。
  • v3.5.8 还将 zap 时间戳精度对齐到微秒(2006-01-02T15:04:05.999999Z0700),并修复了 JWT token 缺少 username/revision 时的 panic、CVE-2021-28235(认证后清除内存中的密码)。

v3.5.10 ~ v3.5.12:快照恢复与健康检查

  • v3.5.10:etcdctl snapshot restoreetcdutl snapshot restore 新增可选 --bump-revision--mark-compacted 标志,用于恢复场景中的 revision 处理;同版修复 --socket-reuse-port/--socket-reuse-address 无法在配置文件中设置的问题。
  • v3.5.11:新增 livez/readyz HTTP 端点(对以 Kubernetes pod 方式运行 etcd 的场景尤为重要);修复 --experimental-distributed-tracing-sampling-rate 不可用的问题。
  • v3.5.12:在帮助文档中补记 --experimental-enable-lease-checkpoint-persist 标志(该标志自 v3.5.2 引入,用于启用租约 checkpoint 持久化,防止 leader 切换时 TTL 被重置)。

v3.5.16 / v3.5.18 / v3.5.25:compaction 与离线检查

  • v3.5.16:新增 --experimental-compaction-sleep-interval 控制每批 compaction 之间的休眠间隔(v3.5.19 又修复了该机制带来的性能回退);同时把 etcd_disk_wal_write_duration_seconds 指标补齐了注册。
  • v3.5.18:新增 etcdutl check v2store 命令,离线检查 v2store 中是否含有自定义内容(配合 v2 存储退役流程);该命令在 v3.5.25 增加 --wal-dir 支持独立 WAL 目录,v3.5.32 进一步增强为同时检查 v2 snapshot 与 WAL 记录。命令实现位于 etcdutl/etcdutl/snapshot_command.go 相关的 etcdutl 命令目录 etcdutl/etcdutl/
  • v3.5.19:readyz 端点加入 learner 状态检查(backport)。
  • v3.5.32:--v2-deprecation 新增 write-only-skip-check 选项,可跳过 v2 内容检查。
  • v3.5.16 同时新增 --experimental-stop-grpc-service-on-defrag:defrag 期间暂停 gRPC 服务以触发客户端 failover。

贯穿性主题:安全修复密集

3.5 系列后半段(2025 下半年起)安全修复显著加密,升级决策时应对号入座:

  • v3.5.28:修复多个 API 的认证绕过(CVE-2026-33413)与嵌套事务绕过 RBAC(CVE-2026-33343);
  • v3.5.30:修复 RBAC 可通过嵌套在事务内的 Put 请求借 PrevKv 或 lease 附加读取绕过的授权漏洞;修复 quorum 满足但有一节点宕机时无法添加新成员的问题;
  • v3.5.32:修复配置了 --listen-client-http-urls 时 gRPC 监听上 CRL 强制被绕过的问题(GHSA-3wh4-j44w-pg92);
  • v3.5.33:修复"用户对某 key 有读权限却能收到以该 key 为起点的所有后续 key 的 watch 响应"的越权问题,并为 client http.Server 设置 ReadHeaderTimeout、为 peer lease HTTP handler 的 body 读取加上界、为 tlsListener 设置 tlsHandshakeTimeout;
  • v3.5.24:拒绝 revision 为 -1 的 watch 请求,防止未 compact 集群上的非法 resync。

依赖层面,每个补丁版本都会同步升级 Go 工具链(从 v3.5.8 的 go 1.19.8 一路到 v3.5.34 的 go 1.25.13)并跟进 CVE 修复(golang.org/x/crypto、x/net、grpc、protobuf、jwt 等),因此"升到最新 3.5.x"本身也是安全实践。

五、稳定性与数据正确性修复速览

除安全外,3.5 系列中值得运维关注的正确性修复包括:

  • compaction/watch 相关:v3.5.13 修复 compaction 后的 watch 事件丢失与无进度通知问题;v3.5.22 修复"watch 未来 revision 却返回旧事件";v3.5.18 修复 watch 打开在与 compaction 请求相同 revision 时缺 delete 事件的问题。
  • defrag 相关:v3.5.6 修复 defrag 期间崩溃导致 revision 不一致;v3.5.17 修复 defrag 错误处理 panic 与临时文件未关闭;v3.5.23 修复 applySnapshot 与 defragment 并发时的数据损坏风险。
  • 成员管理:v3.5.31 修复 MemberUpdate 隐式且意外地提升 learner;v3.5.24/v3.5.20 修复 learner 提升未持久化到 v3store 的问题;v3.5.28 修复开启 auth 时无法从 follower 提升成员的问题。
  • 租约:v3.5.13 修复旧 leader 的撤销请求误删新 leader 租约;v3.5.23 修复租约已吊销却返回 leaseRenew 成功的问题。
  • 读取正确性:v3.5.28 修复 read index 与 leader 切换的竞态、进程暂停导致的过期读(stale reads)。

六、如何核对与验证(结合仓库)

  1. 核对版本条目CHANGELOG/CHANGELOG-3.5.md 按版本倒序组织,直接搜索版本号即可定位;3.4 之前的记录在 CHANGELOG/CHANGELOG-3.4.md,索引见 CHANGELOG/README.md
  2. 验证标志是否可用:本文引用的服务器标志集中在 server/embed/config.go(flag 注册)与 server/etcdmain/ 目录(命令行入口与 help 文案,如 server/etcdmain/help.go 中的默认值展示),可用 etcd --help 与实际二进制输出比对。
  3. 验证工具命令:etcdutl 各子命令(snapshot、check、defrag、migrate 等)实现在 etcdutl/etcdutl/,例如 etcdutl/etcdutl/snapshot_command.goetcdutl/etcdutl/defrag_command.go
  4. 注意适用前提:本仓库处于活跃演进状态,部分 3.5 条目在主干上的实现可能已进一步变化;v3.5.34 标注 TBC(待发布),文中所有条目以该 changelog 文件的记录为准,实际部署前请以对应 release 的官方说明再次确认。

小结

etcd 3.5 系列的意义在于:v3.5.0 一次性完成 Go modules 迁移、zap 日志默认化、V2 API 废弃与 V2 API 的最终告别,并留下官方 arm64 支持与 etcdutl 新工具;此后两年多的补丁系列则以每月节奏持续交付 TLS、独立 HTTP 监听、流并发控制、快照恢复增强等运维能力,并在后期集中清除了多个 RBAC/认证绕过类漏洞。对仍运行 3.5 的集群,升级到 v3.5.33 及以上可以同时覆盖 watch 权限泄漏、CRL 绕过与无界读取等一批安全修复。

登录后查看全文
热门项目推荐
相关项目推荐