首页
/ etcd v3.6 系列变更日志详解:从 v3.6.0 破坏性变更、新特性到 v3.6.15 的安全修复全览

etcd v3.6 系列变更日志详解:从 v3.6.0 破坏性变更、新特性到 v3.6.15 的安全修复全览

2026-09-05 12:12:28作者:贡沫苏Truman

etcd 官方变更日志 CHANGELOG-3.6.md 完整记录了 v3.6 版本线从 v3.6.0-rc.0 到 v3.6.15 的全部演进:包括移除 v2 兼容层带来的破坏性变更、v2 弃用(deprecation)流程、一批新增服务端启动参数、存储层包结构重组,以及十几个补丁版本中持续修复的 RBAC 越权、watch 权限泄漏等安全漏洞。读完本篇,你将掌握 v3.6 相对 v3.5 的关键差异点、升级前必须核对的配置清单,以及各补丁版本修复问题的分类索引,用于制定安全的升级与回退策略。

一、v3.6 版本线全景

v3.6 是 etcd 版本演进中的重要节点,官方变更日志按“发布版 + 补丁版”的方式组织:

  • v3.6.0-rc.0 ~ v3.6.0-rc.5(2025-02-13 至 2025-05-08):候选发布版,承载了绝大部分特性开发与破坏性变更;
  • v3.6.0(2025-05-15):正式发布,官方明确说明“自 v3.6.0-rc.5 之后没有任何生产代码变更”;
  • v3.6.1 ~ v3.6.15(TBC):从 2025-06-06 到 2026-07 之后的补丁版,以缺陷修复、安全漏洞修复(含多个 CVE 与 GHSA 公告)和依赖升级为主,其中 v3.6.13、v3.6.14 引入了少量功能性变更(如 --v2-deprecationwrite-only-skip-check 选项)。

从源码侧印证,当前仓库的版本常量集中在 api/version/version.go 中,定义了 V3_5V3_6V3_7 等 semver 版本对象与 MinClusterVersion = "3.0.0"(最小兼容集群版本),v3.6 系列服务端在判断集群成员版本、执行降级检查时依赖这些常量。注意:当前仓库主干已处于 3.8.0-alpha.0 开发阶段(各 go.mod 要求 Go 1.26),本文所有 v3.6 相关结论均以官方变更日志及仓库中可核对的实现为准,适用于 v3.6.x 系列。

二、v3.6.0 的破坏性变更(升级前必读)

变更日志在 v3.6.0-rc.0 中用 “Breaking Changes” 一节集中声明了四类破坏性变更,这是升级决策的核心依据:

2.1 数据目录不再向前兼容,降级需用 etcdutl migrate

v3.6 的 etcd 二进制无法直接运行在更高版本(如 v3.7+)创建的数据目录上。如需将数据目录降级到 v3.6 可读取的格式,官方指定路径是 etcdutl migrate 命令。这与 v3.6.0 中新增的 etcdutl migrate 命令(用于降级/升级 etcd 数据目录文件)相呼应——v3.6 正式确立了“新版本数据目录单向兼容”的原则。

2.2 移除的启动参数

以下 v2 时代与代理相关的 flag 被整体移除,升级脚本中必须清理:

  • --enable-v2
  • --experimental-enable-v2v3
  • --proxy
  • --proxy-failure-wait
  • --proxy-refresh-interval
  • --proxy-dial-timeout
  • --proxy-write-timeout
  • --proxy-read-timeout

2.3 其他行为变更

  • peer 端口不再服务客户端请求etcd 不再支持在 peer 监听端口(--listen-peer-urls)上处理客户端请求。依赖“客户端复用 peer 端口”的部署需要显式配置 client 监听地址;
  • etcdctl 删除保护etcdctl 执行不带 --range flag 的 range delete 时会 sleep 2 秒,为误操作提供缓冲窗口;
  • 构建要求:依赖 etcd v3.6 相关 Go 包的应用必须使用 Go >= 1.18 构建;v3.6.0 发布线自身要求 Go 1.23+ 编译(后续补丁版逐步升级到 Go 1.24、1.25 系列,见 4.3 节)。

2.4 弃用与移除的既有能力

变更日志的 Deprecations 一节列出:

  • 弃用 V2 discovery(v2 发现协议);
  • 弃用 limitListenerConn 中的 SetKeepAliveSetKeepAlivePeriod
  • 移除 etcdctl defrag --data-dir 选项;
  • 移除 etcdctl snapshot statusetcdctl snapshot restore 命令(snapshot 相关操作统一收敛到 etcdutl snapshot);
  • 移除 server/embed 包中的 NewZapCoreLoggerBuilder 导出 API。

