AI时代的Kubernetes教程36招-第30招-etcd为什么是集群生命线,备份与灾难恢复到底怎么做?

etcd 备份恢复实战:集群状态、健康检查与容量治理

备份跑通一次不算本事,恢复成功才算交付。

[读者] 用 kubeadm 维护自建集群的运维与 SRE
[痛点] 备份脚本天天绿,没人验证过快照能不能恢复
[现在读] 一次误删对象、一次磁盘抖动,就足以让控制面集体超时
[读完] 能独立完成 etcd 健康检查、快照备份、恢复演练与容量治理
[旧方案] cron 定时执行 snapshot save,文件堆在本机目录
    |
    v
[新需求] 业务要求可证明的回滚能力,误删对象要能恢复
    |
    v
[冲突] etcd 里只有 API 对象,证书、kubeadm 配置、应用数据都不在里面
    |
    v
[后果] 数据恢复了,集群拼不回来,业务库依旧裸奔

我是老李,这几年一直在带自建 Kubernetes 平台的运维和稳定性。集群干净利落:kubeadm 拉起来的三个控制面,stacked etcd,etcd 以 static pod 的形式由 /etc/kubernetes/manifests/etcd.yaml 描述,数据目录是 /var/lib/etcd/。

备份方案也干净利落得有点天真:一台机器上的 cron,每天凌晨跑一次 etcdctl snapshot save,产物堆在 /var/backups/etcd 下。跑了两年,目录里躺着几百个 .db 文件,看起来非常安全。

转折来自一个再普通不过的需求:同事误删了某个命名空间下的 ConfigMap,需要回滚。按流程,这是备份该发光的时刻。结果我们从下午折腾到深夜,才承认一个事实——我们备份的是 etcd,不是集群。

第一个问题:etcd 里到底存了什么,又没存什么?

第二个问题:手上有一个昨天的快照文件,凭什么认为它今天能恢复出一个能用的集群?

第三个问题:如果恢复出来的集群缺证书、缺 kubeadm 配置,业务数据库也从来不在快照里,这次恢复到底算成功还是失败?

01、故事

演练定在一个周五下午。为了不碰线上,我们把上个月的一份快照拷进隔离环境,准备把它恢复成一套能承载业务的可运行集群。

我们的任务是:证明这份快照在真正需要的时候,能变成一套可用的控制面。

第一关就卡住了。手边 etcdctl 的版本比集群里 etcd 的版本新,快照相关的子命令归属已经变了,检查快照与执行恢复的动作被挪到了另一个二进制上。我们对着帮助信息翻了半小时,才明白不是语法写错了,而是工具换了。这里的具体版本对应关系,需按当前官方文档核验。

第二关更微妙。restore 出来的数据目录放好了,etcd.yaml 里的 --data-dir 和 volume hostPath 也改对了,etcd Pod 顺利起来,endpoint status 三个成员全绿。但 kube-apiserver 起不来——我们把 etcd 的数据搬回来了,却没把 /etc/kubernetes/pki 一起搬过来。集群没有身份,等于没有集群。

第三关是确认边界。即便控制面重新开口说话,业务数据也不在快照里。等式的另一半在 MySQL、Redis 和对象存储上,它们的备份链路跟 etcd 完全是两条线,谁也替不了谁。

那一天真正学到的不是命令,而是恢复的定义:恢复一个集群,等于恢复数据、身份、配置三件套,etcd 快照只覆盖了第一件里最核心的一部分。

快照只存对象
身份另需归档
恢复先问边界
演练才算备份

02、问题

旧方案失效的地方,不是备份没跑,而是它只有一条腿。

它做的事是:每天把 etcd 的数据抓下来,存到本机目录。它没做的事是:证明这份数据可用,归档恢复所需的身份与配置,观测 etcd 自身的健康与容量,说明业务数据的边界在哪里。

业务影响很直接:RTO 无法承诺,回滚能力无法证明。业务方问一句多久能恢复,我们只能回答看情况。

技术表现则集中在五点。第一,备份脚本用管道和容错符号包着,失败和成功在退出码上不可区分。第二,快照只是被创建,从未被校验,更没有在隔离环境里恢复过。第三,证书、kubeadm 配置、加密配置这些恢复必需件散落在不同机器上,没有同批次归档。第四,etcd 的成员数、quorum 状态、磁盘 fsync 延迟、DB SIZE 增长全都没有观测。第五,应用数据库被默认在 Kubernetes 里,实际上它不在 etcd 里。

