etcd v3.4 版本发布全史:从 Learner、Pre-Vote 到 v3.4.45 EOL 的变更解读与升级要点
本文基于仓库中的 CHANGELOG-3.4.md 完整梳理 etcd v3.4 系列(v3.4.0 ~ v3.4.45)的 45 个补丁版本发布记录,覆盖每个版本的服务端修复、clientv3 改进、安全漏洞响应与依赖升级。读完本文,你能掌握:v3.4 相对 v3.3 引入了哪些核心能力(Learner、Pre-Vote、watch 分片、lease checkpointing)、哪些行为属于破坏性变更(breaking changes)、哪些 CVE 修复必须跟进,以及如何依据 changelog 制定生产环境的版本选择与升级策略。
一、v3.4 变更日志的组织方式与 EOL 公告
仓库中每个 minor 版本对应一份独立变更日志(CHANGELOG/ 目录下有 CHANGELOG-3.3.md 至 CHANGELOG-4.0.md 等),阅读顺序由新到旧。CHANGELOG/CHANGELOG-3.4.md 记录 v3.4.0(2019-08-30)到 v3.4.45(2026-06-01)的全部发布,其组织规则在 CHANGELOG/README.md 中明确:
- 每个补丁版本只记录相对上一个补丁版本的变更(例如 v3.5.5 只包含相对 v3.5.4 的新增项);
- 每个 minor/major 的第一个版本(如 3.4.0)只记录相对上一 minor 版本(3.3.0)的新增内容。
v3.4.45(2026-06-01)是 v3.4 系列的最终版本,标志着该分支结束支持(EOL):changelog 明确声明“此后不再发布补丁”,仍在使用 v3.4 的环境应尽快升级到受支持的版本。这是阅读本 changelog 时最重要的一条信息——v3.4 的所有修复(包括下文多个 CVE 修复)只在 v3.4 分支内有效,长期策略上应规划升级到 v3.5+ 分支。
当前仓库主分支已经领先于 v3.4:api/version/version.go 中 Version = "3.8.0-alpha.0",且 AllVersions 版本列表包含 V3_4、V3_5 … V4_0 等常量。因此文中若引用当前源码路径,均指主分支实现,用于印证 v3.4 引入的特性在代码中的落点,而不是 v3.4 分支本身。
二、v3.4.0:一次能力跃迁版本
v3.4.0(2019-08-30,含 rc.0~rc.4 共 6 个发布阶段)是 v3.4 的主版本,变更密度远高于后续补丁版本。以下按主题完整继承 changelog 的核心内容。
2.1 Raft Learner 与集群扩缩容
- Add Raft learner:etcd 支持以 learner 身份添加成员。用户可通过
etcdctl member add --learner添加 learner,再用etcdctl member promote提升为正式成员,API 层对应MemberAddRequest/isLearner字段与新增的MemberPromoteRPC。从当前仓库源码看,这套接口仍保留在 client/v3/cluster.go(MemberAddAsLearner/MemberPromote)与服务端 RPC 定义 api/etcdserverpb/etcdserver.proto 中。 - learner 配套的可观测性指标:
etcd_server_is_learner、etcd_server_learner_promote_failures、etcd_server_learner_promote_successes。 - raft 包层面:
raftpb.ConfState.Nodes更名为raftpb.ConfState.Voters;新增raftpb.ConfChangeV2支持 joint quorum(联合仲裁);新增raft/quorum、raft/confchange包处理成员变更;learner 可以投票但不计入 quorum(针对已提升但尚未感知的过渡态)。
2.2 客户端(clientv3)重大重构
- 重写 client balancer:基于 gRPC 新的 balancer 接口(gRPC 升级到 v1.23.0),修复了“kube-apiserver 1.13.x 在首个 etcd-server 不可用时拒绝工作”与“多成员集群 failover 时 DNS 不一致导致证书校验失败”两类问题。新的 balancer 使用异步 resolver 把 endpoints 传给 gRPC dial 函数,如需阻塞直到底层连接建立,需要在
clientv3.Config.DialOptions中传入grpc.WithBlock()。 - watch 分片(fragmentation):
etcdserverpb.WatchCreateRequest新增fragment字段,当 watch 事件总量超过服务端etcd --max-request-bytes(默认embed.DefaultMaxRequestBytes为 1.5 MiB)+ gRPC 开销 512 字节时,服务端将事件拆分为多个低于上限的 chunk 发送;clientv3 端通过WithFragmentOpOption 与自动合并逻辑对接。适用于客户端带宽受限的场景。 Watcher.RequestProgress方法:手动触发向所有关联 watch 流广播 progress 事件(带最新 header 的空响应),可视为可手动触发的WithProgressNotify。- watch 重试在瞬态错误时加入 backoff;watch progress notify 加入 jitter,避免
etcd_network_client_grpc_sent_bytes_total尖峰。 PermitWithoutStream选项:允许客户端在没有活跃流的情况下发送 keepalive ping。- 修复 lease keepalive 在响应队列满时仍以 500ms 而非 TTL/3 频率发送的问题;修复
clientv3/concurrency在取消时释放锁 key 的逻辑;修复(*Client).Endpoints()竞态。
2.3 自动压缩(Auto-Compaction)保留窗口调整
--auto-compaction-mode=revision --auto-compaction-retention=1000:每 5 分钟在 “latest revision − 1000” 处压缩。- periodic 模式行为变化:
--auto-compaction-retention=24h时,压缩从每 2.4 小时一次改为每小时一次(v3.3.3 之前是 2.4 小时);--auto-compaction-retention=30m时从每 3 分钟一次改为每 30 分钟一次。压缩器在每个压缩周期(<1h 按周期,>1h 按 1h)记录最新 revision,用上一周期获取的 revision 丢弃历史数据,保留窗口随之逐周期移动。 - 修复 revision 模式保留值解析 bug:此前
--auto-compaction-mode revision --auto-compaction-retention 1会被错误解析为 3600000000000。
2.4 Raft 选举与重启行为
- Pre-Vote 特性:新增
etcd --pre-vote标志(v3.4 默认false,v3.5 起默认true)。故障/重加入的成员会发起选举并把 term 抬高,导致忽略低 term 消息、最终触发一次破坏性选举;Pre-Vote 阶段先探测能否获得足够选票,从而避免此类扰动。 - initial election tick advance:新增
etcd --initial-election-tick-advance(默认true)。默认情况下本地成员在启动时快进选举 tick 以加速首次选主——例如跨数据中心部署需要 10 秒选举超时时,tick 可快进到只剩 2 秒。若 leader 到重加入 follower 的网络拥塞、follower 没能在剩余 tick 内收到心跳,仍会发生破坏性选举,可设false关闭,代价是跨数据中心场景的初始 bootstrap 变慢;单节点集群无论该值如何都会快进。 - 长读事务并发改进:backend 读事务做到全并发(此前长读会阻塞写与后续读),在有长读存在时写吞吐提升 70%、P99 写延迟降低 90%;周期性 commit 不再阻塞并发读事务。
- index compaction 使用 copy-on-write clone,不再持锁遍历整个索引。
- 新增
raft.ErrProposalDropped:内部 Raft proposal 被丢弃时(成员被移除、leadership transfer 期间收到MsgProp等)服务端向 v3/v2 applier 返回该错误。 raft.Config.MaxUncommittedEntriesSize限制未提交 entry 总字节数,超限返回ErrProposalDropped,防止 Raft 日志无界增长;Ready.CommittedEntries支持按MaxSizePerMsg分页,避免日志极大时一次性 commit 导致 OOM。- 消息发送流控优化:leader 允许多个在途 append 消息;新增
raft/tracker包单独承载 progress 跟踪。
2.5 Lease 相关
- Lease checkpointing:新增
--experimental-enable-lease-checkpoint实验标志,把剩余 TTL 周期性持久化到共识日志,使长寿命 lease 在 leader 切换与重启后仍按预期走向过期。 - lease 过期/撤销操作性能改进;
Lease.Lookup在并发Grant/Revoke下变为非阻塞。 - 防止
Grant的超大TTL溢出:TTL 单位为秒,超过 9,000,000,000 秒(约 285 年)时服务端返回rpctypes.ErrLeaseTTLTooLarge。etcd Lease 设计目标是秒/分钟级会话,而非小时/天级。
2.6 日志体系:zap 取代 capnslog
- 新增
etcd --logger标志支持结构化日志。--logger=capnslog --log-outputs=default为默认(与旧格式一致);--logger=zap输出 JSON 格式,--log-outputs支持多个输出(stderr、stdout、systemd/journal、任意文件,可组合如a.log,b.log,c.log,stdout;/dev/null丢弃日志)。注意--logger=zap --log-outputs=default组合不支持,需显式指定stderr等。 - 动机是让 etcd “少打日志、多靠指标告警”,推动自动化监控而非回看日志排障。
- 新增
--log-level标志;--log-output更名为--log-outputs(--log-output在 v3.5 弃用);--debug标志被弃用,改用--log-level=debug。 embed.Config.SetupLogging被移除,日志器基于embed.Config.Logger、LogOutputs、Debug字段自动建立。
2.7 安全与认证
- TLS 密码套件白名单:新增
etcd --cipher-suites与embed.Config.CipherSuites,用于屏蔽弱密码套件;为空时由 Go 自动填充;embed.Config.ClientTLSInfo.CipherSuites与embed.Config.CipherSuites不可同时非空。 - Host 白名单:新增
etcd --host-whitelist(以及etcdserver.Config.HostWhitelist、embed.Config.HostWhitelist)防御 DNS Rebinding 攻击。策略:HTTPS 连接放行任意 hostname;非安全连接且白名单非空时,仅放行 Host 字段在白名单内的 HTTP 请求;默认*表示非安全服务器放行所有请求;回环地址不会自动加入,需要手动添加localhost/127.0.0.1。该策略无论是否开启认证都会执行。当前源码中标志注册仍在 server/embed/config.go(host-whitelist,默认*)。 - 支持无密码用户(只能走 CommonName 认证),降低密码泄露风险。
- 支持
etcd --cors用于 gRPC gateway 的 v3 HTTP 请求;embed.Config.CorsInfo(*cors.CORSInfo)改为embed.Config.CORS(map[string]struct{})。 - JWT 认证:token 支持
ttl字段(如--auth-token jwt,pub-key=...,priv-key=...,sign-method=...,ttl=5m),签名算法放开为任意支持的方法;etcdserver.ServerConfig.AuthToken允许空的 token provider。 - 修复证书 SAN 仅含 IP 时 TLS reload 不触发的问题:现在初始握手时
(*tls.Config).Certificates置空以触发GetCertificate,即使客户端 SNI 为空也能在线轮换过期证书。 - 新增
--experimental-peer-skip-client-san-verification跳过对 peer 客户端地址的校验。
2.8 破坏性变更(v3.4 升级必读)
以下为 changelog 明确列出的 breaking changes,从 v3.3 升级到 v3.4 时逐条核对:
- 导入路径迁移:模块从
"github.com/coreos/etcd"迁移到"github.com/etcd-io/etcd",导入路径统一改为go.etcd.io/etcd/...(如import "go.etcd.io/etcd/raft")。 - 依赖管理从 glide 迁移到 Go modules,要求 Go 1.12+;
cmd/vendor移到仓库根vendor,移除cmd下递归软链;go get/install/build强制使用 vendor 构建。 etcdctl默认 API=3:etcdctl set foo bar必须改为ETCDCTL_API=2 etcdctl set foo bar;etcdctl put foo bar不再需要ETCDCTL_API=3前缀。- v2 store 默认关闭:
etcd --enable-v2=false成为默认,embed.DefaultEnableV2也改为 false。 - TLS 标志更名:
--ca-file弃用改用--trusted-ca-file;--peer-ca-file弃用改用--peer-trusted-ca-file;pkg/transport.TLSInfo.CAFile字段弃用改用TrustedCAFile。 - 容器标签:
latest与 minor 版本 tag 弃用——docker pull .../etcd:v3.4不再可用,必须用精确补丁版本 tag(如v3.4.x);ACI 产物停止提供。 - 空 host 的 advertise URL 直接退出:如
--advertise-client-urls=http://:2379会报错退出。 - 影子环境变量退出:如
ETCD_NAME=abc etcd --name=def、ETCDCTL_ENDPOINTS=abc.com ETCDCTL_API=3 etcdctl endpoint health --endpoints=def.com会报错退出。 - proto 字段类型变化:
AuthRoleRevokePermissionRequest的key/range_end从string改为bytes。 - gRPC gateway 端点:
/v3beta、/v3alpha弃用,统一为/v3(v3.4 中/v3beta仍作为/v3的 fallback 可用,v3.5 移除);lease 相关 HTTP 端点从/v3/kv/lease/*迁移到/v3/lease/{leases,revoke,timetolive}。 - snapshot 文件权限:Linux 下从 0644 收紧为 0600。
etcdctl snapshot退出码变化:出错统一退出码 1(不再有 5/6)。grpc.ErrClientConnClosing弃用:clientv3 与 grpcproxy 不再返回它,改用clientv3.IsConnCanceled(error)或status.FromError(error)。- 字段与配置更名:
etcdserver.ServerConfig.SnapCount/embed.Config.SnapCount更名SnapshotCount;embed.Config.LogOutput(string)更名LogOutputs([]string),配置 YAML 中log-outputs: default必须改为log-outputs: [default]。 wal包函数签名变化:Open/OpenForRead/Repair/Create均增加*zap.Logger参数;pkg/cors包移除;多个内部包(alarm、compactor、discovery、memberships 等)移入etcdserver/api/*。pkg/adt.IntervalTree从 struct 改为 interface(并修复了红黑树删除操作破坏黑高性质的问题)。- 发布分支版本号格式:
3.4.x-pre替代3.4.y+git(如3.4.5-pre)。
2.9 新增 Prometheus 指标
v3.4.0 一次性引入大量指标(etcd_debugging_* 均为实验性,可能随时变化):
- 网络/快照:
etcd_network_active_peers(按 Local/Remote 标签记录每对 peer 连接状态)、etcd_network_disconnected_peers_total、etcd_network_server_stream_failures_total(如{API="watch",Type="receive"} 1)、快照收发成功/失败/耗时/在途计数(etcd_network_snapshot_send/receive_*),etcd_snap_fsync_duration_seconds,etcd_network_peer_round_trip_time_seconds改为采样 leader 心跳并扩大直方图上限(0.8192s / 1.6384s / 3.2768s)。 - 服务器:
etcd_server_is_leader、etcd_server_id、etcd_server_version(替代 Kubernetes etcd-version-monitor)、etcd_cluster_version、etcd_server_go_version、etcd_server_health_success/failures、etcd_server_read_indexes_failed_total、etcd_server_heartbeat_send_failures_total、etcd_server_slow_apply_total、etcd_server_slow_read_indexes_total。 - 存储:
etcd_server_quota_backend_bytes(如2.147483648e+09表示 2GB 配额)、etcd_mvcc_db_total_size_in_use_in_bytes(defrag 后可达到的“在用水位”)、etcd_mvcc_db_open_read_transactions;etcd_mvcc_db_total_size_in_bytes − etcd_mvcc_db_total_size_in_use_in_bytes即为 defrag 可回收的字节数。etcd_disk_backend_defrag_duration_seconds、etcd_mvcc_hash_duration_seconds、etcd_mvcc_hash_rev_duration_seconds、backend commit 的 rebalance/spill/write 耗时。 - Lease:
etcd_debugging_lease_granted/revoked/renewed_total、etcd_debugging_lease_ttl_total。 - 弃用指标(v3.5 移除):
etcd_debugging_mvcc_db_total_size_in_bytes→etcd_mvcc_db_total_size_in_bytes;etcd_debugging_mvcc_put/delete/range/txn_total→ 去前缀版本。 - 其他:
etcd_debugging_mvcc_index_compaction_pause_duration_milliseconds直方图上限扩大(1.024s / 2.048s / 4.096s);gRPC proxy 的/metrics改为暴露真实 etcd server 端点(此前暴露的是 proxy 自身指标)。
2.10 etcdctl 与其他工具
- 新增
etcdctl member add --learner、etcdctl member promote;--password标志(支持用户名含:);user add --new-user-password。 - 新增
etcdctl check datascale、check perf(均可选--auto-compact、--auto-defrag)、defrag --cluster。 endpoint status新增 “raft applied index” 与 “errors” 字段;endpoint health支持--write-out并修复缺失换行。watch --interactive新增progress命令;修复etcdctl watch [key] [range_end] -- [exec-command...]解析 panic;修复 TLS 端点下的move-leader;snapshot save支持--command-timeout;discovery 场景剥离不安全端点。endpoint status的 StatusResponse 同步新增raftAppliedIndex、errors(如"etcdserver: no leader"、"NOSPACE"、"CORRUPT")、dbSizeInUse字段。- 新增
snapshot包,便于以库形式实现 snapshot save/restore 工作流。 - WAL 包新增
Verify函数做 WAL 内容损坏检查——当前仓库中该函数仍位于 server/storage/wal/wal.go。 - 工具:
etcd-dump-logs新增--entry-type(按 entry 类型过滤)与--stream-decoder(自定义解码器);release assets 新增SHA256SUMS(维护者团队分布全球,允许无签名密钥的校验发布)。 - Dockerfile 基础镜像从 Alpine 换到 Debian(3.4.18 时又进一步升级 bullseye 基础镜像以修复多个高危 CVE)。
2.11 v3.4.0 依赖升级(摘选)
bbolt 从 github.com/coreos/bbolt v1.3.1-coreos.6 迁到 go.etcd.io/bbolt v1.3.3;gRPC 从 v1.7.5 升到 v1.23.0;ugorji/go/codec 迁到 json-iterator/go;ghodss/yaml 迁到 sigs.k8s.io/yaml;gogo/protobuf v1.2.1;cmux v0.1.4;google/btree v1.0.0;prometheus/client_golang v1.0.0;grpc-gateway v1.4.1 等。编译使用 Go 1.12.9(含 1.12.8 安全修复),要求 Go 1.12+。
三、补丁版本演进:v3.4.1 ~ v3.4.45 时间线
以下按 changelog 原文逐版本覆盖(自新至旧),保留每条的实质内容,作为生产排障与补丁跟进的检索索引。
3.1 v3.4.38 ~ v3.4.45(近年维护期)
- v3.4.45(2026-06-01):EOL 版本,仅依赖变更——编译工具链升级到 go 1.25.10。
- v3.4.44(2026-05-01):修复 RBAC 授权绕过——嵌套在事务中的 Put 请求可通过
PrevKv或 lease 附加获得读访问(两个 PR 分别修复)。go 1.25.9。 - v3.4.43(2026-04-01):允许非 admin 用户获取成员列表与 alarms;修复开启 auth 时
etcdctl endpoint --cluster的回归。 - v3.4.42(2026-03-20):修复 read index 与 leader 切换的竞态;修复进程暂停(pause)导致的陈旧读;针对两个 CVE 的授权加固——多 API 未认证端点授权绕过(CVE-2026-33413)与嵌套事务绕过 RBAC 检查(CVE-2026-33343);go 1.25.8;升级
golang.org/x/net至 v0.51.0、gRPC 至 1.79.3 修复对应漏洞。 - v3.4.41(2026-02-13):clientv3 移除对 grpc-go Metadata 字段的使用;go 1.24.13(同时解决三个 Go 标准库 CVE)。
- v3.4.40(2025-12-17):日志中只打印 token 指纹而非原始 token;构建脚本使用
buildvcs=false,避免go version报告 pseudo-version;go 1.24.11;升级golang.org/x/crypto到 0.45.0 修复两个 CVE。 - v3.4.39(2025-11-11):构建侧使用
buildvcs=false;go 1.24.10。 - v3.4.38(2025-10-21):一批存储与 lease 修复——修复 watch close/cancel 竞态下 watcher gauge 双重递减;修复“watch 未来 revision 却收到旧事件”;改进
--quota-backend-bytes帮助信息;修复 applySnapshot 与 defragment 并发时可能损坏数据;拒绝-1revision 的 watch 请求以防止未压缩 etcd 上的异常重同步;修复 lease 已吊销时LeaseRenew仍可能返回成功。go 1.24.9;bbolt 升至 v1.3.12。 - v3.4.37(2025-04-15):仅依赖——
golang.org/x/netv0.36.0(修复 CVE-2025-22870);go 1.23.8。 - v3.4.36(2025-02-25):避免 bootstrap 期间调用
etcd.Close的 deadlock;修复在“与压缩请求同一 revision 打开的 watch”丢失 delete 事件;clientv3 修复KeepAlive使用不可比较类型的 Context 引发的 panic。go 1.23.6;x/cryptov0.35.0、x/netv0.34.0 修复相关 CVE。 - v3.4.35(2024-11-12):修复 watchserver 相关 goroutine 泄漏;修复 defragment 期间错误处理不当引发的 panic;defragment 出错时关闭临时文件。go 1.22.9。
3.2 v3.4.31 ~ v3.4.34(3.5 兼容性窗口)
- v3.4.34(2024-09-11):修复 lease renew 中
ensureLeadership引入的性能回归;压缩时若 tombstone 恰是压缩 revision 则保留;clientv3 用官方go fmt包保证 gRPC metadata 打印顺序;go 1.22.7;bbolt 1.3.11。 - v3.4.33(2024-06-13):grpc-proxy 修复 proxy 节点下线后 memberlist 不更新;go 1.21.11;bbolt 1.3.10。
- v3.4.32(2024-04-25):LeaseTimeToLive 在 leader 变更时不再报错;member id 不匹配时忽略 raft 消息;bootstrap 时更新 compaction 日志;新增
next-cluster-version-compatible=true允许新 server 加入 3.5 集群、允许从 3.5 降级时更新集群版本;修复 compaction 期间 panic 后 revision 回退。clientv3 在收到ErrGRPCLearnerNotSupported且 endpoints > 1 时自动重试;go 1.21.9。 - v3.4.31(2024-03-21):compaction 日志打印 backend 数据库大小与在用大小;忽略旧 leader 的 lease 撤销请求,修复 lease 被错误吊销;修复无事件 watch 不发送 progress 通知;修复 compaction 后的 watch 事件丢失;新增
next-cluster-version-compatible标志支持从 3.5 降级;clientv3 增加 backoff 与 retry 配置选项;bbolt 1.3.9、protobuf v1.33.0(修复 CVE-2024-24786)、logrus v1.9.3;构建侧支持配置CGO_ENABLED。
这一窗口(v3.4.31/v3.4.32)是3.4 与 3.5 集群混布/回滚的关键版本:若曾升级到 3.5 需要回退,3.4 侧必须至少到这两个版本才能正常加入。
3.3 v3.4.25 ~ v3.4.30
- v3.4.30(2024-01-31):修复因用错日志库导致的 nil 指针 panic;go 1.20.13;
x/cryptov0.17+ 修复 CVE-2023-48795。 - v3.4.29(2024-01-09):peer 通信禁用 HTTP 重定向跟随;新增 livez/readyz HTTP 端点;
be被覆盖为 nil 时的 panic 防护;help 输出补上遗漏的experimental-enable-lease-checkpoint-persist标志;snapshot 文件不再被 flock;go 1.20.12。 - v3.4.28(2023-11-23):auth 关闭时跳过从入站 context 读取 authInfo;golang.org/x/net v0.11.0 改用 round-robin 调度器后恢复默认写调度器;数据损坏检测加入集群 ID 检查防误报;Learner 支持 Snapshot RPC。clientv3:auth 被禁用时刷新失败会重置 auth token;简化 grpc dialer 用法;自研 balancer 替换为上游 gRPC 方案(消除 1.10 起弃用的自定义 balancer);修复
dial()访问cfg.Endpoints的竞态、单端点场景的 authority 头错误。bbolt 1.3.8;gRPC 升级 1.58.3,注意:gRPC server 会拒绝携带 Connection 头的请求(这是有客户端兼容影响的依赖变更)。 - v3.4.27(2023-07-11):修复刚做完 compaction 时 corruption check 报
ErrCompacted;auth 关闭或 admin 用户时 lease put 性能改进;stopServernil 指针修复。etcdctlsnapshot restore新增可选--bump-revision、--mark-compacted标志。go 1.19.10。 - v3.4.26(2023-05-12):LeaseTimeToLive 不再向无读权限的客户端返回 key(越权读修复)。go 1.19.9。
- v3.4.25(2023-04-14):本版引入两个新标志并修多个问题——
--tls-min-version/--tls-max-version:支持 TLS 1.3 的版本边界控制;--listen-client-http-urls:把 HTTP(gRPC gateway)服务与 gRPC 服务分离监听,从根本上免疫高读负载下 watch 流被饿死(starvation)的问题;- http2 frame 调度改为随机算法;
- 修复同地址同时启动安全/不安全 gRPC server 的数据竞争;auth 禁止创建空权限区间;wsproxy JSON 日志格式修复;
- 修复 CVE-2021-28235(认证成功后清除密码内存);
- 修复解析无 username/revision 的 JWT 时 panic;
- 修复成员重连从 leader 下载 snapshot 时 watch 响应“回到过去”;修复 progress notify 与流的同步问题。
- 推荐 Go 1.19+,编译用 1.19.8;Docker 镜像修复“所有 tag 都标记 amd64”的架构标注问题。
3.4 v3.4.20 ~ v3.4.24
- v3.4.24(2023-02-16):修复非启动 learner 被错误提升;count-only range 开销降低;RangeOptions.limit 下推到索引树减少内存;多并发 readTx 共享一个 txReadBuffer;zap 时间戳精度从毫秒对齐到微秒(格式
2006-01-02T15:04:05.999999Z0700);IPv6 地址比较统一格式。clientv3 修复可能向 watch 客户端发送重复事件;bbolt v1.3.7;grpc-gateway v1.9.5→v1.11.0;Docker 基础镜像从 base-debian11 换 static-debian11 并移除 busybox。 - v3.4.23(2022-12-21):corruption alarm 去掉 memberID;只读 txn nil 响应 panic 修复;依赖升级缓解多个高危漏洞(推荐 Go 1.17+,编译 1.17.13);clientv3 修复 CommonName 认证刷新 token 的段错误;Docker 镜像改用 distroless 基础镜像应对关键漏洞。
- v3.4.22(2022-11-02):corruption alarm 中 memberID 为 0 的修复;auth 场景下 watch 的 invalid token/old revision 错误;避免错误关闭 ID 为 0 的 watch;auth 从 snapshot 恢复时的数据一致性问题。netutil 的
URLStringsEqual加入无解析器的 URL 比较;clientv3 在 watch 流不可用时重试前加 backoff;grpc-proxy 新增--listen-cipher-suites可配置密码套件。 - v3.4.21(2022-09-15):修复单节点集群的 durability API 保证;nil 日志对象 panic;成员启动时 auth 数据未加载;etcdctl
move-leader多端点失败。 - v3.4.20(2022-08-06):
- 新增
etcd --max-concurrent-streams:限制每个客户端并发打开的 stream 数,默认math.MaxUint32(当前源码 server/embed/config.go 中该字段与默认值仍在,标志注册于 server/embed/config.go); - 新增
etcd --experimental-enable-lease-checkpoint-persist:lease checkpoint 持久化,配合修复“checkpoint 无法阻止 leader 变更后 TTL 重置”(注意:该实验特性在后续主分支中已被移除/演进,当前 main 分支源码中已搜索不到该标志,v3.4 分支行为以该版本为准); - rangePermCache 的读写锁使用修复;raft 层
MsgReadIndex推迟到本 term 首次 commit 之后、空 apply 请求下重发 ReadIndex、Grant 负 ID 导致 db 失同步的防护、NOSPACE 时放行非变更请求。 - clientv3 在 autosync 时过滤 learner 成员。
- 新增
3.5 v3.4.10 ~ v3.4.19
- v3.4.19(2022-07-12):排除同类型 alarm 被多个 peer 重复激活;Defrag 不再清空 backend 选项;从 snapshot 恢复 auth store 时 tokenProvider 未启用导致的 lease 泄漏;lease 撤销的 goroutine/channel 竞态与降 leader 后仍调度 checkpoint;clientv3 修复过期 token 不刷新;bbolt v1.3.3→v1.3.6;
x/crypto、yaml.v2(v2.4.0,修复 CVE-2019-11254)安全升级;Go 要求提升到 1.16+,依赖跟踪从 vendor 目录切换为 go modules(这是 3.4 线内的重要构建体系变更)。 - v3.4.18(2021-10-15):新增
etcd_disk_defrag_inflight指标;Docker 基础镜像升级 debian:bullseye 修复四个关键 CVE(含 glibc 整数溢出 CVE-2021-35942 等)。 - v3.4.17(2021-10-03):
etcdctl check datascale支持 https 端点;gRPC gateway 支持MaxCallRecvMsgSize;JWT 库从dgrijalva/jwt-go替换为golang-jwt/jwt;编译 Go 1.12.17。 - v3.4.16(2021-05-11):新增
--experimental-warning-apply-duration使 apply 耗时阈值可配置;--unsafe-no-fsync修复为仍会写出数据(大多数情况下避免损坏);range 响应大小日志不再 marshal,内存分配降低约 30%;health check 可按条件排除 alarm。 - v3.4.15(2021-02-26):服务端 health check 成功日志降为 debug 级;修复 64KB websocket 通知消息上限;fileutil 的
F_OFD_常量修复;gorilla/websocket v1.4.2。 - v3.4.14(2020-11-25):clientv3 修复 watch 重连后 auth token 失效(clientConn ready 时自动获取 token);修复 force-new-cluster 与 learner 并存时的 server panic;netutil 移除
DropPort/RecoverPort/SetLatency/RemoveLatency(仅旧版功能测试使用,移除以消除任意 shell 调用面);tools/etcd-dump-metrics加入输入校验防止任意 shell 执行。 - v3.4.13(2020-08-24):安全加固——etcd 使用已有目录且权限不符合要求时(Linux 700 / Windows 777)打 warning 日志。
- v3.4.12(2020-08-19):修复 slow writes 告警中的 server panic。
- v3.4.11(2020-08-18):
runtime.FDUsage调用模式优化;新增etcd --experimental-watch-progress-notify-interval使 watch progress 通知间隔可配置;clientv3 去除过量 watch cancel 日志;新增os_fd_used/os_fd_limit指标监控文件描述符。 - v3.4.10(2020-07-16):
- 新增
--unsafe-no-fsync:禁用所有 fsync(会丢数据),用于测试/开发时避免文件系统压力; - 新增
--auth-token-ttl定制 simple token 的 TTL; - raft logger 的 int64 转换 panic 修复;
- 破坏性行为:已存在的数据/证书目录会检查权限(Linux 700 / Windows 777),此前不检查。
- 新增
- v3.4.9(2020-05-20):WAL validate 补上缺失的 CRC 校验(此前缺失会导致 panic)。
- v3.4.8(2020-05-18):snapshot 保存的 checksum 完整性校验(etcdctl 与 clientv3);snapshot 收发日志改进;修复 WAL 与服务端 snapshot 不一致——此前 server 在持久化 raft hard state 之后、保存 snapshot 之前崩溃会导致 restore 失败;auth 包修复保存 consistent index 的数据损坏 bug;clientv3 侧新增
etcd_debugging_auth_revision指标。
3.6 v3.4.1 ~ v3.4.7
- v3.4.7(2020-04-01):latest index 超 100 万时的 compaction 性能改进;新增
etcd_wal_write_bytes_total指标。 - v3.4.6(2020-03-29):修复 follower 节点的 lease 内存泄漏。
- v3.4.5(2020-03-18):服务端记录
[CLIENT-PORT]/health检查日志;clientv3 修复WithRequireLeader(ctx)覆盖已有 context key 的元数据嵌入 bug;etcdctl member add防超时;etcd_server_client_requests_total指标新增type与client_api_version标签;gRPC proxy 修复 metrics handler 的 error panic。 - v3.4.4(2020-02-24):
- 修复关闭时 purge 文件循环等待的严重问题:此前 shutdown 期间可能误删所需 WAL 文件,导致启动时
etcdserver: open wal error: wal: file not found.;现在 purge 循环先于 raft 节点停止信号退出。 - 修复 defrag 损坏 bug;learner 提升时的 quorum 保护逻辑;peer corruption checker 在 peer mTLS 下可用。
- 新增
etcd_debugging_mvcc_total_put_size_in_bytes指标;修复etcd_debugging_mvcc_db_compaction_keys_total恒为 0 的 bug。 - auth:GRPC gateway 添加用户时的 NoPassword 检查修复;部分 auth 日志级别纠正。
- 修复关闭时 purge 文件循环等待的严重问题:此前 shutdown 期间可能误删所需 WAL 文件,导致启动时
- v3.4.3(2019-10-24):
etcd_cluster_version指标只保留 major.minor。 - v3.4.2(2019-10-11):
etcdctl member add防超时;etcdserver 的 range/put/compact 请求加入 tracing;client balancer 对多端点的 failover 修复(含 kube-apiserver 多成员 failover 证书校验、成员加入时的 IPv6 端点解析两类 k8s 相关问题)。 - v3.4.1(2019-09-17):新增
etcd_debugging_mvcc_current_revision、etcd_debugging_mvcc_compact_revision指标;embed.Config.ZapLoggerBuilder支持自定义 zap logger;gRPC v1.23.0→v1.23.1。
四、安全修复的演进脉络
从 changelog 可以提取出一条清晰的安全跟进线,生产环境可按“受影响组件 → 最低修复版本”建表跟进:
| 修复版本 | 内容 |
|---|---|
| v3.4.25 | CVE-2021-28235:认证成功后清除密码;无密码用户仅可 CommonName 认证(v3.4.0 引入) |
| v3.4.22 | auth 从 snapshot 恢复的数据一致性;watch invalid token/old revision 错误 |
| v3.4.19 | yaml.v2 v2.4.0(CVE-2019-11254)、x/crypto 安全升级 |
| v3.4.30 | x/crypto v0.17+(CVE-2023-48795) |
| v3.4.37 | x/net v0.36.0(CVE-2025-22870) |
| v3.4.40 | x/crypto 0.45.0(两个 2025 年 CVE);日志仅打印 token 指纹 |
| v3.4.42 | gRPC 1.79.3、x/net v0.51.0;服务端授权加固(两个 CVE:未认证端点绕过、嵌套事务绕过 RBAC) |
| v3.4.44 | 事务内 Put 的 PrevKv/lease 路径 RBAC 绕过修复 |
与之呼应的是 v3.4.0 一次性引入的防御面:--cipher-suites 密码套件白名单、--host-whitelist 防 DNS Rebinding、--cors 精确控制、TLS 1.3 版本边界(v3.4.25 的 --tls-min/max-version)。这些配置项的当前实现位置可参考 server/embed/config.go 中的标志注册段(pre-vote、host-whitelist、initial-election-tick-advance、max-concurrent-streams 等均在此注册并写入启动日志 server/embed/etcd.go)。
五、数据正确性类修复专题
changelog 中高频出现的一类修复直接关系数据正确性,值得单独索引(按主题归并):
- Compaction / revision:compaction 期间 panic 后 revision 回退(v3.4.32)、tombstone 恰为压缩 revision 时保留(v3.4.34)、compaction 后 watch 事件丢失(v3.4.31)、
ErrCompacted误报(v3.4.27)、revision 保留值解析错误(v3.4.0)。 - Watch:未来 revision 的 watch 收到旧事件(v3.4.38)、与压缩同 revision 打开的 watch 丢 delete 事件(v3.4.36)、重复事件(v3.4.24)、网络分区后 snapshot 恢复导致 watch 响应时间倒流(v3.4.25)、
mvccunsynced watcher restore 丢事件与 restore panic(v3.4.0)。 - Lease:单节点集群 durability 保证(v3.4.21)、follower 内存泄漏(v3.4.6)、负 ID grant 致 db 失同步(v3.4.20)、TTL 溢出防护(v3.4.0)、已吊销 lease 的 Renew 误报成功(v3.4.38)、过期 lease 未删 key(v3.4.0)。
- 存储 / 崩溃恢复:applySnapshot 与 defragment 并发损坏(v3.4.38)、defrag 损坏与临时文件未关(v3.4.4/v3.4.35)、WAL 与服务端 snapshot 不一致致 restore 失败(v3.4.8)、WAL validate 缺 CRC 校验(v3.4.9)、shutdown 误删 WAL(v3.4.4)。
- WAL 损坏自检:v3.4.0 引入的
Verify函数在 server/storage/wal/wal.go 中至今仍是etcd-dump-logs等工具做 WAL 损坏检查的入口,与 changelog 中 v3.4.9 补 CRC 校验、v3.4.28 集群 ID 检查形成一条完整的损坏检测演进链。
六、生产版本选择与升级建议
结合 CHANGELOG/README.md 与本文的逐版本梳理:
- 最低生产版本:README 明确建议生产环境至少使用 v3.4.22+(以及 v3.5.6+ 线)。低于 v3.4.22 的版本存在 auth 恢复一致性、watch 错误处理等未修复问题,不应作为生产基线。
- 已 EOL:v3.4.45 是 v3.4 最后一个补丁版本。仍在 v3.4 的集群,升级方向是 3.5/3.6 线;若因故需要 3.4 与 3.5 混布(例如从 3.5 回滚),确保 3.4 侧不低于 v3.4.31(
next-cluster-version-compatible标志可用)并按 v3.4.32 的集群版本更新逻辑操作。 - 跟进补丁的判断依据:对照本文第四节的 CVE 表与第五节的正确性修复表,凡涉及“授权绕过 / 数据损坏 / restore 失败”类修复的版本都应视为强制升级点;其余依赖升级版本(如各
Compile binaries using go 1.x条目)可结合内部 Go 工具链策略合并跟进。 - 升级前阅读顺序:CHANGELOG 头部指引从 CHANGELOG-3.3.md 回溯上一代变更;v3.4.0 的 breaking changes(第二节 2.8 节)必须在升级窗口内逐条核对——尤其是 etcdctl 默认 API=3、v2 store 默认关闭、
/v3beta端点、TLS 标志更名、容器 tag 规则与 Go 1.12+ 要求。 - 验证手段:升级后可以用 changelog 中反复出现的可观测性手段自检——
etcdctl endpoint status(含 raft applied index 与 errors 字段)、/livez、/readyz(v3.4.29 起)、/metrics中etcd_server_is_leader、etcd_cluster_version、etcd_mvcc_db_total_size_in_bytes/etcd_mvcc_db_total_size_in_use_in_bytes(差值即 defrag 可回收量)等指标,全部来自 v3.4.0 起新增的指标体系。
七、小结
CHANGELOG/CHANGELOG-3.4.md 完整记录了 etcd 3.4 线 45 个版本、跨越 2019-08 至 2026-06 的演进:v3.4.0 以 Learner、Pre-Vote、zap 日志、watch 分片、lease checkpointing 与大规模指标体系奠定架构;中间补丁版本持续修复 compaction/watch/lease/崩溃恢复等数据正确性问题,并跟进各依赖 CVE;v3.4.45 宣告 EOL。对运维者而言,这份 changelog 的价值在于:以版本号为锚点,能快速定位“我当前版本是否包含某修复/某 CVE 补丁”,并据此决定是打补丁还是直接升级主线分支。
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 StartedRust0623
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