这些变更直接改变了运维工具链:例如做快照备份/恢复的自动化脚本,从 v3.5 的 etcdctl snapshot 切换为 etcdutl snapshot

三、v3.6.0 的新特性与参数变化

3.1 服务端新增启动参数

v3.6.0 集中新增了一批服务端 flag,以下结合变更日志说明其用途与默认值:

参数 说明
--log-format 支持配置日志格式(v3.6.5 中同时移除了 --help 输出里已删除的 --experimental-snapshot-catch-up-entries 残留)
--experimental-max-learners 配置 learner 成员数量上限(后在 rc.3 中被 Feature Gate 取代,见 3.2 节)
--experimental-enable-lease-checkpoint-persist 用于从开启了该特性的 v3.5.2 集群平滑升级;该特性在 v3.6 中默认开启
--max-concurrent-streams 限制每个客户端可打开的最大并发 gRPC 流数量,默认 math.MaxUint32(不限制)
--experimental-compact-hash-check-enabled / --experimental-compact-hash-check-time 支持对已压缩(compacted)revision 启用可靠的损坏检测
--experimental-snapshot-catch-up-entries 配置 raft 存储压缩后慢 follower 追赶所需的条目数,默认 5000
--tls-min-version / --tls-max-version 启用对 TLS 1.3 的支持
--warning-unary-request-duration --experimental-warning-unary-request-duration 毕业而来;实验性 flag 已弃用并将在 v3.7 移除

其中 --max-concurrent-streams 的默认值可以在当前仓库中得到印证:server/etcdmain/config.go 中通过 flags.Uint32FromFlag(cfg.cf.flagSet, "max-concurrent-streams") 读取该参数,server/etcdmain/help.go 的帮助文本同样显示其默认值为 math.MaxUint32

另一个影响运维直觉的默认值变更:--snapshot-count 的默认值从 100,000 下调到 10,000,即 raft 日志更频繁地触发快照,降低磁盘上 WAL 的堆积。变更日志后续还记录了相关参数的反复调整:v3.6.8 将 --max-snapshots 的移除时间从 v3.7 推迟到 v3.8,并撤销了对 --snapshot-count 的弃用——这说明官方对快照相关参数的策略在 v3.6 系列中保持审慎。

3.2 Feature Gate 机制与 v3.6 特性开关

v3.6 引入了(或扩展了)Feature Gate 来管理实验性特性。当前仓库的 server/features/etcd_features.go 中定义了一套完整的 gate 注册表,其中标注 “alpha: v3.6” 的条目与变更日志逐条对应:

  • StopGRPCServiceOnDefrag:defragmentation 期间停止 gRPC 服务以处理客户端请求(alpha,默认 false);
  • InitialCorruptCheck:在服务任何 client/peer 流量前做数据损坏检查(alpha,默认 false);
  • CompactHashCheck:leader 周期性检查 follower 的 compaction 哈希,即 3.1 节 --experimental-compact-hash-check-* 参数背后的 gate(alpha,默认 false);
  • LeaseCheckpoint / LeaseCheckpointPersist:leader 向其他成员发送租约检查点,防止 leader 切换导致剩余 TTL 重置(alpha,默认 false);
  • SetMemberLocalAddr:允许使用 initial-advertise-peer-urls 中第一个非 loopback 本地地址作为与 peer 通信的本地地址(alpha,默认 false);
  • TxnModeWriteWithSharedBuffer:写事务在只读检查中使用共享缓冲区(v3.5 起 beta,默认 true)。

可以印证变更日志中的一段历史:v3.6.0-rc.3 的 “Replace ExperimentalMaxLearners with a Feature Gate” 说明 --experimental-max-learners 参数最终被 Feature Gate 机制取代;rc.2 还新增了“通过 Prometheus metric 查询服务端 feature gate”的能力,便于运维在监控面观察 gate 状态。

3.3 etcdctl 与 etcdutl 变化

etcdctl v3 的新增能力:

  • 新增 shell completion 生成命令(etcdutl 同样获得该能力);
  • endpoint status 输出新增 db 使用大小字段,并新增 storageVersion 字段;v3.6.0-rc.1 进一步在 endpoint status 结果中加入 DowngradeInfo(降级信息),与 v3.6 的降级/兼容性检查能力配套;
  • --max-txn-ops 加入 make-mirror 命令;make-mirror --rev 支持增量镜像;
  • member list 新增 --consistency flag;成员列表 JSON 输出中 raft_term 恒定以十进制打印;
  • endpoint hash 命令展示 hash_revision 字段;
  • 新增全局 flag --max-request-bytes--max-recv-bytes

