LabHub
学习 学习路径 课程

Kubernetes 运维实务

用快照把误删事故撤回来

在 LabHub 中继续学习

目标

实际删除对象后,再从快照中将其恢复。使用恢复的数据目录亲自启动第二个 etcd,亲眼确认“确实恢复了”。

为什么重要

只在文档中了解恢复流程,与亲自实践一次有很大区别。尤其是,snapshot restore 不是还原数据的命令,而是创建新 etcd 集群的命令,这一点只有亲手实践才会真正记住。因此,它要求 --name--initial-cluster--initial-advertise-peer-urls--initial-cluster-token 等身份标志,并通过 --data-dir 要求一个空的新路径。一旦直接指定现有的 /var/lib/etcd,就会触碰正在使用的数据。另一个重要方面是顺序。先验证快照,再停止 apiserver 以切断写入,然后执行恢复,将清单中的 hostPath 改为新路径,最后使用 kubectl 检查。如果颠倒顺序,可能会用不可用的快照启动集群、丢失恢复期间进入的写入,或再次从旧数据启动。本实验不会停止实时集群,而是在独立端口启动恢复副本,以得出相同结论。

步骤

  1. 创建命名空间 etcd-lab,并在其中创建 ConfigMap etcd-lab-markerdata.owner=platform)。然后将事故前状态以 JSON 记录到 /root/etcd/restore/out/pre.json。包含三个键:marker_owner(值为 platform)、registry_keys/registry 下的键数量,不少于 20)、revision(当前 etcd revision,大于 0)。
  2. 将用于恢复的快照保存到 /root/etcd/restore/before.db(不少于 20000 字节),并将验证结果以 JSON 保存到 /root/etcd/restore/out/before.jsonrevision 必须大于 0。
  3. 删除 ConfigMap etcd-lab-marker 以复现事故。删除后,将查询该对象的输出保存到 /root/etcd/restore/out/gone.txt。文件中必须包含类似 NotFoundnot found 的“不存在”响应,而且实时集群中不能重新出现该 ConfigMap。
  4. before.db 恢复到 /root/etcd/restore/data。恢复后必须生成 /root/etcd/restore/data/member/snap/db/root/etcd/restore/data/member/wal。将恢复命令的输出(包括标准错误)保存到 /root/etcd/restore/out/restore.txt
  5. 这次带上所有身份标志,再恢复一次到 /root/etcd/restore/data2。必须包含 --data-dir--name--initial-cluster--initial-advertise-peer-urls--initial-cluster-token 五个标志;名称设为 restored,peer 地址设为 http://127.0.0.1:12380,token 设为 etcd-restore-lab。将实际执行的完整命令原样保存到 /root/etcd/restore/out/restore-cmd.txt--data-dir 不能写 /var/lib/etcd)。
  6. 在后台启动以 /root/etcd/restore/data2 为数据目录的第二个 etcd 进程。客户端地址为 http://127.0.0.1:12379,peer 地址为 http://127.0.0.1:12380,名称为 restored,初始成员为 restored=http://127.0.0.1:12380,token 为 etcd-restore-lab。**在评分结束前不要终止此进程。**将启动命令保存到 /root/etcd/restore/out/second-etcd.txt(文件中必须显示 12379--data-dir)。
  7. 从恢复副本读取键 /registry/configmaps/etcd-lab/etcd-lab-marker,确认值中包含 platform,并将输出保存到 /root/etcd/restore/out/recovered.txt。查询目标是 127.0.0.1:12379,实时集群(2379)中仍不能存在该对象。
  8. /root/etcd/restore/runbook.md 中编写不少于 400 字节的恢复运行手册。每个步骤放在不同行,并遵守以下顺序:(1)验证快照(snapshot status),(2)停止 kube-apiserver,(3)执行 snapshot restore,(4)将 etcd 清单的 hostPath/data-dir 替换为新路径,(5)使用 kubectl get 检查。最后还必须写明恢复失败时的回滚方法。

参考

用数字记录事故前状态

