[K8S小白问题集] - K8S为什么选择etcd而不是别的key-value DB?比如Redis

小白问:etcd是K8S核心组件,是一个key-value DB,为什么不用其它的KV DB?比如Redis就被广泛使用?或者Zookeeper是不是也干类似的活儿?

一、etcd 在 K8S 中的核心角色

K8S 的所有资源对象(Pod、Service、ConfigMap、Secret、Deployment、Node 等)在 etcd 中以扁平键值对形式持久化。apiserver 是唯一与 etcd 直接交互的组件,整个集群的读路径 (kubectl get)和写路径 (kubectl apply)都经过 etcd。

kubectl apply ──► apiserver ──► etcd (Raft 写入)


Controller/Scheduler/Kubelet
(通过 Watch 监听变化)

etcd 不仅是一个数据库,它是 K8S 控制平面的分布式共识中枢事件总线

二、etcd 核心技术架构详解

2.1 Raft 共识算法:CP 强一致

etcd 使用 Raft 实现分布式一致性,属于 CAP 理论中的 CP 系统(Consistency + Partition Tolerance)。

|---------------|-------------------------------------------------------------------|---------------------------------------------------|
| 机制 | 技术细节 | 对 K8S 的意义 |
| Leader 选举 | 集群启动或 Leader 故障时,Follower 在随机超时后发起投票,获得多数派(>N/2)选票者成为 Leader | 任何时候只有一个合法写入端,避免脑裂导致状态冲突 |
| 日志复制 | 写请求必须先写入 Leader 的 WAL(Write-Ahead Log),再复制到多数派 Follower,提交后才返回客户端 | K8S 的 kubectl create 在 etcd 层面保证:一旦返回成功,后续任何读都能读到 |
| 多数派原则 | 3 节点集群容忍 1 故障,5 节点容忍 2 故障 | 与 K8S Master 高可用架构天然匹配 |
| 线性一致性读 | 默认 quorum=true,读请求也走 Raft 确认,或利用 Leader Lease 保证不读到脏数据 | Controller 基于 Watch 做出的调度决策,不会基于过期视图 |

关键 :Raft 的强一致不是"配置参数可调",而是协议级强制。这与 Redis 的主从异步复制有本质区别。

2.2 MVCC(多版本并发控制):BoltDB/bbolt 存储后端

etcd v3 使用 bbolt (BoltDB 的 etcd 维护分支)作为底层存储引擎,这是一个纯 Go 编写的嵌入式 B+ 树 MVCC 数据库

etcd 键空间逻辑结构(扁平):
/registry/pods/default/nginx-xxx
/registry/services/default/kubernetes
/registry/nodes/node-01
/registry/deployments/prod-core/payment

bbolt 物理存储:
├── key:revision 序列化后的复合键(main revision + sub revision)
├── value:protobuf 编码的 KeyValue + 版本信息 + LeaseID
└── B+ 树索引:支持范围查询(Range)

MVCC 对 K8S 的关键支撑:

  1. 乐观并发控制 :每个写操作分配全局单调递增的 revision。K8S 的 resourceVersion 直接映射 etcd 的 revision,apiserver 用此实现乐观锁 (If-Match 语义),防止并发写冲突。
  2. 历史版本保留 :默认保留所有历史版本,支持 kubectl get --watch 和历史 List (带 resourceVersion=0 或具体版本号)。
  3. 快照与压缩(Compaction) :历史版本无限增长会撑爆磁盘,etcd 定期压缩(删除某 revision 之前的旧版本),但压缩期间不影响读写。

2.3 Watch 机制:K8S 事件驱动的基石

这是 etcd 最被低估、也最难被替代的能力。

K8S Controller 工作模式:

  1. List:启动时从 etcd 拉取全量资源(基于当前 revision)
  2. Watch:建立长连接,监听后续变化(从该 revision 之后)
  3. 事件驱动:收到 Watch 事件后,Controller 执行调谐(Reconcile)