etcdutl v3 的新增能力:

  • 新增 migrate 命令(数据目录降级/升级,见 2.1 节);
  • snapshot restore 新增可选的 --bump-revision--mark-compacted 参数。这一实现可在当前仓库 etcdutl/etcdutl/snapshot_command.go 中直接看到:--bump-revision 用于恢复后提升 revision,--mark-compacted 用于将恢复后的最新 revision 标记为计划压缩点(当 --bump-revision > 0--mark-compacted 为必填,否则禁止使用);
  • 新增 hashkv 命令,打印到指定 revision 为止的键值哈希,用于跨集群数据一致性校验;
  • 移除了 legacy etcdutl backup
  • 键数量统计改为“从用户视角”计数(排除内部键),使 etcdutl 报告的键数与用户可见数据一致。

3.4 包结构重组与 raft 独立

v3.6.0 对服务端 Go 包做了大规模搬移,当前仓库目录结构正是其结果:

  • mvccstorage/mvcc(对应仓库 server/storage/mvcc);
  • mvcc/backendstorage/backend
  • mvcc/bucketsstorage/schema
  • walstorage/wal
  • datadirstorage/datadir

更深层的架构动作是 raft 与 etcd 解耦:raft 模块迁移到独立仓库并更名为 go.etcd.io/raft/v3。此外 v3.6.0-rc.3 将 client/internal/v2 移入 server/internal/clientv2,v3.6.0-rc.4 则完成“v2 与 v3 同步后切换为校验 v3”的校验策略调整——这些都是 v2 数据平面逐步退役(deprecation)路线图的一部分。

其他值得注意的基础设施变更:

  • 镜像基础镜像切换为 Distroless,降低攻击面并缩小镜像体积;
  • grpc-gateway 从 v1 升级到 v2;
  • Prometheus 集成从 go-grpc-prometheus 切换到 grpc-ecosystem/go-grpc-middleware/providers/prometheus
  • 新增指标:etcd_disk_defrag_inflight(进行中的 defrag 数)、etcd_debugging_server_alarms(服务端告警)、etcd_server_range_duration_seconds(range 请求耗时分布)。

3.5 v2 弃用(deprecation)流程

v3.6 系列持续完善 --v2-deprecation 选项:v3.6.13 新增 write-only-skip-check 选项以绕过 v2 内容检查,为只需“只写不读”的场景提供过渡空间;v3.6.12 修复了 MemberUpdate 意外提升 learner、以及 etcdutl 对数据文件路径 panic 而非校验的问题。e2e 测试 tests/e2e/v2store_deprecation_test.go 覆盖该流程下的快照恢复场景。

四、v3.6.x 补丁版修复索引(v3.6.1 ~ v3.6.15)

补丁版是运维选型的关键:如果线上运行 v3.6.0/v3.6.1,建议至少升级到包含下列安全修复的版本。

4.1 安全修复(按发布时间)

