etcd生产运维与灾难恢复完整指南

etcd 是 Kubernetes 控制面的事实来源。Deployment、Secret、Lease、CRD和控制器状态最终都依赖它。etcd 进程仍在运行并不代表集群健康:磁盘同步延迟、空间配额耗尽、成员失去多数派或错误恢复,都可能让API写入停顿,甚至造成永久数据分叉。

本文面向自建或负责底层控制面的运维团队。托管Kubernetes通常不允许直接操作etcd,应使用云厂商提供的备份与恢复能力。所有成员变更、快照恢复和强制动作都必须先在同版本隔离环境演练。

一、先理解一致性与多数派

etcd 使用Raft复制日志,写入需要多数成员确认。常见奇数成员容错关系:

成员数 需要多数 可容忍永久故障
1 1 0
3 2 1
5 3 2

增加到偶数成员不会增加对应容错能力,例如4成员仍只能容忍1个故障,却增加复制开销。Kubernetes常见3或5成员。成员应分布在独立故障域,但网络往返和磁盘延迟必须满足控制面要求;跨越高延迟地域的单个Raft集群通常会牺牲写入可用性。

二、拓扑与硬件基线

  • 使用低延迟、可靠的本地SSD或明确保证fsync性能的块存储;
  • etcd数据盘与高I/O日志、容器层、备份压缩任务隔离;
  • CPU不能长期被控制面其他组件抢占;
  • 成员间网络稳定、低延迟、低丢包;
  • 时间同步、DNS和证书生命周期受监控;
  • 数据目录有容量预留,不依赖磁盘接近满时再扩容;
  • 快照写往独立故障域,不与数据盘同生共死。

etcd最敏感的往往不是顺序吞吐,而是尾部fsync延迟。虚拟化存储“平均很快”但周期性停顿,也会触发选主和请求超时。

三、TLS与访问边界

客户端和成员间通信均启用TLS,分别管理server、client和peer证书。证书包含正确SAN,私钥权限最小,并在到期前完成滚动轮换。不要为了处理证书错误临时改为明文监听公网或业务网卡。

export ETCDCTL_API=3
etcdctl --endpoints=https://10.0.0.11:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
  endpoint status --write-out=table

生产端点只对控制面和受控运维网络开放。快照包含Secret等敏感数据,必须加密、限制访问、记录下载和恢复操作。

四、日常健康检查不能只看进程

etcdctl --endpoints=https://10.0.0.11:2379,https://10.0.0.12:2379,https://10.0.0.13:2379 \
  --cacert=ca.crt --cert=client.crt --key=client.key \
  endpoint health --cluster

etcdctl --endpoints=https://10.0.0.11:2379,https://10.0.0.12:2379,https://10.0.0.13:2379 \
  --cacert=ca.crt --cert=client.crt --key=client.key \
  endpoint status --cluster --write-out=table

etcdctl --endpoints=https://10.0.0.11:2379 \
  --cacert=ca.crt --cert=client.crt --key=client.key alarm list

检查leader、Raft term、已提交和已应用索引、数据库大小、是否存在learner、错误和告警。不同成员索引短暂有差异属正常,但持续扩大需要调查网络或磁盘。

五、核心监控指标

重点关注:

  • leader变化和无leader时长;
  • 提交到应用延迟、proposal pending与failed;
  • WAL fsync和backend commit高分位延迟;
  • peer往返延迟和发送失败;
  • 数据库实际大小、总分配大小和配额比例;
  • gRPC请求速率、失败和慢请求;
  • 进程CPU、RSS、文件句柄和磁盘空间;
  • Kubernetes API Server请求延迟与etcd指标的时间关联。

告警不应只写“etcd down”。leader频繁变化、磁盘P99恶化、空间超过阈值和成员索引持续落后,都应在写入完全停止前处理。

六、定期快照与校验

snapshot="/backup/etcd/snapshot-$(date +%Y%m%d-%H%M%S).db"
etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=ca.crt --cert=client.crt --key=client.key \
  snapshot save "$snapshot"

etcdutl snapshot status "$snapshot" --write-out=table

快照任务应检查退出码、文件大小、revision和hash,再复制到独立存储。仅复制正在使用的数据目录并不等于一致快照。保留至少日、周、月多层恢复点,并监控最近成功时间是否满足RPO。

恢复演练必须使用快照副本,验证可以启动、成员健康、Kubernetes API可读写、关键CRD存在且Secret可解密。

七、历史版本、压缩与碎片整理

etcd保留键的历史版本以支持watch和历史读取,长期不压缩会持续增长。压缩删除旧revision的逻辑历史,但物理文件可能不会立即缩小;defrag才回收成员本地数据库的空闲页。

revision=$(etcdctl endpoint status --write-out=json | jq -r '.[0].Status.header.revision')
compact_to=$((revision - 10000))
etcdctl compact "$compact_to"

etcdctl --endpoints=https://10.0.0.11:2379 \
  --cacert=ca.crt --cert=client.crt --key=client.key defrag

生产应优先启用经过验证的自动压缩策略。defrag逐成员进行,一次只处理一个非leader成员并观察,再处理其他成员,最后视情况处理leader。它可能阻塞当前成员,不应全成员并行执行。

八、空间配额与NOSPACE告警

当后端超过配额时,etcd会触发NOSPACE告警并限制写入。处置步骤不是直接扩大配额:

  1. 确认各成员数据库和磁盘空间;
  2. 找出异常增长来源,例如大量Events、Lease、自定义资源或控制器热循环;
  3. 在满足watch保留需求的前提下compact;
  4. 逐成员defrag;
  5. 确认空间恢复后解除告警;
  6. 修复增长源并重新评估配额。
