etcd 深度解析:Kubernetes 的分布式大脑

etcd 深度解析:Kubernetes 的分布式大脑

1. etcd 是什么

etcd 是一个强一致性、高可用的分布式键值存储,是 Kubernetes 集群的唯一持久化存储后端。集群的所有状态数据——Pod、Service、ConfigMap、Secret、节点信息等——全部存储在 etcd 中。

etcd 的名字来源于 Unix /etc 目录(存储配置)+ d(distributed,分布式)。

2. 核心特性

特性 说明
强一致性 基于 Raft 算法,线性一致读写
高可用 奇数节点集群,容忍 (n-1)/2 节点故障
Watch 机制 实时监听 key 变化,驱动控制器
MVCC 多版本并发控制,支持历史版本查询
Lease TTL 租约机制,用于节点心跳
事务 原子性 CAS 操作

3. Raft 共识算法

etcd 使用 Raft 算法保证分布式一致性。

3.1 节点角色

1
Leader(领导者)  ←→  Follower(跟随者)  ←→  Candidate(候选者)
  • Leader:处理所有写请求,定期发送心跳
  • Follower:被动接收日志,响应 Leader 心跳
  • Candidate:选举期间的临时状态

3.2 Leader 选举流程

1
2
3
4
1. Follower 超时未收到心跳 → 转为 Candidate
2. Candidate 递增 Term,向所有节点发送 RequestVote RPC
3. 获得多数票(>n/2)→ 成为 Leader
4. Leader 开始发送心跳,其他节点回退为 Follower

3.3 日志复制流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Client Write


Leader 追加日志条目(uncommitted


并行发送 AppendEntries RPC 给所有 Follower


多数节点确认 → Leader commit 日志


通知 Follower commit → 应用到状态机


返回客户端成功

3.4 脑裂保护

Raft 通过 Term(任期) 机制防止脑裂:

  • 每次选举 Term 递增
  • 节点只接受 Term ≥ 自身 Term 的消息
  • 旧 Leader 收到更高 Term 消息后自动降级

4. MVCC 数据模型

etcd 使用 MVCC(Multi-Version Concurrency Control) 存储数据。

4.1 存储结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────┐
│ BoltDB(底层存储引擎) │
│ │
│ keyIndex(内存索引) │
│ ┌─────────────────────────────────────┐ │
│ │ key → [{revision: 1, ...}, │ │
│ │ {revision: 5, ...}] │ │
│ └─────────────────────────────────────┘ │
│ │
│ backend(磁盘存储) │
│ ┌─────────────────────────────────────┐ │
│ │ (revision) → (key, value, lease) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

4.2 Revision(版本号)

每次写操作都会生成一个全局递增的 revision

1
2
3
4
5
# 查看当前 revision
etcdctl endpoint status --write-out=json | jq '.[0].Status.header.revision'

# 查看 key 的历史版本
etcdctl get /registry/pods/default/nginx --rev=100

4.3 Compaction(压缩)

随着时间推移,历史版本会占用大量空间,需要定期压缩:

1
2
3
4
5
# 压缩到指定 revision
etcdctl compact 1000

# 碎片整理
etcdctl defrag

5. Watch 机制

Watch 是 Kubernetes 控制器模式的基础。

5.1 工作原理

1
2
3
4
5
6
7
8
9
Client                    etcd
│ │
│── Watch(key, rev=100) ──▶│
│ │ 监听 rev > 100 的变化
│ │
key 发生变化(rev=105) │
│◀── WatchEvent ──────────│
│ │
│ 继续监听... │

5.2 Watch 的高效实现

etcd 维护一个 watcherGroup,按 key 和 key 前缀分组:

1
2
3
4
5
6
7
8
// 伪代码:Watch 实现
func (s *store) Watch(key string, startRev int64) Watcher {
w := newWatcher(key, startRev)
s.watcherGroup.add(w)
// 推送 startRev 之后的历史事件
s.syncWatchersLoop(w)
return w
}

5.3 Kubernetes 中的 Watch

1
2
3
4
5
6
kube-apiserver ──Watch──▶ etcd

│ 缓存到 Watch Cache(内存)


各控制器 ──ListWatch──▶ apiserver(不直接访问 etcd)

6. Lease(租约)机制

Lease 用于实现 TTL 和节点心跳:

1
2
3
4
5
6
7
8
# 创建 5 秒 TTL 的租约
LEASE_ID=$(etcdctl lease grant 5 | awk '{print $2}')

# 绑定 key 到租约
etcdctl put /nodes/node1 "alive" --lease=$LEASE_ID

# 续约(keepalive)
etcdctl lease keep-alive $LEASE_ID

Kubernetes 中 kubelet 通过 Lease 对象向 apiserver 汇报心跳,替代了早期的 Node Status 更新方式,大幅降低了 etcd 写压力。

7. Kubernetes 中的 etcd 数据结构

1
2
3
4
5
6
7
8
9
10
11
12
# 查看所有 key(需要在 etcd pod 内执行)
etcdctl get / --prefix --keys-only

# 典型的 key 结构
/registry/pods/{namespace}/{name}
/registry/services/{namespace}/{name}
/registry/deployments/{namespace}/{name}
/registry/nodes/{name}
/registry/secrets/{namespace}/{name}
/registry/configmaps/{namespace}/{name}
/registry/events/{namespace}/{name}
/registry/leases/{namespace}/{name}

8. 生产运维最佳实践

8.1 集群规模

集群规模 etcd 节点数 说明
开发/测试 1 无高可用
生产小规模 3 容忍 1 节点故障
生产大规模 5 容忍 2 节点故障

不推荐 7 节点以上,写性能会显著下降。

8.2 硬件要求

1
2
3
4
5
# 生产推荐配置
CPU: 4 核以上(etcd CPU 密集型)
内存: 8GB 以上
磁盘: SSD,IOPS > 3000(etcd 对磁盘延迟极敏感)
网络: 低延迟,节点间 RTT < 10ms

8.3 关键参数调优

1
2
3
4
5
6
7
# etcd 启动参数
--heartbeat-interval=100 # 心跳间隔(ms),默认 100
--election-timeout=1000 # 选举超时(ms),默认 1000
--quota-backend-bytes=8589934592 # 存储配额 8GB
--auto-compaction-mode=periodic
--auto-compaction-retention=1h # 每小时自动压缩
--max-request-bytes=10485760 # 最大请求 10MB

8.4 备份与恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 备份 snapshot
ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d).db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key