创建命名空间 etcd-lab,并在其中创建 ConfigMap etcd-lab-markerdata.owner=platform)。然后将事故前状态以 JSON 记录到 /root/etcd/restore/out/pre.json。包含三个键:marker_owner(值为 platform)、registry_keys/registry 下的键数量,不少于 20)、revision(当前 etcd revision,大于 0)。

恢复从了解“之前存在什么”开始。将标记值、/registry 键数量和当前 revision 三项汇总到一个 JSON 中。revision 位于 endpoint status 的响应头中。

获取并验证用于恢复的快照

将用于恢复的快照保存到 /root/etcd/restore/before.db(不少于 20000 字节),并将验证结果以 JSON 保存到 /root/etcd/restore/out/before.jsonrevision 必须大于 0。

恢复快照创建后应立即验证。等事故发生后才发现文件损坏,就已经太晚了。

复现删除事故并留下记录

删除 ConfigMap etcd-lab-marker 以复现事故。删除后,将查询该对象的输出保存到 /root/etcd/restore/out/gone.txt。文件中必须包含类似 NotFoundnot found 的“不存在”响应,而且实时集群中不能重新出现该 ConfigMap。

删除对象后再尝试查询。查询不存在的资源时,消息会输出到标准错误,因此重定向时必须同时包含标准错误,才能保存到文件中。

将快照恢复到新数据目录

before.db 恢复到 /root/etcd/restore/data。恢复后必须生成 /root/etcd/restore/data/member/snap/db/root/etcd/restore/data/member/wal。将恢复命令的输出(包括标准错误)保存到 /root/etcd/restore/out/restore.txt

恢复不是覆盖现有路径,而是创建新路径。恢复日志也输出到标准错误。请确认结果目录中生成了 member 结构。

带上集群身份标志再次恢复

这次带上所有身份标志,再恢复一次到 /root/etcd/restore/data2。必须包含 --data-dir--name--initial-cluster--initial-advertise-peer-urls--initial-cluster-token 五个标志;名称设为 restored,peer 地址设为 http://127.0.0.1:12380,token 设为 etcd-restore-lab。将实际执行的完整命令原样保存到 /root/etcd/restore/out/restore-cmd.txt--data-dir 不能写 /var/lib/etcd)。

restore 实际上是“创建一个新集群”的命令。明确指定名称、初始成员列表、peer 地址和 token 四项后,就能使用这些数据启动 etcd。

使用恢复副本启动第二个 etcd

在后台启动以 /root/etcd/restore/data2 为数据目录的第二个 etcd 进程。客户端地址为 http://127.0.0.1:12379,peer 地址为 http://127.0.0.1:12380,名称为 restored,初始成员为 restored=http://127.0.0.1:12380,token 为 etcd-restore-lab。**在评分结束前不要终止此进程。**将启动命令保存到 /root/etcd/restore/out/second-etcd.txt(文件中必须显示 12379--data-dir)。

只有将恢复的数据目录接入实际进程,才能完成确认。客户端和 peer 端口不能与实时 etcd 重叠,并在评分结束前保持进程运行。

确认已删除对象在恢复副本中仍然存在

从恢复副本读取键 /registry/configmaps/etcd-lab/etcd-lab-marker,确认值中包含 platform,并将输出保存到 /root/etcd/restore/out/recovered.txt。查询目标是 127.0.0.1:12379,实时集群(2379)中仍不能存在该对象。

Kubernetes 对象的 etcd 键为 /registry/<종류>/<네임스페이스>/<이름>。值采用 protobuf 格式,人类难以直接阅读,但字符串仍会原样显示。

编写恢复运行手册

/root/etcd/restore/runbook.md 中编写不少于 400 字节的恢复运行手册。每个步骤放在不同行,并遵守以下顺序:(1)验证快照(snapshot status),(2)停止 kube-apiserver,(3)执行 snapshot restore,(4)将 etcd 清单的 hostPath/data-dir 替换为新路径,(5)使用 kubectl get 检查。最后还必须写明恢复失败时的回滚方法。

这是一份凌晨 3 点也要能读懂的文档。步骤顺序很重要,还必须写明失败时返回到哪里。