于是我们把完成标准写成可验证的几条,而不是口号:

  1. 每份快照都能被独立校验,能读出 revision、键数量与文件大小,校验不过视为备份失败。
  2. 归档必须同批次包含快照、/etc/kubernetes/pki 全量、kube-system 下的 kubeadm-config,以及加密配置等恢复必需件。
  3. 每个季度在隔离环境完成一次恢复演练,产出可用的 kube-apiserver 与可注册的节点,演练记录留档。
  4. 三个成员的 endpoint health 与 endpoint status 有定期巡检和告警,leader 变更次数可观测。
  5. 恢复手册第一页明确写出:应用数据库与 PV 内的数据不在 etcd,走独立备份。

备份不等于恢复
成功不等于可用
数据不等于集群
边界先说清楚

03、原理

先把 etcd 在 Kubernetes 里的角色钉死:它是集群唯一的持久化真源。你创建的 Pod、Deployment、Service、Secret、ConfigMap、CRD、Lease、Event,最终都落在这里。kube-apiserver 是唯一直接读写它的组件,其他组件都是通过 apiserver 间接读写的。

反过来同样重要:业务数据不在 etcd。etcd 里可能存着数据库的连接串(通常放在 Secret 里),但表里的行、对象存储里的文件、PV 里的数据,一个字节都不在 etcd。把 etcd 快照当成全量备份,是绝大多数恢复事故的起点。

接着是 member 与 quorum。etcd 用 Raft 复制日志,一次写要拿到多数派确认才算提交。三个成员的多数派是二,所以能容忍一个成员掉线;四个成员的多数派是三,容忍度仍然只有一个,却多了同步成本与选举复杂度。成员数不是越多越好,奇数才有意义。

然后是 WAL 与 snapshot。写请求先追加进 WAL,并且要求 fdatasync 落盘之后才对外可见;内存中的状态机定期把全量状态写成 snapshot,随后截断旧的 WAL 段。这条路径决定了 etcd 的性能特征:它对 CPU 和网络带宽其实不敏感,对磁盘的 fsync 尾延迟极其敏感。

反直觉判断:控制面的体感可用性,往往由磁盘尾延迟而不是 CPU 使用率决定。一次几十毫秒的 fsync 尖刺,会直接放大成 apiserver 的请求超时;如果尖刺持续到超过 election-timeout,leader 就会被换掉,客户端看到的是短暂的请求风暴。

再分清 compact 与 defrag,这两个词经常被混着说。compact 删除的是某个 revision 之前的可见历史,释放的是逻辑空间;defrag 才会重写底层的存储文件,把空洞真正还给文件系统。只 compact 不 defrag,DB SIZE 依旧只涨不跌。而且 compact 可以在线做,defrag 会让被操作的成员在期间短暂不响应请求,必须串行、避开高峰。

最后是健康检查的判据。命令层面看 endpoint health 与 endpoint status;指标层面看是否有 leader、leader 变更次数、WAL fsync 与 backend commit 的延迟分布、DB 总大小与在用大小。命令给你一次快照,指标给你一条趋势,两者缺一不可。

写入先落 WAL
提交要等落盘
尾延迟定成败
偶数不加容错

04、架构

[输入] kubectl 与控制器发来的写请求
    |
    v
[模块] kube-apiserver -> etcd member(Raft leader)
    |
    v
[数据/状态] WAL 追加 + 状态机 snapshot + bbolt 存储文件
    |
    v
[处理] compact / defrag / snapshot save / snapshot restore
    |
    v
[输出] 可用的控制面 + 同批次归档(快照 + PKI + kubeadm 配置)

这套架构的边界很清楚。第一层边界在写入路径:所有变更都经过 apiserver,所以 etcd 的一致性等价于集群的一致性,绕过 apiserver 直接写 etcd 等于自毁。第二层边界在数据范围:etcd 只持有 API 对象,业务数据与 PV 数据在它之外。第三层边界在恢复路径:快照只提供数据,证书提供身份,kubeadm 配置提供拓扑与参数,三者齐备才能拼出集群。

收益是显而易见的:快照是原子的、可校验的、与版本号绑定的,恢复出的状态是一个明确的时间点,不需要对上千个对象逐个做反向操作。

代价也必须说清楚:快照是整库级别,不能只恢复一个命名空间;恢复是多成员动作,参数必须对齐;defrag 有短暂的可用性代价;恢复演练本身要占用一套隔离资源。

