etcd v3.6 系列变更日志详解:从 v3.6.0 破坏性变更、新特性到 v3.6.15 的安全修复全览
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-deprecation的write-only-skip-check选项)。
从源码侧印证,当前仓库的版本常量集中在 api/version/version.go 中,定义了 V3_5、V3_6、V3_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执行不带--rangeflag 的 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中的SetKeepAlive与SetKeepAlivePeriod; - 移除
etcdctl defrag --data-dir选项; - 移除
etcdctl snapshot status与etcdctl 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新增--consistencyflag;成员列表 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 包做了大规模搬移,当前仓库目录结构正是其结果:
mvcc→storage/mvcc(对应仓库 server/storage/mvcc);mvcc/backend→storage/backend;mvcc/buckets→storage/schema;wal→storage/wal;datadir→storage/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 的运维决策可以归纳为三点:
- 升级路径:从 v3.5 升级到 v3.6 前,先清理 2.2 节列出的已移除 flag、把
etcdctl snapshot脚本迁移到etcdutl snapshot,并确认 Go 构建链满足要求;跨大版本回退前先评估数据目录格式,必要时使用etcdutl migrate; - 版本选型:生产环境建议直接采用包含 4.1 节全部安全修复的 v3.6.14 及以上版本(当前最新条目为 v3.6.15/TBC),尤其当集群启用了 auth 与 TLS CRL 时,v3.6.13 与 v3.6.14 的修复不可跳过;
- 特性核对:通过 Feature Gate 与
endpoint status的DowngradeInfo/storageVersion字段确认集群特性状态与存储版本,结合etcd_disk_defrag_inflight、etcd_server_range_duration_seconds等新指标完善监控。
更早期的版本历史可查阅 CHANGELOG-3.5.md,各版本对应的代码结构与参数实现可在 server/etcdmain、server/features/etcd_features.go、etcdutl/etcdutl/snapshot_command.go 等路径中继续核对。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00