etcdctl alarm list
etcdctl alarm disarm

只有确认空间已实际释放且根因受控后才解除告警,否则写入很快再次停止。

九、成员替换的安全步骤

单成员永久损坏但仍有多数派时,优先替换而非全量恢复:

etcdctl member list --write-out=table
etcdctl member remove MEMBER_ID
etcdctl member add etcd-3 --peer-urls=https://10.0.0.13:2380

随后在新节点使用全新数据目录和命令返回的初始集群参数启动。不要把旧损坏目录原样挂回。一次只替换一个成员,等待其追平并通过健康检查后再进行下一步。

成员增删是集群配置变更,不要在失去多数派后继续随意remove。先确认剩余拓扑、备份和恢复方案。

十、证书轮换与滚动维护

轮换前确认新旧CA信任重叠、SAN完整、所有成员时间正确。建议:

  1. 备份快照与静态Pod清单;
  2. 更新一个非leader成员;
  3. 验证peer和client通信、索引追平;
  4. 逐成员滚动;
  5. 验证API Server连接;
  6. 观察完整业务周期后再移除旧信任。

不要同时重启超过容错数的成员。维护窗口内持续监控多数派和API请求。

十一、从快照恢复的核心原则

恢复快照会创建新的逻辑集群,而不是简单把文件复制回原目录。使用 etcdutl snapshot restore 为每个成员生成独立数据目录,明确成员名称、peer URL和initial-cluster。

etcdutl snapshot restore snapshot.db \
  --name=etcd-1 \
  --data-dir=/var/lib/etcd-restored \
  --initial-cluster=etcd-1=https://10.0.0.11:2380,etcd-2=https://10.0.0.12:2380,etcd-3=https://10.0.0.13:2380 \
  --initial-advertise-peer-urls=https://10.0.0.11:2380

为其余成员分别执行并使用对应name、data-dir和URL。停止旧集群、保留旧数据目录只读副本,切换静态Pod或服务配置后再启动。具体参数和revision处理以所用etcd版本官方恢复文档为准。

十二、Kubernetes恢复后的连锁效应

etcd还原到旧时间点后,现实世界可能已经变化:

  • 已删除的Pod、Job或Node对象重新出现;
  • 云负载均衡器、磁盘和IP与对象状态不一致;
  • Lease和领导选举回到旧状态;
  • ServiceAccount令牌、证书和Secret可能已轮换;
  • Operator可能依据旧spec再次执行外部动作;
  • GitOps会尝试把集群收敛到当前仓库状态。

恢复后先隔离外部写操作,检查控制器和Operator,再分阶段恢复。不能只看到API Server启动就宣布成功。

十三、失去多数派时的决策

失去多数派后不能通过启动一个旧副本安全“凑数”。先冻结所有变更并收集:存活成员、数据目录、最新快照、revision、证书、静态Pod配置和基础设施状态。

选择:

  • 能恢复原多数派:修复网络、电源或磁盘后让成员重新加入;
  • 原成员永久丢失:从已验证的最新快照恢复新集群;
  • 无有效快照:只能基于剩余数据和官方灾难恢复流程评估,必须接受可能的数据丢失。

不要让两组持有不同历史的成员同时对外服务,避免脑裂式数据分叉。

十四、性能异常排查

顺序:

  1. 对齐API Server延迟与etcd请求延迟;
  2. 检查leader变化、proposal和慢请求;
  3. 检查WAL fsync、backend commit和磁盘队列;
  4. 检查成员网络丢包、RTT和MTU;
  5. 检查CPU抢占、内存压力和宿主机停顿;
  6. 检查资源数量、Events和控制器热循环;
  7. 检查数据库大小、压缩与碎片;
  8. 在修复基础设施后再调超时或配额。

盲目提高heartbeat、election timeout或API超时可能掩盖基础设施问题,并延长真实故障发现时间。

十五、维护周期建议

周期 工作
持续 健康、leader、延迟、空间、磁盘与证书监控
每日 快照、状态校验、异地复制和失败告警
每周 容量趋势、慢请求、成员差异和异常资源增长复核
每月 隔离恢复抽检、权限和备份保留检查
每季度 完整控制面恢复、成员替换和证书轮换演练
升级前 快照、兼容矩阵、回滚和恢复验证

周期只是假设,实际频率由RPO、变更速度和合规要求决定。

十六、生产验收清单

  • [ ] 使用3或5个成员并跨独立故障域合理分布;
  • [ ] 数据盘fsync高分位延迟满足要求且有告警;
  • [ ] client和peer通信均启用TLS,证书受监控;
  • [ ] 每日快照已校验并复制到独立故障域;
  • [ ] 自动压缩和逐成员defrag流程经过验证;
  • [ ] NOSPACE、失去leader和索引落后有Runbook;
  • [ ] 成员替换一次一个并等待追平;
  • [ ] 恢复环境记录版本、证书、清单与启动参数;
  • [ ] 恢复后检查外部资源和控制器副作用;
  • [ ] 最近一次完整恢复演练满足RPO与RTO。

十七、官方参考

etcd运维的核心不是熟记命令,而是始终保护多数派、数据历史和可验证恢复点。任何“快速修复”若破坏这三项,都可能把短暂控制面故障变成不可逆的数据事故。

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-21 09:46:44

results matching ""

    No results matching ""