适用条件是:你用的是 kubeadm 这类可复现的安装方式,证书与配置有明确位置,且能接受恢复后需要重新引导节点。如果集群是手工搭建、证书来源不明、配置散落在个人笔记里,那么再好的快照也救不回来。

快照只是原料
证书才是身份
配置补上骨架
恢复才成集群

05、实战一次

先说明环境。集群由 kubeadm 部署,控制面为 stacked etcd;操作机上需要与集群内 etcd 主版本一致的 etcdctl 与快照工具,版本对应关系需按当前官方文档核验。依赖是 /etc/kubernetes/pki/etcd 下的 ca.crt、server.crt、server.key,以及各控制面 2379 端口的连通性。

先确认对象与成员:

kubectl -n kube-system get pods -l component=etcd -o wide
kubectl -n kube-system get pod etcd-cp-01 -o jsonpath='{.spec.containers[0].command}' | tr ',' '\n' | grep -E 'data-dir|listen-client|advertise'
ls -ld /var/lib/etcd

然后是核心实现,一个最小但完整的备份脚本,包含健康检查、快照、校验与同批次归档:

#!/usr/bin/env bash
set -euo pipefail

export ETCDCTL_API=3

ENDPOINTS=' https://10.0.0.11:2379,https://10.0.0.12:2379 ,https://10.0.0.13:2379'
CACERT='/etc/kubernetes/pki/etcd/ca.crt'
CERT='/etc/kubernetes/pki/etcd/server.crt'
KEY='/etc/kubernetes/pki/etcd/server.key'
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
OUT='/var/backups/etcd'
mkdir -p "$OUT"

etcdctl --endpoints="$ENDPOINTS" --cacert="$CACERT" --cert="$CERT" --key="$KEY" \
  endpoint health --write-out=table

etcdctl --endpoints="$ENDPOINTS" --cacert="$CACERT" --cert="$CERT" --key="$KEY" \
  endpoint status --write-out=table

etcdctl --endpoints="$ENDPOINTS" --cacert="$CACERT" --cert="$CERT" --key="$KEY" \
  snapshot save "$OUT/etcd-$STAMP.db"

# 后置校验:读不出 revision 的快照一律视为失败
etcdutl --write-out=table snapshot status "$OUT/etcd-$STAMP.db"

# 同批次归档集群身份与安装配置
tar czf "$OUT/pki-$STAMP.tgz" -C /etc/kubernetes/pki .
kubectl -n kube-system get configmap kubeadm-config -o yaml > "$OUT/kubeadm-config-$STAMP.yaml"
sha256sum "$OUT/etcd-$STAMP.db" > "$OUT/etcd-$STAMP.db.sha256"

echo "backup ok: $STAMP"

启动方式上用 systemd timer 或节点 cron 都可以,关键是 PATH 要显式声明,并且禁止任何形式的失败吞掉。请求就是手工跑一次,观察退出码与产物。

验证分三层。第一层看命令退出码,必须为零。第二层看快照元数据,未在当前环境实测,以下为预期结果:

+--------------------------+----------+----------+------------+
|        HASH              | REVISION | TOTAL KEYS | TOTAL SIZE |
+--------------------------+----------+------------+------------+
| 8f2c1b9e6a4d3c7f1e0b     |  1234567 |       9876 |      65 MB |
+--------------------------+----------+------------+------------+

这段输出为示例输出,用于说明校验该看哪几个字段,不是任何真实集群的数据。第三层看归档目录,快照、证书包、kubeadm 配置、校验和四类文件必须同批次齐全。

到这一步,V1 跑通了,但它只解决了一半问题:我们知道快照是有效的,却还没证明它能被恢复。而恢复恰恰是后面所有坑的集中地。

命令要先跑通
校验必须后置
归档同批落地
失败必须出声

06、排查

第一条链:备份看起来天天成功,实际上什么都没备份。

现象是 cron 日志显示任务已完成,但快照文件的修改时间是三天前。怀疑脚本提前退出,或者 cron 环境的 PATH 里根本没有那个二进制。检查方式是打开脚本的退出码,去掉所有容错符号后手工重跑,再去看调度器的日志与邮件。证据是脚本退出码为零,而标准错误里明明白白写着命令未找到——因为管道把失败吞掉了,最后一个命令成功,整体就算成功。根因是失败路径与成功路径在退出码上不可区分。修复是补上严格模式,去掉吞错写法,并强制在后置校验失败时非零退出并触发告警。

错误尝试: 一开始我们怀疑是定时任务没被触发,于是加了一堆探针脚本,在每个步骤后面打日志、写标记文件,结果什么都没查到。因为问题不在有没有跑,而在跑失败了也算跑过。