etcd Watch 的技术实现:

  • 基于 MVCC 历史 :Watch 不是"轮询",而是基于 revision 的事件日志回溯。bbolt 中每个 revision 对应一个变更事件,Watch 请求从指定 revision 开始顺序扫描。
  • 流式 gRPC:etcd v3 使用 gRPC 双向流,单个连接可 Watch 多个 key/prefix,服务端事件主动推送。
  • 可靠性 :若客户端断开重连,可携带 revision 恢复,保证不丢事件(只要 revision 未被压缩)。
  • 范围 Watch :支持按前缀(prefix)Watch,如 Watch /registry/pods/default/ 下所有 Pod。

对 K8S 的意义 :Controller、Scheduler、Kubelet 全部依赖 Watch 实现最终一致的事件驱动架构。没有 Watch,K8S 控制平面将退化为轮询,apiserver 和 Controller 会被压垮。

2.4 事务与租约(Lease)

  • 事务(Txn) :etcd 支持基于 revision 的比较-更新原子操作(CAS)。K8S 用此实现:
    • kubectl apply 的乐观并发控制
    • EndpointSlice 的原子更新
    • Leader Election 的原子性(update if resourceVersion == x)
  • Lease(租约) :用于 TTL 机制,如 Node 心跳(NodeLease)。Kubelet 定期续租,若节点故障,Lease 过期后 etcd 自动删除对应 key,触发 Node Controller 驱逐 Pod。

三、为什么不用 Redis?

Redis 是优秀的内存数据结构存储,但它与 etcd 的设计目标存在架构级错位

3.1 一致性模型:AP vs CP

|----------|-------------------------------------|------------------------------------------------------|
| 维度 | etcd | Redis |
| 共识协议 | Raft(强一致,线性一致读) | 主从异步复制(默认)或 Redis Cluster(Gossip,最终一致) |
| 脑裂处理 | Raft 多数派保证只有一个 Leader,旧 Leader 自动降级 | 主从切换时,若网络分区,可能出现双主(需 Sentinel/Cluster 仲裁,但非严格多数派) |
| 写入语义 | 写入成功 = 多数派持久化 | 写入主节点成功即返回,异步复制到从节点(appendfsync everysec 也可能丢 1 秒数据) |

K8S 场景 :若用 Redis 存储 Pod 状态,网络抖动导致主从切换,Controller 可能读到旧视图,误判 Pod 已删除而重复创建,或漏掉调度事件。金融级 K8S 不可接受这种不确定性

3.2 持久化与可靠性

  • etcd :WAL + 定期快照,设计目标是高可靠持久化。etcd 的数据首先安全落盘,内存主要用于缓存和索引。
  • Redis:内存优先,持久化(RDB/AOF)是"备份机制"而非核心路径。AOF 每秒刷盘仍可能丢数据,RDB 是快照点恢复。

K8S 场景 :集群状态是 K8S 的"黄金数据",丢失 etcd 数据等于丢失整个集群的"大脑"。Redis 的内存数据库定位不适合作为唯一可信源

3.3 Watch 机制的根本差异

|-----------|--------------------------------|-----------------------------------------|
| 维度 | etcd Watch | Redis Keyspace Notifications |
| 设计目标 | 分布式系统的事件驱动核心 | 缓存失效通知、消息辅助 |
| 事件范围 | 支持前缀 Watch、历史 revision 回溯、断点续传 | 仅支持 key 级别或全局事件,无历史回溯能力 |
| 一致性保证 | 事件顺序与 revision 严格单调递增 | 无全局顺序保证,Pub/Sub 可能丢消息 |
| 性能模型 | 为"万级并发 Watch + 百万级 key"优化 | 开启 Keyspace Notifications 后性能下降显著,非核心设计 |

K8S 场景:Controller 需要可靠的事件流。Redis 的 Pub/Sub 或 Keyspace Notifications 既无历史回溯,也无全局顺序,无法满足 K8S List-Watch 语义。

