etcd v3.0 系列版本演进全解:从 v3.0.0 到 v3.0.16 的完整变更、关键特性与源码印证
【免费下载链接】etcdDistributed reliable key-value store for the most critical data of a distributed system项目地址: https://gitcode.com/GitHub_Trending/et/etcd
本文以 etcd 官方 CHANGELOG-3.0.md 为主线,完整梳理 etcd v3.0 系列自 2016-06-30(v3.0.0)至 2016-11-13(v3.0.16)共 17 个版本的发布时间线、全部变更条目与各版本对应的 Go 编译版本,并结合当前仓库源码印证其中WithPrevKV/--prev-kv选项、etcdctl migrate工具、Docker 镜像CMD/ENTRYPOINT变更等关键特性的实际实现,帮助读者准确理解 etcd 3.0 这一历史大版本的演进脉络与升级注意事项。
etcd 3.0 是 etcd 历史上最重要的架构分代版本之一:它引入了基于 gRPC 的 v3 API、mvcc 存储模型与全新的客户端生态。CHANGELOG 目录下的 README 明确规定了变更日志的编写规则:每个补丁版本仅记录相对上一个补丁版本的增量变更(例如 v3.5.5 的日志只包含相对 v3.5.4 的变更),且每个小版本的首个 release 仅包含相对上一个大版本首发的增量。因此阅读 CHANGELOG-3.0.md 时,需要把所有版本条目自上而下累加,才能还原 v3.0 系列从首个正式版到 v3.0.16 的完整能力集合。
v3.0 系列版本总览
CHANGELOG-3.0.md 覆盖 v3.0.0 至 v3.0.16 共 17 个版本,时间跨度约 4.5 个月。每个版本条目除变更内容外,均标注了编译所用 Go 工具链版本。完整时间线与 Go 版本对照如下:
| 版本 | 发布日期 | 编译 Go 版本 | 该版本要点 |
|---|---|---|---|
| v3.0.0 | 2016-06-30 | Go 1.6.2 | v3.0 首发版本(对比基线为 v2.3.0) |
| v3.0.1 | 2016-07-01 | Go 1.6.2 | 编译工具链更新 |
| v3.0.2 | 2016-07-08 | Go 1.6.2 | Dockerfile 改用ENTRYPOINT |
| v3.0.3 | 2016-07-15 | Go 1.6.2 | Docker 回退CMD;v3 etcdctl 默认端点改为127.0.0.1:2379 |
| v3.0.4 | 2016-07-27 | Go 1.6.3 | v2etcdctl ls --output=json;官方 Docker 镜像加入/var/lib/etcd目录;v2 auth 支持取 TLS 证书 CN |
| v3.0.5 | 2016-08-19 | Go 1.6.3 | SRV 记录域必须与 discovery 域匹配(未提供自定义 CA 时) |
| v3.0.6 | 2016-08-19 | Go 1.6.3 | 编译工具链更新 |
| v3.0.7 | 2016-08-31 | Go 1.6.3 | SRV 记录仅允许 A 记录(RFC 2052) |
| v3.0.8 | 2016-09-09 | Go 1.6.3 | listen URL 仅允许 IP 地址(拒绝域名) |
| v3.0.9 | 2016-09-15 | Go 1.6.3 | 放宽为对 listen URL 中的域名仅告警(v3.2 起拒绝) |
| v3.0.10 | 2016-09-23 | Go 1.6.3 | 编译工具链更新 |
| v3.0.11 | 2016-10-07 | Go 1.6.3 | 新增WithPrevKV选项与 v3 etcdctl--prev-kv参数 |
| v3.0.12 | 2016-10-07 | Go 1.6.3 | 编译工具链更新 |
| v3.0.13 | 2016-10-24 | Go 1.6.3 | 编译工具链更新 |
| v3.0.14 | 2016-11-04 | Go 1.6.3 | v3etcdctl migrate支持--no-ttl参数 |
| v3.0.15 | 2016-11-11 | Go 1.6.3 | 修复 watch 请求取消时 range end 错误的缺陷 |
| v3.0.16 | 2016-11-13 | Go 1.6.4 | 编译工具链升至 Go 1.6.4 |
从表格可以提炼出三条清晰的演进规律:
- 工具链升级非常克制:整个系列只发生过两次 Go 版本变更——v3.0.4 从 1.6.2 升到 1.6.3,v3.0.16 升到 1.6.4,均只跨点版本(patch release),体现了发布分支"只修 bug、不引入新依赖"的维护原则。
- v3.0.3 和 v3.0.4 是分水岭:前者统一了默认端点与 Docker 用法,后者补全了运维向的镜像目录与 JSON 输出能力。
- v3.0.5 到 v3.0.9 集中处理 DNS/discovery 与网络暴露面:连续四个版本围绕 SRV 记录校验、listen URL 域名策略调整,反映了社区对 etcd 集群发现机制安全性的持续收紧。
CHANGELOG 中每个版本条目的标准话术是"查看代码差异(code changes)与 v3.0 升级指南以了解破坏性变更",并反复强调:从任何旧版本升级前,务必先阅读下方全部变更日志与 v3.0 升级指南。这一提示在 v3.0 语境下尤为重要,因为 v2 到 v3 涉及 API、存储格式与 etcdctl 行为的整体切换。
v3.0.11:WithPrevKV——返回修改前的键值对
v3.0.11(2016-10-07)是 v3.0 系列中功能增量最实质的一个版本,CHANGELOG 原文记录:
- Server returns previous key-value (optional)
clientv3.WithPrevKVoption- v3 etcdctl
put,watch,del --prev-kvflag
即服务器支持(可选地)返回键被修改/删除之前的旧键值对,提供两个使用入口:Go 客户端的clientv3.WithPrevKV操作选项,以及 v3 etcdctl 的put、watch、del子命令--prev-kv参数。
这一特性在当前仓库源码中依然完整存在,可以逐一印证:
- 客户端选项定义:client/v3/op.go 中定义了
WithPrevKV()函数及其注释——"获取事件发生前的旧键值对;如果旧 KV 已被 compact,则返回零值"。它作为OpOption与Put、Delete、Watch等操作组合使用,同时提供了IsPrevKV()判断方法供内部逻辑检查该选项是否已设置。 - etcdctl 参数:三个子命令均注册了该布尔标志,帮助文本与 CHANGELOG 描述一一对应——
- etcdctl/ctlv3/command/put_command.go:
"return the previous key-value pair before modification"; - etcdctl/ctlv3/command/del_command.go:
"return deleted key-value pairs"; - etcdctl/ctlv3/command/watch_command.go:
"get the previous key-value pair before the event happens"。
- etcdctl/ctlv3/command/put_command.go:
- 使用示例:etcdctl/README.md 给出了可直接复制的命令形态,如
./etcdctl put foo bar1 --prev-kv、./etcdctl del --prev-kv key,并在 watch 章节说明--prev-kv用于在事件发生时获取修改前的键值对。
从源码结构看,WithPrevKV是一个贯穿"etcdctl 参数 → 客户端 Op 选项 → 服务端返回 PrevKv 字段"的链路型特性:mvcc 存储层在每次写入时都会保留旧版本记录,服务端按该标志把上一版本 KV 随响应/事件一起下发。典型用途包括审计(记录值被改成什么)、缓存失效判断(比较新旧值)以及调试(确认删除前该键的实际内容)。需要注意的边界是:如果旧版本已被 compaction 回收,则拿不到 prevKV——这一点由 client/v3/op.go 中WithPrevKV的注释明确说明,也是理解该特性行为的重要前提。
v3.0.14:etcdctl migrate 支持 --no-ttl
v3.0.14(2016-11-04)的 CHANGELOG 记录:
- v3
etcdctl migratecommand now supports--no-ttlflag to discard keys on transform.
etcdctl migrate是 v2→v3 升级路径上的关键工具:它扫描数据目录中 v2 键值存储的残留内容,将其转换成 v3 的键值条目,让升级后的集群能继续被 v3 API 读取。--no-ttl参数的语义是在转换过程中丢弃 v2 键携带的 TTL 信息,即转换后的 v3 键不带租约、不会自动过期。这个选项对升级决策很关键:v2 中基于 TTL 的临时键如果在 v3 中机械地映射为带租约的键,租约语义(lease 需客户端保活)与 v2 的自动过期并不完全等价,运维者可以选择丢弃 TTL,让这类键成为持久键,再按需重建过期策略。
从当前仓库的演进来看,"数据迁移"这条工具链仍在延续并重构:v3.0 时代的etcdctl migrate在后续版本中被拆分为etcdutl migrate(v2 数据→v3 快照)与etcdutl migrate snapshot,以及用于数据目录 schema 版本迁移的etcdutl migrate命令。当前仓库中 etcdutl/etcdutl/migrate_command.go 实现了面向"数据目录 schema 版本"的 migrate,要求--data-dir与--target-version(格式X.Y,最小支持 3.5)两个必填参数,并可选--force在迁移失败时强制覆写存储版本。虽然命令形态已变,但"迁移是版本升级中必须单独验证的环节"这一工程原则,从 v3.0.14 的--no-ttl一直延续到今天。
v3.0.8 / v3.0.9:listen URL 域名策略的收紧与回调
CHANGELOG 中有一个少见的"先收紧再放宽"案例,完整脉络横跨三个版本:
- v3.0.8(2016-09-09,归类于 Other):"Allow only IP addresses in listen URLs (domain names are rejected)"——监听地址只允许 IP,配置域名直接拒绝启动。
- v3.0.9(2016-09-15,归类于 Added):"Warn on domain names on listen URLs (v3.2 will reject domain names)"——改为仅打印告警,并注明该行为在 v3.2 才会真正被拒绝。
这种回调说明:把"拒绝域名"作为硬校验上线后,发现会破坏一批"容器 IP 漂移、依赖域名解析"的既有部署(例如 k8s Service 域名场景),于是先降级为告警,把破坏性变更推迟到 v3.2 这个次版本,符合 etcd 的语义化版本承诺。对运维的直接启示是:v3.0 时代在--listen-*参数中配置域名不会导致启动失败,但属于不推荐做法,升级到 v3.2+ 前必须改为 IP 地址。
同属 DNS/网络暴露面收紧的还有 v3.0.5 与 v3.0.7 的 discovery 相关规则:
- v3.0.5:"SRV records (e.g., infra1.example.com) must match the discovery domain (i.e., example.com) if no custom certificate authority is given"——未提供自定义 CA 时,集群发现使用的 SRV 记录所属域必须与 discovery 域一致,防止通过 DNS 记录将节点引导到任意第三方地址;
- v3.0.7:"SRV records only allow A records (RFC 2052)"——SRV 记录只解析 A 记录,排除了 AAAA 等其他记录类型带来的不确定性。
当前仓库中 pkg/netutil 等模块仍保留着对网络地址校验、主机名归一化的实现与测试,从源码结构看,这些 2016 年定型的校验规则是后来--listen-client-urls等参数合法性检查的历史源头。
v3.0.2 / v3.0.3:Docker 镜像 ENTRYPOINT 与 CMD 的反复
Docker 官方镜像的入口设计在两周内经历了一次完整来回:
- v3.0.2(2016-07-08):"Dockerfile uses
ENTRYPOINT, instead ofCMD, to run etcd without binary path specified"——改用ENTRYPOINT,容器启动后直接运行 etcd 服务,无需在镜像里指定二进制路径。 - v3.0.3(2016-07-15):"Revert Dockerfile to use
CMD, instead ofENTRYPOINT, to supportetcdctlrun.Docker commands for v3.0.2 won't work without specifying executable binary paths."——回退为CMD,理由是支持"同一个镜像内运行 etcdctl"的场景;同时明确警告v3.0.2 的 Docker 用法若不指定可执行二进制路径将不再可用。
回退的原因可以推断:etcd 官方镜像同时内置了etcd与etcdctl两个二进制(当前仓库的 Dockerfile 第 7-9 行依然分别ADD这三个二进制到/usr/local/bin/)。若默认入口写死为 etcd 服务,想在容器里临时执行etcdctl get这类一次性操作,就必须用docker run覆盖默认命令并显式写出二进制全路径;用CMD作为默认值则允许docker run <image> etcdctl ...这种自然用法。当前仓库 Dockerfile 末尾仍以CMD ["/usr/local/bin/etcd"]作为默认命令,印证了这个"可服务、也可执行工具"的双用途镜像定位。
v3.0.3:v3 etcdctl 默认端点变为 127.0.0.1:2379
v3.0.3 的另一条 Other 变更:"v3 etcdctl default endpoints are now127.0.0.1:2379"。在 v3.0.2 之前,v3 etcdctl 的默认端点行为与 v2 工具存在差异,导致同一台机器上 v2/v3 工具的默认连接目标不一致,容易造成"命令看似执行成功却连到别的实例"的困惑。统一为127.0.0.1:2379(etcd 的默认客户端端口)之后,零参数直接运行etcdctl put k v即可命中本机默认实例。
当前仓库的客户端生态延续了这一默认值:client/v3 客户端库在未显式指定端点时使用127.0.0.1:2379作为默认地址,测试代码(如 client/v3/clientv3util/example_key_test.go)中的Endpoints: []string{"127.0.0.1:2379"}写法也与之呼应。跨机器访问时仍建议显式使用--endpoints(-endpoints)参数,不要依赖默认值。
v3.0.4:v2 etcdctl JSON 输出、/var/lib/etcd 目录与证书 CN 认证
v3.0.4(2016-07-27)包含三条变更,各自对应一类运维场景:
- Added:v2
etcdctl ls支持--output=json。在 v2/v3 双 API 并存的过渡期,v2 工具此前只有人类可读的树状/文本输出;补齐 JSON 输出后,脚本可以直接消费etcdctl ls的结果做结构化解析,为后续迁移到 v3 工具链争取了平滑窗口。 - Added:官方 Docker 镜像加入
/var/lib/etcd目录。这是 etcd 官方约定的数据目录默认位置。当前仓库的 Dockerfile 中WORKDIR /var/lib/etcd/一行正是这条变更留下的痕迹——镜像预建该目录,保证卷挂载与数据落盘路径自 v3.0 时代起保持稳定。 - Other:v2 auth 在启用
--client-cert-auth时可以使用 TLS 证书中的 Common Name。即 v2 用户体系支持"以证书 CN 作为身份"的客户端认证方式:开启双向 TLS 后,服务端从客户端证书中提取 CN 作为用户名完成鉴权,无需为每个调用方单独颁发用户名/口令。这一"证书即身份"的模式在 v3 auth 体系中被进一步规范化(v3 的 role/user 与 TLS 客户端认证可以组合使用),是 etcd 多租户部署的常用做法。
v3.0.15:watch 取消请求的 range end 缺陷修复
v3.0.15(2016-11-11)仅一条 Fixed 变更:
- Fix cancel watch request with wrong range end.
即取消(cancel)watch 请求时携带了错误的 range end的缺陷修复。watch 是流式长连接,客户端断开或主动取消时,服务端需要按正确的 key range 结束对应的事件流;range end 计算错误会导致取消请求命中错误的键区间,表现为 watch 无法及时释放或误取消邻近区间的订阅。虽然只是一行描述,但属于正确性级别(correctness)缺陷——任何依赖 watch 做服务发现或状态同步的系统,其断连清理路径都会受影响。
面向升级者的阅读指引:如何正确使用这份变更日志
综合 CHANGELOG/README.md 的规则与 CHANGELOG-3.0.md 的内容,给出三条实操性建议:
- 按规则累加阅读。由于"补丁版本日志只含相对上一补丁的增量",v3.0.16 用户的升级检查单 = v3.0.16 + v3.0.15 + …… + v3.0.0 全部条目的并集。上文的"版本总览"表已经完成了这一累加,可直接作为检查单使用。
- 区分变更类别。CHANGELOG 使用
Added/Fixed/Other/Go四类小节:Added是能力增量(v3.0.4、v3.0.11、v3.0.14);Fixed是缺陷修复(v3.0.15);Other多涉及行为与兼容性(Docker 入口、SRV 校验、listen URL 策略)——升级风险主要藏在Other里,v3.0.2→v3.0.3 的 Docker 用法不兼容即为例证;Go仅是编译工具链说明,对使用者无直接行为影响。 - 注意生产版本推荐。当前仓库 CHANGELOG/README.md 明确指出:生产环境最低推荐版本为 v3.4.22+ 与 v3.5.6+,且 v3.5.0~v3.5.2 在高负载下存在数据损坏问题(建议升级至 v3.5.4+,仓库中亦有对应事后报告 Documentation/postmortems/v3.5-data-inconsistency.md)。因此本文对 v3.0 系列的分析定位是版本演进研究与存量 v3.0 集群的升级决策参考,新集群部署应直接采用当前受支持的大版本;CHANGELOG-3.0.md 中反复引用的"v3.0 升级指南"在当时指向 etcd 官方文档站,当前仓库内对应升级资料可参阅 CHANGELOG/CHANGELOG-3.1.md 及后续各版本日志的延续脉络。
小结
etcd v3.0 系列的 17 个版本浓缩了一个大版本发布分支的典型形态:首发(v3.0.0)确立 3.0 架构,随后一个多月内通过高频小步补丁(最快两天一个版本,如 v3.0.12/v3.0.13 与 v3.0.15/v3.0.16)完成三类工作——补齐能力(WithPrevKV、migrate --no-ttl、JSON 输出)、修正行为(watch 取消缺陷、Docker 入口回退)、收紧边界(SRV/discovery 域名校验、listen URL 仅告警域名的过渡策略)。对照当前仓库源码可见,其中--prev-kv选项(client/v3/op.go、etcdctl/ctlv3/command/put_command.go 等)、/var/lib/etcd镜像目录与127.0.0.1:2379默认端点(Dockerfile、client/v3)均已成为延续至今的既定事实;而工具链本身则从etcdctl migrate演进为今天 etcdutl/etcdutl/migrate_command.go 中的 schema 版本迁移命令。理解这份变更日志,既是对 etcd 3.0 时代的一次完整复盘,也为排查"从 v3.0 老集群升级"场景中的兼容性问题提供了权威依据。
【免费下载链接】etcdDistributed reliable key-value store for the most critical data of a distributed system项目地址: https://gitcode.com/GitHub_Trending/et/etcd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考