为什么 Kubernetes 使用 etcd,而不是其他数据库
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| API | Application Programming Interface | 应用程序编程接口 |
| CAS | Compare-And-Swap | 比较并交换,基于条件的原子更新 |
| KV | Key-Value | 键值存储模型 |
| PV | Persistent Volume | 持久卷 |
| PVC | Persistent Volume Claim | 持久卷申领 |
| SQL | Structured Query Language | 结构化查询语言 |
| TTL | Time To Live | 存活时间;具体指缓存有效期或记录过期时间 |
Kubernetes 控制面需要可靠保存对象、处理并发修改,并持续通知组件状态变化。etcd 把一致性、条件事务、版本历史和 Watch 集成在同一个存储系统中,适合这类协调任务。其他数据库也能实现其中不少能力,但替换时必须满足整套存储语义与接口。
本文解释当前架构的适配关系,不把某一项优势当作 Kubernetes 历史选型的唯一原因。
1. Kubernetes 实际需要什么#
| 控制面需求 | etcd 提供的能力 | 解决的问题 |
|---|---|---|
| 多个 API Server 操作同一份状态 | Raft 多数派提交、线性一致读 | 在需要最新值时读取已提交状态,避免不同副本独立接受冲突写入 |
| 两个客户端同时更新对象 | 基于版本比较的原子事务(CAS) | 发现对象已被别人修改,避免旧数据覆盖新数据 |
| 控制器持续感知对象变化 | Revision、历史版本、Watch | 先读取状态,再从对应版本追踪变化,减少反复全量查询 |
| 按资源路径读取对象 | 键值与范围查询 | 保存序列化的 API 对象,不要求对象之间做 SQL JOIN |
| 少量节点故障后继续运行 | 复制、Leader 选举、持久化 | 多数成员可用时继续提交;失去多数时停止正常写入 |
这些能力是组合关系:只有持久化,没有并发控制和可靠变更追踪,还不够。etcd 的线性一致读与可选的较弱一致性读也不能混为一谈;Watch 有自己的顺序/恢复保证,并不等于“事件立即送达”。etcd API 保证
2. 用一次 Deployment 更新理解#
假设两个客户端都读取到副本数为 3、resourceVersion=R1 的 Deployment:
- A 提交副本数 5,携带 R1;更新成功,对象版本改变。
- B 用旧 R1 提交副本数 2;对于带版本前提的更新,API Server 返回
409 Conflict。 - B 重新读取对象,再决定是否继续修改;不能直接覆盖 A 的结果。
- 控制器通过 Kubernetes API 的 List/Watch 感知变化,逐步调整 ReplicaSet 和 Pod。
这里 resourceVersion 是客户端必须视为不透明字符串的版本标识,不应自行加一、解析或假设它永远等于 etcd Revision。若 Watch 所需历史已清理,客户端通常需处理 410 Gone,重新 List 后建立 Watch。Kubernetes API 语义
数据路径是 客户端/控制器 → API Server → 存储层 → etcd。控制器通常不直连 etcd;API Server 还可能通过 watch cache 提供读取,不能理解成每次 GET 都直接访问 etcd。
存储一致不等于业务状态瞬间一致:Deployment 更新成功只说明期望状态已保存,Pod 达到 5 个 Ready 仍需要调度、拉镜像和健康检查。Kubernetes 控制循环负责逐步收敛。
3. 为什么不直接换成其他数据库#
| 候选 | 已具备的相关能力 | 不能直接替换的原因 |
|---|---|---|
| MySQL / PostgreSQL | 事务、并发控制、持久化,可配置复制与高可用 | SQL 协议不是 etcd API;还需适配 Revision、List/Watch、历史清理及故障切换语义 |
| Redis | 快速 KV、原子操作、持久化选项 | 常见主从复制默认异步,故障切换可能丢失已确认写入;也不是 etcd 的版本化 Watch/事务接口 |
| ZooKeeper | 成熟的分布式协调、版本检查、Watch | znode、会话和 Watch 语义与 etcd 不同,不能只改连接地址 |
| etcd | 原生提供 Kubernetes 存储后端所需的接口与语义组合 | 仍需维护容量、磁盘延迟、多数派、备份和版本兼容 |
不能说“关系型数据库没有强一致性”。例如 PostgreSQL 支持同步复制,具体保证取决于配置及读取路径;替代成本在于完整适配与验证,而非“SQL 天生不可靠”。PostgreSQL 复制
Redis 的 WAIT 也不把常见异步复制系统直接变成强一致存储。ZooKeeper 同样能承担协调任务;其传统 Watch 是一次性触发,新版本也支持持久 Watch,因此“ZooKeeper 没有 Watch”是不准确的。Redis 复制说明、ZooKeeper Watch
4. Kubernetes 能不用 etcd 吗#
可以通过发行版支持的适配层实现,但不是直接给标准 API Server 填一个 MySQL 地址。
例如 K3s 支持外部 MySQL/PostgreSQL,Kine 将其适配为 Kubernetes 所需的部分 etcd API。Kine 不是完整的 etcd 通用替代品;是否可用于某个环境,需核对发行版、数据库版本和部署限制。K3s 存储选项、Kine 项目
企业评估替代方案时至少验证:并发更新冲突、List/Watch 连续性、数据库故障切换、已确认写入的保护、备份恢复、升级兼容和支持责任。已有数据库团队可以降低运维成本,但不能省掉这些验证。
5. 容易误解的边界#
- 3 节点不是任意 1 节点都能独立工作:需要 2 个投票成员组成多数派;网络分区时少数派不能继续正常提交写入。
- Kubernetes Lease 不等于 etcd Lease:前者是 Kubernetes API 对象,用于节点心跳、选主等;后者是 etcd 的键 TTL 机制,不能推导成“节点失联就自动删除 Pod”。Kubernetes Lease
- etcd 不负责存储业务数据:Pod/PVC 等对象在其中,PV 文件、订单数据库和镜像不在其中。
- 成员越多不代表写入越快:复制与多数派确认有成本;跨高延迟地域部署会影响控制面延迟。
继续实践:读写、Watch 与 Lease 实验、生产运维与恢复。