3.4 数据模型与事务

  • etcd :扁平键空间 + 前缀范围查询 + 多键事务(Txn)。K8S 所有资源按 /registry/<resource>/<namespace>/<name> 扁平存储,依赖前缀 List 和范围 Watch。
  • Redis :丰富的数据结构(String/Hash/List/Set/ZSet),但无原生多键 ACID 事务 (Lua 脚本可原子执行,但无 MVCC 乐观锁语义)。Redis 的 WATCH/MULTI/EXEC 是乐观锁,但实现机制与 etcd 的 revision 比较完全不同。

K8S 场景 :K8S 的 resourceVersion 机制需要全局单调递增的版本号,Redis 无此概念。

3.5 架构定位差异

Redis 是缓存/数据结构服务器,etcd 是分布式共识存储。

K8S 需要的不是"快",而是**"在分布式环境下对状态变更达成共识,并可靠地通知所有观察者"。Redis 优化的是 内存访问延迟和丰富数据结构**,etcd 优化的是共识达成效率、事件通知可靠性、历史版本管理

四、为什么不用其他 KV 系统?

|---------------------|-------------------------------------------------------------------------------------------------------------------------|
| 系统 | 不适用原因 |
| ZooKeeper | 早期 K8S 曾考虑,但 ZK 的 ZAB 协议复杂、Java 生态重、Watch 模型是一次性触发(需重新注册,易丢事件)、数据模型是树形 znode 而非扁平键空间。etcd 专为 K8S 设计,API 更简洁(gRPC)、性能更优。 |
| Consul | 定位是服务发现 + KV,Raft 实现正确但 KV 层是附加功能,Watch 机制(Blocking Queries)基于索引但不如 etcd 的 revision 模型精确,且非 K8S 原生集成。 |
| TiKV | 分布式 KV(TiDB 底层),强一致但架构重(PD + TiKV 多节点),延迟高于 etcd,且设计目标是海量数据存储而非 K8S 的"小数据 + 高并发 Watch"。 |
| LevelDB/RocksDB | 嵌入式 KV,无分布式共识能力,单机使用。 |
| MongoDB/MySQL | 文档/关系数据库,非 KV 语义,无 Watch 机制,延迟高。 |

五、总结:etcd 的不可替代性

etcd 被 K8S 选中并持续依赖,不是因为"它是 KV 数据库",而是因为它同时满足四个刚性需求

  1. CP 强一致:Raft 保证集群状态在任何故障下不分裂、不丢失已确认写入。
  2. MVCC 历史版本 :支撑 K8S 的 resourceVersion 乐观并发控制、List-Watch 机制、历史查询。
  3. 可靠 Watch:基于 revision 的事件流,是 K8S 控制器模式的心跳。
  4. 高可靠持久化:WAL + 快照,数据安全优先于内存速度。

Redis 等系统在其设计域内是卓越的,但它们的一致性模型、持久化语义、事件机制、事务能力 与 K8S 控制平面的需求存在架构级不匹配。用 Redis 替代 etcd,相当于用跑车引擎驱动盾构机------单看马力数字无意义,工况完全不同。

相关推荐
小夏子_riotous2 小时前
Kubernetes学习路径——3. Kubernetes 1.25 高可用集群部署实战:从 Docker 到 Calico 全链路详解
linux·运维·学习·docker·容器·kubernetes·centos
bukeyiwanshui2 小时前
20260512 docker笔记
linux·运维·笔记·docker·容器
东北甜妹3 小时前
k8s特殊容器 和 调度管理
云原生·容器·kubernetes
AOwhisky3 小时前
Docker 学习笔记:网络篇
linux·运维·网络·笔记·学习·docker·容器
眷蓝天3 小时前
Kubernetes 特殊容器技术详解
云原生·容器·kubernetes
亚空间仓鼠4 小时前
Docker容器化高可用架构部署方案(五)
docker·容器·架构
Gc9umsbL14 小时前
Istio 架构全景解析:控制面 vs 数据面、核心组件与流量路径深度拆解
云原生·架构·istio
成为你的宁宁4 小时前
【K8s RBAC 基础详解及 Role、ClusterRole 实战案例】
kubernetes·rbac
步步为营DotNet4 小时前
探索.NET 11:ASP.NET Core 10 云原生应用开发实践
云原生·asp.net·.net