第二条链:快照恢复成功,etcd 却起不来。

现象是 etcd static pod 反复重启,日志里是打开数据目录失败。怀疑是恢复出来的目录权限或属主不对,也可能是 manifest 指向的 hostPath 与实际目录不一致。检查是看恢复目录的属主与权限、看 etcd.yaml 里的 --data-dir 与 hostPath、看容器运行时里这个 Pod 的最近状态与日志。证据是 manifest 还指向旧路径,而且三台控制面里只改了一台。根因是 static pod 的变更必须在每台控制面上同步,不然每台 etcd 指向不同数据目录,集群连成员都对不齐。修复是三台同步修改、统一 restore 参数、逐台滚动重启,并在恢复前把旧数据目录改名保留而不是删除。

顺带一个版本层面的坑:不同 etcd 主版本之间,快照的查看与恢复命令归属不同,脚本里应该做存在性检测与分支,而不是假设某条子命令一定在原来那个二进制上。

第三条链:kubectl 偶发超时,leader 悄悄换人。

现象是请求间歇性报 etcd 请求超时,同时 leader 变更计数在涨。怀疑是磁盘 fsync 尾延迟,或者 CPU 被同机其他负载抢走。检查是看 WAL fsync 与 backend commit 的延迟分布,配合系统层面的磁盘利用率与等待队列观察。证据是延迟尖刺的时间点与请求超时的时间点对得上,而 CPU 与网络都很闲。根因是 etcd 的提交路径必须等待落盘,尾延迟会直接转化成请求延迟,持续越久越容易触发选举。修复是给 WAL 与后端存储安排低延迟、低争抢的盘,并按官方调优文档调整心跳与选举超时,具体阈值需按当前官方文档核验。

错误尝试: 第一反应是把选举超时时间拉大,让告警先安静下来。结果超时告警确实少了,写入延迟一点没变,用户感知到的慢请求反而更久。这是把症状按住了,把问题留住了。

第四条链:DB SIZE 只涨不跌,磁盘告警。

现象是 endpoint status 里的 DB SIZE 单调增长。怀疑是自动压缩没生效,或者只压缩了没有整理。检查是看总大小与在用大小的差值,以及 kube-apiserver 的压缩相关参数。证据是在用空间远小于总大小,说明文件里堆了大量空洞。根因是压缩只处理可见性,不归还文件空间。修复是逐个成员串行整理,避开业务高峰,并接受整理期间该成员短暂不响应请求。

错误尝试: 有人提议直接删掉数据目录下的旧文件来腾空间。那等于把 WAL 和快照一起删了,是最彻底的自我伤害,必须写进红线清单。

先看现象再看码
证据胜过猜测
根因必须落地
修复才可收工

07、优化

V2 的每一项改动都来自上一章的证据,而不是来自直觉。

根因一:失败与成功在退出码上不可区分。修改是补上严格模式,去掉吞错写法,并在快照生成后强制执行一次元数据校验,校验失败即非零退出并告警。原因是备份的价值只在于可恢复性,而可恢复性的第一道门就是能读出元数据。新行为是失败的定时任务会主动喊人。验证方式是故意把证书路径写错,脚本必须非零退出且告警触达。

根因二:只备份了数据,没备份集群身份与配置。修改是把证书目录、kubeadm 配置、加密配置与快照放进同一个批次、同一个目录、同一份校验清单。原因是恢复时的失败点几乎都在数据之外。新行为是一次恢复所需的全部材料都能从同一个归档里取到。验证方式是在隔离环境用这份归档把控制面拉起来,并且节点能重新注册。

根因三:命令归属随版本漂移。修改是脚本启动时探测快照工具与客户端是否存在,按可用性选择命令分支,同时把集群内 etcd 的版本写进归档清单。原因是恢复当天最不该做的事就是查文档猜语法。新行为是同一份脚本在两种版本的测试集群里都能跑通。

根因四:容量增长没有观测。修改是把整理拆成两步:日常交给 kube-apiserver 的自动压缩机制处理,整理由受控任务串行执行,且每次只动一个成员、动完确认成员健康再动下一个。原因是整理会带来短暂不可用,必须可控。新行为是磁盘容量曲线可预测。验证方式是对比整理前后总大小与在用大小的差值,记录实测值,不预设结论。

