etcd 保存 Kubernetes 集群的核心状态,包括 Namespace、Deployment、Service、RBAC、Secret 元数据以及控制器期望状态。控制平面节点全部丢失时,一份可用的 etcd 快照往往是恢复集群的关键。
但 etcd 快照不是完整业务备份。数据库内容、对象存储文件、PersistentVolume 数据和集群外部依赖,仍需要各自的备份方案。
一、先确认 etcd 部署方式
常见拓扑有两种:
1. Stacked etcd:etcd 作为静态 Pod 与控制平面节点一起运行,kubeadm 集群常见。
2. External etcd:etcd 是独立集群,由控制面通过远程地址访问。
备份前先确认:
kubectl -n kube-system get pods -l component=etcd -o wide
kubectl -n kube-system get pod -l component=kube-apiserver -o yaml
对于 kubeadm 本地 etcd,还可以检查静态 Pod 清单:
sudo grep -E -- \
'--(data-dir|listen-client-urls|cert-file|key-file|trusted-ca-file)' \
/etc/kubernetes/manifests/etcd.yaml
不要假设所有集群都使用 127.0.0.1:2379 或相同证书路径。外部 etcd、托管集群和自定义安装工具可能完全不同。
二、etcd 备份包含什么
etcd 快照包含备份时刻的 Kubernetes API 状态,因此可能包含:
1. 工作负载和控制器定义。
2. Service、ConfigMap、RBAC 与 CRD 对象。
3. Secret 数据或加密后的 Secret 数据。
4. 集群身份、租约和其他敏感元数据。
即使集群启用了静态数据加密,快照仍应被视为高度敏感文件。备份应加密、限制访问、记录审计,并复制到与控制平面故障域隔离的位置。
三、使用 etcdctl 创建在线快照
下面示例适用于常见的 kubeadm stacked etcd,但执行前必须核对实际端点和证书路径:
sudo env ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
--key=/etc/kubernetes/pki/etcd/healthcheck-client.key \
snapshot save /secure-backup/etcd-snapshot.db
备份路径不应位于容易被清理的临时目录,也不应只保存在同一块系统盘上。
如果使用外部 etcd,应选择健康成员的客户端地址,并使用该集群实际配置的 CA、客户端证书和私钥。不要把私钥内容写入脚本日志或博客。
四、必须验证快照
命令成功退出并不等于备份一定可恢复。至少应检查快照状态、文件大小、校验结果和备份时间。
不同 etcd 版本可能使用 etcdctl 或 etcdutl 查看快照状态,应以当前安装版本的帮助信息为准。例如:
etcdutl snapshot status \
/secure-backup/etcd-snapshot.db \
--write-out=table
如果当前版本不支持该写法,执行:
etcdctl snapshot status --help
etcdutl snapshot status --help
检查输出中的 revision、key 数量、hash 和文件大小,并把验证结果写入备份日志。
真正可靠的验证是定期在隔离环境做恢复演练。未经恢复测试的快照,只能算“可能可用”。
五、建立合理的备份策略
1. 根据业务可接受的数据丢失量确定备份频率。
2. 保留多个历史版本,避免最新快照已经包含误删除或错误配置。
3. 至少保存一份跨节点、跨磁盘或跨故障域副本。
4. 对备份加密并限制解密密钥权限。
5. 对快照大小、生成时间、失败次数和校验结果监控告警。
6. 定期清理过期备份,但不要只有唯一一份最新文件。
7. 记录 Kubernetes、etcd、kubeadm 和操作系统版本。
快照恢复通常要求与创建快照的 etcd major.minor 版本兼容。灾难发生后临时寻找未知版本工具,会显著增加恢复风险。
六、etcd 快照不能替代业务数据备份
etcd 保存的是 Kubernetes 对象状态,不会自动包含挂载到 Pod 的数据库文件、云盘数据、NFS 文件或对象存储内容。
例如恢复了 StatefulSet 和 PVC 对象,并不代表对应云盘或数据库数据一定同时回到同一时刻。完整灾难恢复需要协调:
1. etcd 快照。
2. PersistentVolume 或存储后端快照。
3. 数据库一致性备份。
4. 镜像仓库和部署清单。
5. 集群外部 DNS、负载均衡、证书和密钥系统。
不同备份之间还要考虑时间点一致性。
七、恢复前的关键判断
etcd 恢复是高风险、可能中断控制面的操作。恢复前应先确认:
1. 是单个成员故障,还是整个 etcd 集群已经失去多数派。
2. 是否真的需要从旧快照恢复,而不是修复剩余健康成员。
3. 快照的版本、时间点和校验是否正确。
4. 当前数据目录和静态 Pod 清单是否已安全备份。
5. 控制面和 API Server 将如何停机、切换与回滚。
6. 恢复后是否会与仍在运行的旧成员产生冲突。
在多成员 etcd 中,不应把恢复理解为简单地把一个 db 文件覆盖到每台机器。成员名称、初始集群、peer URL、cluster token 和数据目录必须与恢复拓扑一致。
八、使用 etcdutl 恢复到新目录
现代 etcd 版本推荐使用 etcdutl 恢复。通用形式是:
etcdutl \
--data-dir <NEW_DATA_DIR> \
snapshot restore <SNAPSHOT_FILE>
恢复会创建新的数据目录。对于 kubeadm 本地 etcd,随后通常需要让 /etc/kubernetes/manifests/etcd.yaml 中的 etcd-data hostPath 指向恢复后的目录,并让 kubelet重建静态 Pod。
但是,单节点 stacked etcd、多控制平面 stacked etcd 和 external etcd 的完整参数不同。生产恢复必须依据实际拓扑和所用 etcd 版本的官方灾难恢复文档生成命令,不能直接复制通用示例。
恢复时不要立即删除旧数据目录。应先把它移动到明确的备份位置,确认新 etcd、API Server 和集群对象完整后,再按变更流程处理旧数据。
九、恢复后的验证
恢复 etcd 后,应依次检查:
1. etcd 成员和端点是否健康。
2. API Server readyz 是否通过。
3. 节点是否 Ready。
4. kube-system 组件是否正常。
5. CRD、RBAC、Secret、Webhook 和关键工作负载是否存在。
6. Service、EndpointSlice、Ingress 与存储对象是否一致。
7. 业务数据后端是否恢复到匹配时间点。
常用检查:
kubectl get --raw='/readyz?verbose'
kubectl get nodes
kubectl get pods -A
kubectl get crd
kubectl get pv,pvc -A
kubectl get events -A --sort-by=.metadata.creationTimestamp
恢复后控制器会根据快照中的期望状态重新协调资源,可能立即创建、删除或回滚对象。应在受控维护窗口观察变化。
十、常见错误
1. 只复制正在运行的 etcd 数据目录,没有使用一致性快照。
2. 快照只保存在控制平面本机,节点故障时一起丢失。
3. 没有加密快照,泄露了 Secret 和集群配置。
4. 从未执行恢复演练。
5. 不记录 etcd 版本,灾难时工具不兼容。
6. 把 etcd 快照误认为数据库和云盘备份。
7. 恢复时覆盖唯一旧数据目录,没有回滚副本。
8. 多成员集群使用单节点命令,破坏成员关系和 quorum。
总结
etcd 备份的核心不是偶尔运行一次 snapshot save,而是建立完整闭环:识别拓扑 → 生成快照 → 校验 → 加密异地保存 → 定期恢复演练 → 与业务数据备份协同。只有经过恢复验证的快照,才能真正成为灾难恢复能力。
参考资料:
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/
https://etcd.io/docs/