版本 修复内容
v3.6.9(2026-03-20) CVE-2026-33413:多个未鉴权端点的越权访问,通过 auth 检查守护未认证端点;CVE-2026-33343:嵌套事务绕过 RBAC 授权检查,对嵌套 txn 操作强制鉴权
v3.6.11(2026-05-01) RBAC 越权:嵌套事务中 Put 请求通过 PrevKv 或 lease 挂接实现读越权(PR #21681、#21685)
v3.6.13(2026-07-01) 配置 --listen-client-http-urls 时 gRPC listener 上 CRL 强制校验被绕过(GHSA-3wh4-j44w-pg92)
v3.6.14(2026-07-23) watch 权限漏洞:仅对某个 key 有读权限的用户会收到从该 key 开始所有 key 的 watch 响应(GHSA-xg4h-6gfc-h4m8);peer 租约 HTTP handler 上无界 io.ReadAll;客户端 http.Server 缺少 ReadHeaderTimeout;TLS 握手超时(GHSA-6vch-q96h-7gc3)

依赖侧同步修复了多个 CVE:golang.org/x/net(CVE-2026-25681 等 6 项)、golang.org/x/crypto(CVE-2025-47914、CVE-2026-46598 等)、google.golang.org/grpc(GHSA-hrxh-6v49-42gf、CVE-2026-33186)、OpenTelemetry SDK(CVE-2026-29181 等)、golang-jwt(CVE-2025-30204)。仓库安全公告的发布流程可参考 security/security-release-process.md

4.2 关键行为与数据正确性修复

  • watch:v3.6.1 修复“watch 未来 revision 返回旧事件/通知”;v3.6.9 修复 read index 与 leader 切换的竞态、进程暂停导致的 stale reads;v3.6.6 拒绝带 -1 revision 的 watch 请求,防止在未压缩 etcd 上的非法 resync 行为;
  • lease:v3.6.5 修复“租约已撤销时 leaseRenew 仍可能返回成功”;v3.6.6 修复启用 auth 后无法从 follower 提升成员;
  • 数据目录/快照:v3.6.5 修复 applySnapshot 与 defragment 并发时的潜在数据损坏;v3.6.4 修复回放 learner 提升操作导致 bootstrap 失败;v3.6.6 修复 --force-new-cluster 在创建快照后无法清理 learner、以及 v3.6.1 在 corner case 下无法移除全部其他成员;
  • 压缩(compaction):v3.6.0-rc.5 修复压缩暂停时长指标未按每批压缩输出的问题;
  • 成员/集群:v3.6.11 修复“一个成员宕机但 quorum 仍满足时无法添加新成员”;v3.6.12 修复 MemberUpdate 意外提升 learner 的 bug、允许非 admin 获取 maintenance status;v3.6.10 允许非 admin 获取成员列表与告警;
  • gRPC/代理:v3.6.9 修复 grpc-proxy 启动死锁;v3.6.0-rc.3 修复 grpcproxy 陷入死循环导致高 CPU;rc.2 升级 grpc-gateway 修复 REST watch 流请求导致 etcdserver 崩溃;
  • 认证/可观测:v3.6.7 日志中只打印 token 指纹而非原始 token;v3.6.13 修复 bearer 前缀 auth token 的 websocket 认证;v3.6.9 保证 metrics interceptor 先于其他 interceptor 执行以维持指标时效;
  • clientv3 客户端:v3.6.14 修复 leaseCache.entries 的无同步 range 遍历;v3.6.9 在 unary interceptor 中打印 gRPC 请求实际发送到的 endpoint;v3.6.8 移除对 grpc-go Metadata 字段的使用;v3.6.0-rc.5 将 resolver.State.Addresses 替换为 resolver.State.Endpoint.Addresses

4.3 Go 工具链与依赖追踪

变更日志逐版本记录了编译工具链的演进,可作为供应链核对依据:

  • v3.6.0 线:Go 1.23.7 ~ 1.23.9;
  • v3.6.1:Go 1.23.10;v3.6.2:Go 1.23.11 + bbolt v1.4.2;
  • v3.6.5:Go 1.24.7 + bbolt 升级到 v1.4.3;
  • v3.6.6 ~ v3.6.8:Go 1.24.10 → 1.24.11 → 1.24.13(后者同时修复 Go 语言本身的 3 个 CVE);
  • v3.6.9 ~ v3.6.12:Go 1.25.8 → 1.25.10;
  • v3.6.13 ~ v3.6.14:Go 1.25.11 → 1.25.12;
  • v3.6.15(TBC):Go 1.25.13。

五、升级与核对建议

基于以上变更日志与仓库证据,面向 v3.6 的运维决策可以归纳为三点:

  1. 升级路径:从 v3.5 升级到 v3.6 前,先清理 2.2 节列出的已移除 flag、把 etcdctl snapshot 脚本迁移到 etcdutl snapshot,并确认 Go 构建链满足要求;跨大版本回退前先评估数据目录格式,必要时使用 etcdutl migrate
  2. 版本选型:生产环境建议直接采用包含 4.1 节全部安全修复的 v3.6.14 及以上版本(当前最新条目为 v3.6.15/TBC),尤其当集群启用了 auth 与 TLS CRL 时,v3.6.13 与 v3.6.14 的修复不可跳过;
  3. 特性核对:通过 Feature Gate 与 endpoint statusDowngradeInfo/storageVersion 字段确认集群特性状态与存储版本,结合 etcd_disk_defrag_inflightetcd_server_range_duration_seconds 等新指标完善监控。

更早期的版本历史可查阅 CHANGELOG-3.5.md,各版本对应的代码结构与参数实现可在 server/etcdmainserver/features/etcd_features.goetcdutl/etcdutl/snapshot_command.go 等路径中继续核对。

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