根因五:恢复能力没有被证明过。修改是把恢复演练写进季度日历,产出一份演练记录:用了哪个快照、恢复了哪些成员、卡在哪一步、实际耗时多少。原因是只有跑过的路径才算存在的路径。新行为是恢复手册不再是文档,而是一份被反复验证过的操作剧本。

再加一条运维层面的补强:所有与 etcd 相关的告警都挂上归属人,并且把恢复手册的第一页固定写清应用数据库不在 etcd,业务数据必须走独立的备份与恢复链路。

校验写进脚本
归档写进流程
演练写进日历
指标写进告警

08、演进

[同一输入] 一份某个时间点的集群状态
    |
    +--[V1] 本机快照,无校验无归档无演练 / 代价:恢复当天才发现缺件
    |
    +--[V2] 快照+身份+配置同批次归档,带校验、巡检与演练 / 代价:存储与演练成本,整理需窗口
    |
[Trade-off]
得到的是可证明的恢复能力与可观测的容量趋势
失去的是本机落盘的省事,多出隔离环境与演练人力的投入
适用边界:kubeadm 这类可复现安装的集群;手工拼装的集群需先补齐身份与配置的可归档性

正确性上,V1 只能保证文件存在,V2 保证文件可读、可恢复、可回溯到具体 revision。稳定性上,V1 把风险押在恢复当天的临场发挥,V2 把风险提前到演练环境里暴露。复杂度上,V1 只有一个脚本,V2 有脚本、归档、巡检、受控整理任务和演练流程,运维负担真实增加。成本上,V2 多出归档存储、隔离环境和人力,但换来的是可承诺的恢复目标。适用范围上,V2 依赖安装方式的规范化,这恰恰是自建集群最容易被忽视的前置条件。

遗留问题也很明确:一是快照的异地与加密归档还没有纳入统一策略;二是恢复演练目前仍是半自动,人工步骤偏多;三是节点重新加入集群的路径与证书轮换的衔接还没有完全打通。这三条构成了下一轮演进的输入。

V1 只求能跑
V2 要求能证
取舍在于成本
边界写进文档

09、洞见

9.1 备份的验收标准是恢复,不是文件存在

我们过去衡量备份质量的指标是任务成功率,这个指标几乎没有任何信息量,因为它只证明脚本被执行过。真正有信息量的指标是恢复演练的成功率,以及演练中暴露出的缺件数量。反直觉判断:备份的成功率是一个会骗人的指标,恢复的可重复性才是唯一的验收标准。这条判断直接决定了后续所有设计的方向——先设计恢复流程,再倒推备份需要产出什么。

9.2 反直觉判断:控制面的体感可用性由磁盘尾延迟决定

大多数人优化控制面时的第一反应是加 CPU、加内存、调网络,但 etcd 的提交路径必须等待落盘,尾延迟会等比放大成请求延迟。这解释了为什么一个 CPU 空闲、网络通畅的集群仍然会让 kubectl 间歇性卡住,也解释了为什么把选举超时拉大只会把问题藏起来。任何绕过延迟分布的调优,都是在对症状动手。

9.3 反直觉判断:把成员数加到偶数,不会提升容错

三个成员的多数派是二,四个成员的多数派是三,两者都只能容忍一个成员故障,但后者多了同步成本、多了选举复杂度、也多了成员不一致的机会。成员数的正确姿势是奇数扩张,而不是顺手多起一台。这条判断在扩容决策里比任何压测数字都更值得先想清楚。

9.4 恢复是数据、身份、配置的组合,快照只解决了第一个

演练当天最大的收获不是某个命令,而是意识到恢复的对象从来不是一份数据文件,而是一整套集群身份。这带来一个很实用的推论:任何备份设计都应该从恢复步骤反向推导,需要什么就备什么,缺什么就补什么,而不是服务端有什么就存什么。

反直觉的真相
常在最慢一环
判断要凭证据
结论落在取舍

10、系统落地

原来有什么:一个单点 cron 的备份脚本,一堆没有校验过的快照文件,一套只在想象中存在过的恢复流程,以及一份默认业务数据在 Kubernetes 里的错误认知。

本篇新增了什么:一份带健康检查、快照校验与同批次归档的备份脚本;一套包含数据、身份、配置三类材料的归档结构;一份写清了版本分支的恢复操作手册;一组围绕成员状态、leader 变更与磁盘延迟的巡检与告警;一套把整理拆成自动压缩加受控整理的容量治理动作;以及一项按季度执行的恢复演练制度。

现在能做什么:能在任何一天取出一份经过校验的快照,配合同批次归档的证书与安装配置,在隔离环境里重建出可用的控制面,并且能解释 DB SIZE 增长的原因、给出治理动作。

