Kubernetes 灾难恢复实战:用三个故障场景检验备份是否真的可用

2026-09-10 33 预计阅读时间: 1 分钟
来源: cncf.io AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

备份任务显示成功,只能证明某些数据被写到了某个位置;灾难恢复要求的则是,在明确的时间内,把应用、数据和依赖关系恢复到可服务状态。两者之间隔着完整性、兼容性、恢复顺序和操作权限等一整条链路。

真正有效的 Kubernetes 灾难恢复方案,不应只检查“有没有备份”,而应通过可重复的故障注入回答三个问题:备份产物能否读取,集群对象与持久化数据能否一致恢复,恢复后的应用能否真正对外服务。

场景一:备份文件存在,但恢复时才发现不可用

最直接的失败模式,是对象存储中确实存在备份文件,监控也记录了成功状态,但文件可能为空、被截断、无法解密,或者只能由已经丢失的凭据读取。对于 etcd 快照,还需要确认快照本身可被 etcd 工具识别,而不是只检查文件名和大小。

可以在控制平面节点上这样验证 etcd 快照。以下路径和证书参数需要根据发行版调整;对于托管 Kubernetes,应使用云厂商支持的备份与恢复接口,而不是直接操作 etcd:

export ETCDCTL_API=3

sudo etcdctl snapshot save /var/backups/etcd.db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

sudo etcdctl snapshot status /var/backups/etcd.db --write-out=table
sha256sum /var/backups/etcd.db | sudo tee /var/backups/etcd.db.sha256
sha256sum --check /var/backups/etcd.db.sha256

校验和只能发现文件变化,不能证明快照能恢复出可工作的控制面。更可靠的做法,是定期在隔离环境中执行恢复,并验证 Namespace、Deployment、Secret、CRD 与自定义资源是否完整出现。

这类演练还应覆盖加密材料。若 Secret 使用 KMS 或静态加密配置保护,必须单独保存并测试相应密钥和配置。只有密文而没有解密能力,恢复结果仍然不可用。

场景二:Kubernetes 对象恢复了,业务数据却没有回来

Kubernetes API 中的 PVC 只是对存储的声明。备份 Deployment、Service 和 PVC 对象,并不等于备份了卷中的数据。重新创建 PVC 后,它可能绑定到一块全新的空卷,表面上所有资源都是 Running,应用数据却已经丢失。

下面的实验可在安装了 Docker、Kind 和 kubectl 的机器上运行。它创建一个带 PVC 的 Pod,写入标记文件,然后删除并重建整个集群。恢复相同 YAML 后,PVC 会重新出现,但旧标记通常不会回来,这正好暴露“只备份 Kubernetes 清单”的边界:

kind create cluster --name dr-lab

kubectl apply -f - <<'YAML'
apiVersion: v1
kind: Namespace
metadata:
  name: dr-lab
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
  namespace: dr-lab
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: writer
  namespace: dr-lab
spec:
  containers:
    - name: writer
      image: busybox:1.36
      command: ["sh", "-c", "sleep infinity"]
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: app-data
YAML

kubectl wait --for=condition=Ready pod/writer -n dr-lab --timeout=120s
kubectl exec -n dr-lab writer -- sh -c 'date -u > /data/recovery-marker'
kubectl exec -n dr-lab writer -- cat /data/recovery-marker

kind delete cluster --name dr-lab

重建集群并再次应用同一份 YAML 后,可以执行:

kubectl exec -n dr-lab writer -- cat /data/recovery-marker

如果文件不存在,说明恢复的只是资源声明。生产方案还必须覆盖 CSI VolumeSnapshot、存储系统原生快照,或者数据库自身的全量备份与日志归档。对于 PostgreSQL、MySQL 等数据库,仅复制挂载目录还可能得到崩溃不一致的数据,因此需要明确备份工具如何保证应用一致性。

恢复设计还要定义 RPO。每日一次卷快照意味着理论上可能丢失接近一天的数据;若目标是分钟级 RPO,通常需要事务日志归档、增量备份或跨区域复制,而不能只提高 YAML 备份频率。

场景三:资源和数据都恢复了,服务仍无法访问

恢复后的对象数量正确,不代表业务已经恢复。应用可能依赖尚未安装的 CRD、外部 DNS、证书签发器、镜像仓库、KMS、云负载均衡器或数据库凭据。若恢复顺序错误,自定义资源可能创建失败;若身份系统位于同一故障域中,恢复程序甚至可能拿不到访问备份所需的凭据。

因此,恢复流程应该按依赖关系分阶段执行:

  1. 建立网络、存储类、节点池和访问身份。
  2. 安装 CRD 及其控制器,再恢复自定义资源。
  3. 恢复 Secret、配置和持久化数据。
  4. 部署业务工作负载与入口资源。
  5. 从集群外执行端到端探测。

健康检查不能停留在 kubectl get pods。下面的脚本同时检查 Deployment 就绪状态、Service 端点以及 HTTP 响应,可作为恢复流水线的最小验收门槛;运行前替换命名空间、Deployment、Service 和健康检查路径:

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

namespace="production"
deployment="api"
service="api"
local_port="18080"

kubectl rollout status deployment/${deployment} \
  -n "${namespace}" --timeout=5m

kubectl get endpointslice \
  -n "${namespace}" \
  -l "kubernetes.io/service-name=${service}"

kubectl port-forward \
  -n "${namespace}" "service/${service}" \
  "${local_port}:80" >/tmp/dr-port-forward.log 2>&1 &
pf_pid=$!
trap 'kill ${pf_pid} 2>/dev/null || true' EXIT

sleep 3
curl --fail --silent --show-error \
  --retry 10 --retry-connrefused \
  "http://127.0.0.1:${local_port}/healthz"

生产验收还应加入一次真实但无破坏性的业务操作,例如创建并读取测试记录,以验证写路径、数据库权限和读后写一致性。探测应从恢复集群之外发起,否则可能遗漏 DNS、负载均衡和防火墙问题。

把恢复能力做成持续验证

一次成功演练不能永久证明方案有效。Kubernetes 版本、CRD、存储驱动、加密密钥和云权限都在变化,恢复流程会随环境漂移。可以把灾难恢复检查纳入周期性流水线:自动创建隔离集群,恢复最近一次备份,执行对象校验、数据校验和外部业务探测,最后销毁环境并保存报告。

落地时至少应明确以下项目:

  • RPO:最多允许丢失多少数据,以及备份频率能否满足目标。
  • RTO:从宣布灾难到服务通过验收需要多长时间。
  • 备份范围:etcd、Kubernetes 对象、CRD、卷数据、数据库日志、密钥和外部配置是否全部覆盖。
  • 故障隔离:备份、凭据和恢复工具是否位于不同账号、区域或故障域。
  • 恢复顺序:基础设施、控制器、数据和工作负载之间是否有明确依赖。
  • 验收标准:是否通过外部流量、读写操作和关键业务指标判断恢复完成。
  • 演练记录:恢复耗时、失败步骤、人工操作和改进项是否可审计。

灾难恢复的最终产物不是一批备份文件,而是一条经过演练、能够重复执行并有明确验收条件的恢复路径。只有在隔离环境里持续证明这条路径可用,备份才真正具有业务价值。


相关推荐