
上一篇【第60篇】API Server深度解析——K8s的“总控制器“是怎么把请求玩弄于股掌的下一篇【第62篇】Controller Manager——K8s的自动驾驶仪摘要如果说API Server是K8s的前台那etcd就是公司的档案室保险柜——而且是所有数据的唯一真源。你在K8s里创建的一切——每一个Pod、Service、ConfigMap、Secret、PV甚至每个节点的状态——最终都序列化进etcd。如果etcd的数据没了你的集群就失忆了API Server还在但它啥都不记得了等于一个全新的空集群。正因为etcd这么重要它用了Raft共识算法来保证数据不丢持久化、数据一致所有节点看到相同内容、高可用挂几个节点还能工作。这篇文章讲清etcd的地位、Raft怎么干活、它的KV结构以及最实用的——怎么备份和恢复。一、etcd在K8s里的地位1.1 唯一真源【etcd K8s 的唯一持久化存储】 所有资源的最终归宿 Pod ─┐ Service ─┤ ConfigMap ─┼──► 序列化(JSON) ──► etcd Secret ─┤ (key-value) Node状态 ─┘ ... API Server: • 读: 从etcd取 • 写: 写进etcd • 缓存: 内存watch cache(加速读但不是真源) ⚠️ 记忆口诀: etcd没了 集群失忆 API Server可以重启etcd的数据不能丢要点K8s里没有任何其他组件持久化状态。kubelet本地的Pod状态、调度器的缓存都是易失的。只有etcd是铁打的存储。这也是为什么生产集群etcd必须跑在专用、高速SSD、低延迟的机器上且至少要3副本5副本更佳。1.2 部署拓扑【etcd 集群拓扑(奇数节点)】 为什么奇数Raft选主要多数派(quorum) 3节点: 允许挂1个 (1/3) 5节点: 允许挂2个 (2/5) 4节点: 允许挂1个 (和3节点一样能力但多花一台) → 所以不用偶数 ┌────────┐ ┌────────┐ ┌────────┐ │ etcd-0 │◄─►│ etcd-1 │◄─►│ etcd-2 │ ← 两两互联Raft复制 └────────┘ └────────┘ └────────┘ ▲ ▲ ▲ └────────────┼────────────┘ ▼ API Server (连所有etcd节点)二、Raft共识算法2.1 选主与日志复制【Raft 三个核心角色】 Leader (领导者): 唯一处理写请求把日志复制给Follower Follower (跟随者): 被动接收日志参与投票 Candidate (候选者): 选主时的临时状态 ┌─────────────────────────────────────────────┐ │ 写流程(客户端→Leader): │ │ 1. 客户端发写请求给Leader │ │ 2. Leader追加到自己的日志(Entry) │ │ 3. Leader复制日志给所有Follower │ │ 4. 多数派(quorum)确认收到 → Leader提交 │ │ 5. 通知Follower也提交 │ │ 6. 返回客户端成功 │ │ │ │ 关键: 只有多数派确认了才叫提交 │ │ → 保证即使少数节点挂了数据也不丢 │ └─────────────────────────────────────────────┘2.2 为什么Raft强一致场景行为Leader挂了剩余Follower选新Leader(任期term1)继续服务网络分区少数派分区无法选主/写(防止脑裂)日志落后新Leader强制Follower追平自己的日志读请求默认从Leader读(保证强一致)或只读模式(可能稍旧)要点Raft的精髓是多数派存活就能工作。3节点允许挂1个、5节点允许挂2个。但它要求节点间网络延迟低——如果etcd节点跨地域部署、延迟高Raft的提交会卡顿整个K8s变慢。所以etcd节点一定要放同一个机房、同高速网络。三、etcd的数据结构3.1 一切皆在 /registry 下【etcd 的 Key 结构】 /registry/ ├── pods/ │ ├── default/nginx-abc123 → Pod的JSON │ └── kube-system/etcd-0 ├── services/ │ ├── spec/default/my-svc │ └── endpoints/default/my-svc ├── configmaps/default/my-config ├── secrets/default/my-secret ├── deployments/apps/default/my-deploy └── ... → 你可以在etcd里直接看到所有资源(这就是为什么etcd要加密!)# 直接看etcd里的key (用etcdctl)ETCDCTL_API3etcdctl\--endpointshttps://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\get /registry/pods/default/nginx-abc123 --print-value-only# 输出: {kind:Pod,apiVersion:v1,...} ← 序列化的Pod四、性能调优4.1 两个关键参数【etcd 性能的两个命门】 1. 磁盘IO (最重要!) etcd对磁盘延迟极其敏感 → 必须用 SSD/NVMe绝不用HDD → 延迟 10ms 集群就开始抽风 2. 数据库大小 (配额) 默认配额 2GB超了etcd就拒绝写入 → 大集群要调大: --quota-backend-bytes8589934592 (8GB) 3. 历史压缩 (compaction) etcd保留所有历史版本(为了watch) → 历史太多数据库膨胀 → 要定期压缩: etcdctl compact revision → 配合 defrag 真正回收空间# 看etcd性能关键指标ETCDCTL_API3etcdctl endpoint status --write-outtable# | ENDPOINT | ID | VERSION | DB SIZE | ... |# DB SIZE 持续增长 → 该压缩了# 压缩碎片整理ETCDCTL_API3etcdctl compact$(ETCDCTL_API3etcdctl endpoint status-wjson|...)ETCDCTL_API3etcdctl defrag五、备份与恢复——保命技能5.1 快照备份这是运维K8s最关键的命令没有之一# 创建快照(在线不影响运行)ETCDCTL_API3etcdctl snapshot save /backup/etcd-$(date%F).db\--endpointshttps://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# 验证快照完整性ETCDCTL_API3etcdctl snapshot status /backup/etcd-2026-07-28.db-wtable# 显示: 数据库大小、revision、总key数、是否被截断5.2 从快照恢复# 恢复流程(灾难恢复):# 1. 停掉所有 API Server (kubectl不可用时用systemctl)# 2. 用快照恢复etcd数据ETCDCTL_API3etcdctl snapshot restore /backup/etcd-2026-07-28.db\--data-dir/var/lib/etcd-restore\--nameetcd-0\--initial-clusteretcd-0https://127.0.0.1:2380\--initial-cluster-tokenetcd-cluster\--initial-advertise-peer-urlshttps://127.0.0.1:2380# 3. 把恢复的数据目录替换原目录# 4. 重启etcd和API Server# 5. 集群复活所有资源回到快照时刻的状态要点etcd快照是K8s的后悔药。生产环境务必定期自动备份CronJob或Velero见第082篇并且定期演练恢复——很多人备份了但从没试过恢复真出事时发现备份是坏的。记住不演练的备份等于没备份。本篇小结etcd是K8s唯一的持久化真源所有资源最终都序列化进它。它用Raft保证强一致和高可用——3节点可挂1个、5节点可挂2个但要求低延迟网络同机房、SSD。数据按/registry/资源类型/ns/名组织所以etcd必须加密。性能命门是磁盘IO和数据库大小记得调大配额定期compact/defrag。最关键的运维技能是etcdctl snapshot save/restore——定期备份、定期演练恢复这是集群失忆后的唯一救命稻草。下篇讲Controller Manager——K8s的自动驾驶仪。上一篇【第60篇】API Server深度解析——K8s的“总控制器“是怎么把请求玩弄于股掌的下一篇【第62篇】Controller Manager——K8s的自动驾驶仪