还缺什么:异地与加密归档策略、快照保留与生命周期管理、恢复演练的自动化流水线,以及节点重新加入与证书轮换在恢复路径上的衔接。

下一步的演进方向也很清楚:把演练做成可调度的任务,把 etcd 指标接入统一告警并绑定归属人,把恢复手册的第一页固化成本篇最重要的一句话——集群状态的备份在 etcd,业务数据的备份不在 etcd。

原来只有快照
现在拥有档案
缺口仍然清晰
演进才有方向

11、小结

Q1 → etcd 存的是全部 API 对象,三个成员靠多数派容忍一台故障,偶数成员不提升容错
Q2 → 快照只提供数据,恢复还需要证书身份与 kubeadm 配置,三者齐备才叫恢复
Q3 → 应用数据库与 PV 数据不在 etcd,必须走独立备份链路,边界要写在恢复手册第一页
状态 → 可校验的备份脚本 + 同批次归档 + 季度恢复演练 + 成员与容量巡检

三问各有答案
状态可以验证
能力可以交付
边界已经写明

12、作业

12.1 理解题:为什么三个成员的集群能容忍一台故障,而四个成员不能容忍两台?

参考答案:Raft 的提交要求多数派确认,三个成员的多数派是二,允许一个成员缺席;四个成员的多数派是三,也仍然只允许一个成员缺席。容错的提升来自从偶数跨到下一个奇数,而不是简单地增加成员。多出来的成员还会带来同步开销与选举复杂度,所以成员数应该按奇数扩张,并确认奇数扩张确实带来容错收益。

12.2 实战题:写一个备份脚本,要求失败必须非零退出并告警,同时归档证书与安装配置。

参考答案:脚本开头启用严格模式,显式导出客户端 API 版本,用完整的 endpoints 与证书三元组先做健康检查,再生成快照;快照生成后立即读取元数据做后置校验,读不出 revision 即视为失败;随后在同一批次目录内打包证书目录、导出 kube-system 下的 kubeadm 配置,并生成校验和文件;任一环节失败直接非零退出并触发告警通道。验收方式是把证书路径故意写错,观察脚本是否失败并告警。

12.3 排障题:快照恢复后 etcd 反复重启,日志提示数据目录不可用,你会怎么查?

参考答案:先看恢复目录的属主与权限是否符合要求,再看 etcd 的 static pod 清单里 --data-dir 与 volume hostPath 是否都指向了新目录,然后确认三台控制面的清单是否一致,最后看容器运行时里该 Pod 的最近日志与重启原因。常见根因是只改了一台机器的清单,导致各成员数据目录不一致;修复时逐台同步修改并滚动重启,旧数据目录改名保留而不是删除。

12.4 架构判断题:能否把业务数据库部署在集群里,并用 etcd 快照做统一备份?

参考答案:不能。etcd 保存的是 API 对象,不保存业务数据与 PV 内的数据。即使数据库以容器方式运行在集群里,它的真实数据仍然落在外部存储或 PV 上,必须走数据库自身的备份机制加存储卷的快照机制。etcd 快照只能保证集群状态可回滚,两者必须并行存在,并在恢复手册中分别写明恢复顺序与依赖关系。

题目来自现场
答案来自证据
手要真的动过
才算学会一次

13、思考

回到开篇那个冲突:我们备份的是 etcd,不是集群。这句话看上去像文字游戏,实际是一条硬约束——etcd 快照只承载集群状态,而一个能用的集群还包含身份、配置与外部数据三块拼图。

由此可以沉淀出几条可复用的判断。第一,任何备份方案都应该从恢复步骤反向设计,恢复需要什么就备什么,而不是服务端有什么就存什么。第二,衡量备份的指标只有恢复演练的成功率,任务成功率是自欺。第三,控制面的稳定性问题优先怀疑磁盘尾延迟与容量增长,而不是先怀疑 CPU 和网络。第四,偶数成员的扩容不带来容错收益,只带来复杂度。第五,也是最容易被忽略的一条:边界必须写进文档,让每个人都清楚哪些东西不在这个快照里。

把这几条放在一起,结论很朴素:真正让人安心的从来不是备份目录里有多少文件,而是有一份被反复跑通过、并且在缺件时会立刻报错的恢复路径。

状态皆有边界
备份皆有前提
恢复皆是组合
靠谱来自演练

posted @ 2026-10-12 09:38  李福春  阅读(2)  评论(0)    收藏  举报