# 验证 snapshot
etcdctl snapshot status /backup/etcd-20260101.db --write-out=table

# 恢复
etcdctl snapshot restore /backup/etcd-20260101.db \
--data-dir=/var/lib/etcd-restore \
--name=etcd-1 \
--initial-cluster=etcd-1=https://10.0.0.1:2380 \
--initial-advertise-peer-urls=https://10.0.0.1:2380

8.5 监控指标

1
2
3
4
5
6
7
# etcd 关键监控指标
etcd_server_leader_changes_seen_total # Leader 切换次数(应接近 0)
etcd_disk_wal_fsync_duration_seconds # WAL fsync 延迟(应 < 10ms)
etcd_disk_backend_commit_duration_seconds # 后端提交延迟(应 < 25ms)
etcd_network_peer_round_trip_time_seconds # 节点间 RTT
etcd_mvcc_db_total_size_in_bytes # 数据库大小
etcd_server_proposals_failed_total # 提案失败次数

9. 常见问题排查

9.1 etcd 空间不足

1
2
3
4
# 症状:Error: etcdserver: mvcc: database space exceeded
# 解决:
etcdctl compact $(etcdctl endpoint status --write-out="json" | jq '.[0].Status.header.revision')
etcdctl defrag --endpoints=https://127.0.0.1:2379

9.2 Leader 频繁切换

1
2
3
4
5
6
7
8
# 检查磁盘 IO 延迟
iostat -x 1 10

# 检查网络延迟
ping <etcd-peer-ip>

# 适当增大选举超时
--election-timeout=5000

9.3 集群无法选出 Leader

1
2
3
4
5
6
# 检查节点数是否满足 quorum(多数派)
# 3 节点集群需要至少 2 节点存活
# 5 节点集群需要至少 3 节点存活

# 紧急恢复:强制单节点模式(仅用于灾难恢复)
etcd --force-new-cluster

10. 总结

etcd 是 Kubernetes 的”大脑存储”,其稳定性直接决定集群的可用性。核心要点:

  1. Raft 保证一致性:所有写操作经过 Leader,多数派确认后提交
  2. MVCC 支持 Watch:版本号机制让控制器能高效感知变化
  3. Lease 实现心跳:轻量级的节点存活检测
  4. 生产必须 3/5 节点:保证高可用和容错
  5. SSD 是必须的:磁盘延迟直接影响 Raft 性能

etcd 深度解析:Kubernetes 的分布式大脑
https://k8s.chucz.asia/etcd深度解析/
作者
K8s Engineer
发布于
2026年1月3日
许可协议