给 etcd 打快照并校验
目标
熟练掌握检查运行中 etcd 的状态、创建快照,并以机器可判定的方式验证该快照是否真正可用的流程。
为什么重要
备份最困难的并不是创建,而是让它值得信赖。现实中有许多系统的 CronJob 每天都在运行,却每天只留下 0 字节文件,而且没有任何告警。因此,本实验将创建文件和判定文件分为两个步骤。snapshot status 返回的 revision、totalKey、hash 分别回答“这是哪个时间点”“包含了多少内容”“文件是否损坏”。让脚本读取这三个值并输出 OK 后,备份是否成功就不再依靠人眼,而是通过退出码表达。还要结合成员数计算牢记一点:quorum 能防止节点故障,却无法防止误删除。无论是三个成员还是五个成员,错误删除都会被忠实地复制到所有成员。
步骤
- 将
etcdctl --endpoints=127.0.0.1:2379 endpoint health的输出保存到/root/etcd/backup/out/health.txt。文件中必须出现healthy和端点端口2379,且不得出现unhealthy。 - 将
etcdctl member list的输出保存到/root/etcd/backup/out/members.txt(必须包含十六进制成员 ID 和2379/2380地址)。接着在/root/etcd/backup/out/quorum.txt中写入members=<멤버 수>和quorum=<과반 수>两行。本实验的 etcd 只有一个成员,因此结果为members=1、quorum=1。 - 将快照保存为
/root/etcd/backup/snap-01.db。文件大小必须至少为 20000 字节。 - 以 JSON 格式运行
snapshot status,把结果保存到/root/etcd/backup/out/snap-01.json。revision必须大于 0,totalKey必须大于 20,hash不得为 0。 - 统计
/registry前缀下的键数量,只将数字本身写入/root/etcd/backup/out/key-count.txt(必须至少为 20)。再将按资源类型统计的键数量排行榜保存到/root/etcd/backup/out/top-prefixes.txt。该文件中必须出现pods、configmaps、secrets、leases、events、namespaces中至少一个名称。 - 创建命名空间
etcd-lab,并在其中创建 ConfigMapetcd-lab-marker,设置data.owner=platform。然后创建第二个快照/root/etcd/backup/snap-02.db,将验证结果保存到/root/etcd/backup/out/snap-02.json。第二个 JSON 的revision必须大于第一个。 - 在
/root/etcd/backup/cronjob.yaml中编写定期备份规范。要求为kind: CronJob、metadata.namespace: kube-system、spec.schedule: "0 */6 * * *"。容器的command必须采用列表形式,其中包含snapshot save,--endpoints、--cacert、--cert、--key四个标志,以及使用find和-mtime +7的删除命令。Pod 规范中必须包含hostPath为/etc/kubernetes/pki/etcd的卷、键中含有control-plane的nodeSelector,以及tolerations。所有卷都使用hostPath类型。 - 将
/root/etcd/backup/verify.sh编写为具有执行权限的脚本。如果通过参数接收的快照正常,第一行输出OK <revision> <keys>格式(空格分隔,含两个数字);否则输出不以OK开头的行。使用该脚本将snap-01.db的结果保存到/root/etcd/backup/out/verify-01.txt,将snap-02.db的结果保存到/root/etcd/backup/out/verify-02.txt。最后故意创建一个损坏文件,把验证结果保存到/root/etcd/backup/out/verify-bad.txt。
参考
- 本实验的 etcd 未启用客户端 TLS,因此连接时无需
--cacert/--cert/--key。生产环境中这三个标志是必需的,具体路径会原样出现在kubectl describe pod etcd-<노드> -n kube-system的执行参数中。第 7 步将练习这种形式。 - 现在
snapshot status已迁移到etcdutl。推荐使用etcdutl snapshot status <파일> -w json,使用etcdctl也会在发出警告后正常工作。警告写入标准错误,因此不会混入> 파일重定向的内容。 - 使用
--keys-only统计键时,输出中会混有空行。只统计以/registry开头的行才准确。资源类型是/registry/<종류>/...的第二个片段,因此可以用cut -d/ -f3提取,再执行sort | uniq -c | sort -rn。 - 要制作损坏文件,写入一个很短的垃圾文件即可。不要覆盖真实快照。
- 常见错误 1:第 6 步在创建 ConfigMap 之前创建第二个快照。这样 revision 不会增加。
- 常见错误 2:第 8 步脚本在失败路径中仍输出以
OK开头的行。这样的验证器等于没有验证。 - 每次实验都会启动新的实验 Pod,因此前一个实验中创建的集群状态不会保留。请在本实验中自行创建所需对象。这正是必须把运维流程写入 runbook 和 manifest,而不能依靠记忆的原因。
备份前检查 etcd 健康状态
将 etcdctl --endpoints=127.0.0.1:2379 endpoint health 的输出保存到 /root/etcd/backup/out/health.txt。文件中必须出现 healthy 和端点端口 2379,且不得出现 unhealthy。
备份不健康的 etcd 会得到不健康的快照。使用 etcdctl 的 endpoint 子命令中用于检查健康状态的命令,并将输出保存到文件。本实验未启用客户端 TLS,因此不需要证书标志。
列出成员并计算 quorum
将 etcdctl member list 的输出保存到 /root/etcd/backup/out/members.txt(必须包含十六进制成员 ID 和 2379/2380 地址)。接着在 /root/etcd/backup/out/quorum.txt 中写入 members=<멤버 수> 和 quorum=<과반 수> 两行。本实验的 etcd 只有一个成员,因此结果为 members=1、quorum=1。
使用 member list 查看实际成员。quorum 是过半数;请记住,N 个成员的过半数等于 N 除以 2 的商再加 1。
创建第一个快照
将快照保存为 /root/etcd/backup/snap-01.db。文件大小必须至少为 20000 字节。
在 snapshot save 后附加要保存的文件路径。确认结果文件大小达到几十 KB 以上——0 字节备份是常见事故。
使用 JSON 验证快照
以 JSON 格式运行 snapshot status,把结果保存到 /root/etcd/backup/out/snap-01.json。revision 必须大于 0,totalKey 必须大于 20,hash 不得为 0。
成功创建不等于真正可用。为 snapshot status 添加 -w json,hash、revision、totalKey 会以一行 JSON 输出。警告消息写入标准错误,因此不会混入重定向内容。
统计 etcd 中存有什么以及各有多少
统计 /registry 前缀下的键数量,只将数字本身写入 /root/etcd/backup/out/key-count.txt(必须至少为 20)。再将按资源类型统计的键数量排行榜保存到 /root/etcd/backup/out/top-prefixes.txt。该文件中必须出现 pods、configmaps、secrets、leases、events、namespaces 中至少一个名称。
所有 Kubernetes 对象都位于 /registry 前缀下。为 get 添加按前缀查询和只输出键的选项;资源类型是键路径的第三个片段。
制造变更并创建第二个快照
创建命名空间 etcd-lab,并在其中创建 ConfigMap etcd-lab-marker,设置 data.owner=platform。然后创建第二个快照 /root/etcd/backup/snap-02.db,将验证结果保存到 /root/etcd/backup/out/snap-02.json。第二个 JSON 的 revision 必须大于第一个。
创建一个对象会增加 revision。比较两个快照的 revision,就能直观理解备份时间点的含义。关键顺序是先创建对象,再创建快照。
编写定期备份 CronJob 规范
在 /root/etcd/backup/cronjob.yaml 中编写定期备份规范。要求为 kind: CronJob、metadata.namespace: kube-system、spec.schedule: "0 */6 * * *"。容器的 command 必须采用列表形式,其中包含 snapshot save,--endpoints、--cacert、--cert、--key 四个标志,以及使用 find 和 -mtime +7 的删除命令。Pod 规范中必须包含 hostPath 为 /etc/kubernetes/pki/etcd 的卷、键中含有 control-plane 的 nodeSelector,以及 tolerations。所有卷都使用 hostPath 类型。
etcd 只位于控制平面,而控制平面节点带有污点。请从主机路径挂载证书,并在命令中加入删除旧文件的保留策略。
编写快照验证脚本
将 /root/etcd/backup/verify.sh 编写为具有执行权限的脚本。如果通过参数接收的快照正常,第一行输出 OK <revision> <keys> 格式(空格分隔,含两个数字);否则输出不以 OK 开头的行。使用该脚本将 snap-01.db 的结果保存到 /root/etcd/backup/out/verify-01.txt,将 snap-02.db 的结果保存到 /root/etcd/backup/out/verify-02.txt。最后故意创建一个损坏文件,把验证结果保存到 /root/etcd/backup/out/verify-bad.txt。
正常文件应按规定格式输出 OK,损坏文件绝不能输出 OK。如果验证器总是通过,它就什么也没有验证。