1. etcd 存储架构概述
在深入容量水位评估之前,必须先理解 etcd 的存储架构。etcd 是一个强一致性的分布式键值存储系统,其存储组件并非单一模块,而是由 Raft 共识层、状态机层 和 持久化层 三层协同构成。每一层对容量和性能的影响各不相同,水位评估必须分层进行。
1.1 etcd 整体架构
etcd 的架构可以抽象为三个核心层次:
| 层次 | 核心组件 | 主要职责 | 容量关注点 |
|---|---|---|---|
| 网络层 | gRPC Server / Client | 处理客户端请求、节点间 Raft 消息 | 连接数、请求 QPS、网络带宽 |
| 共识层 | Raft 模块 | 日志复制、Leader 选举、成员变更 | Raft 日志条目数、未提交日志量 |
| 存储层 | 状态机 (MVCC) + 后端 (Backend) | 键值读写、事务处理、持久化 | 数据总大小、历史版本数、boltdb 文件大小 |
关键认知: 容量水位评估不能只看 boltdb 文件大小。Raft 日志的堆积、MVCC 历史版本的膨胀,往往比数据本身更快耗尽磁盘空间或导致性能下降。
1.2 Raft 协议与存储的关系
Raft 协议是 etcd 一致性的基石,它与存储组件的交互遵循以下流程:
- 客户端写入:请求到达 Leader 节点。
- 日志追加:Leader 将操作封装为 Raft 日志条目,追加到本地日志存储(WAL)。
- 日志复制:Leader 并行向 Follower 发送日志条目,等待多数派确认。
- 日志提交:收到多数派确认后,Leader 将日志标记为已提交(Committed)。
- 状态机应用:Leader 将已提交的日志应用到内存状态机(treeIndex)和持久化存储(boltdb)。
容量启示: Raft 日志在未提交前会持续占用 WAL 磁盘空间。如果 Follower 节点响应慢或网络分区,Leader 的 WAL 会快速膨胀,这是水位评估中容易被忽略的“隐形容量消耗”。
1.3 存储组件分层
etcd 的存储组件从逻辑到物理分为三层,每一层都有独立的容量特征:
- 内存层 (treeIndex):B-tree 结构,维护所有 key 到版本号的映射。容量受 key 数量影响,通常占用内存较小,但 key 数量超过百万级时内存压力显著。
- 逻辑层 (MVCC):多版本并发控制,每个 key 的每次修改都会生成一个新版本。历史版本不主动清理时,会无限膨胀。
- 物理层 (Backend / boltdb):基于 BoltDB 的 B+tree 持久化存储。单个 boltdb 文件包含所有 key-value 数据及索引,文件大小直接对应磁盘容量。
1.4 各层容量特征对比
为了更清晰地理解容量评估的切入点,下表对比了三层存储组件的关键容量指标:
| 存储层 | 容量上限 | 主要消耗源 | 水位告警阈值 | 扩容/治理手段 |
|---|---|---|---|---|
| Raft WAL | 默认 5GB (可配置) | 未提交日志、慢 Follower 导致的日志堆积 | WAL 目录使用率 > 80% | 调整 --max-wal-files;排查 Follower 延迟 |
| MVCC treeIndex | 受内存限制 (建议 < 8GB) | Key 总数 (每个 key 约 200-300 bytes) | 内存占用 > 2GB 或 key 数 > 100 万 | 压缩历史版本 (compact);删除无用 key |
| BoltDB | 官方推荐 < 8GB,极限 < 100GB | 数据总量 + 历史版本 + 索引 | db 文件 > 4GB 或 > 磁盘 70% | 碎片整理 (defrag);调整 --auto-compaction-retention |
常见误区: 很多运维人员只监控 boltdb 文件大小,忽略了 WAL 日志堆积。当集群出现网络抖动时,WAL 可能在几分钟内写满磁盘,导致 etcd 进程 OOM 或节点被踢出集群。水位评估必须覆盖 WAL 和 BoltDB 两个维度。
1.5 存储组件协作流程
一次完整的写入请求在存储组件中的流转路径如下:
- 客户端 → Leader:Put 请求到达 Leader 的 gRPC 端点。
- Leader → WAL:将操作序列化为 Raft 日志条目,写入本地 WAL 文件。
- Leader → Follower:通过 Raft 协议将日志条目复制到 Follower 节点。
- Follower → WAL:Follower 收到日志后也写入本地 WAL。
- 多数派确认 → 提交:Leader 收到多数派确认后,将日志标记为已提交。
- 提交 → 状态机:Leader 将已提交日志应用到 treeIndex 和 boltdb。
- 返回客户端:写入成功响应返回给客户端。
这个流程中,步骤 2 和步骤 6 是容量消耗的关键点:WAL 写入是顺序 I/O,速度快但会持续占用磁盘;boltdb 写入是随机 I/O,且每次写入都会产生新的 MVCC 版本,导致 boltdb 文件持续增长。
容量评估实践: 在生产环境中,建议使用
etcdctl endpoint status 和 etcdctl endpoint db-size 命令定期采集各节点的 db 大小和 WAL 目录大小,并结合 --auto-compaction-retention 参数设置合理的历史版本保留策略,从源头控制容量膨胀。