4. 升级前的备份与恢复策略

OpenShift 升级不是一次“点按钮”的操作,而是一次对控制面、节点、工作负载和存储的联合变更。升级失败时,真正决定能否快速回退的,不是升级工具本身,而是升级前是否已经准备好可验证、可定位、可恢复的备份。本节围绕四类对象展开:etcd 数据、集群资源、应用配置、持久化数据,并给出可执行的备份方案与恢复演练方法。

一、先明确“回退”到底回退什么

OpenShift 的升级失败通常分为三种情况。第一种是控制面组件升级后无法正常启动,此时最有效的回退手段是恢复 etcd 快照,把集群状态拉回到升级前。第二种是升级过程中部分 Operator 或 CRD 变更导致资源对象不兼容,此时需要恢复集群资源清单,并重新应用。第三种是应用本身在升级后出现异常,但集群控制面正常,此时应优先回滚应用配置和持久化数据,而不是整体恢复 etcd。

因此,备份策略必须分层设计,不能只做一份 etcd 快照就认为万事大吉。etcd 快照解决的是“集群状态回退”,集群资源备份解决的是“对象级回退”,应用配置备份解决的是“工作负载回退”,持久化数据备份解决的是“业务数据回退”。四者职责不同,恢复顺序也不同。

OpenShift 升级前备份分层与恢复路径 etcd 快照 集群状态 / 版本 / 证书 恢复粒度:整集群 集群资源清单 CRD / Operator / RBAC 恢复粒度:对象级 应用配置 Deployment / ConfigMap 恢复粒度:工作负载 持久化数据 PV / PVC / 数据库 恢复粒度:数据卷 cluster-backup.sh 保存到节点外存储 oc get --export / 清单导出 按命名空间归档 GitOps 仓库 / Helm values 版本化配置基线 存储快照 / 逻辑导出 VolumeSnapshot / dump 升级失败 → 判断故障层级 → 选择恢复路径 控制面不可用 → etcd 恢复;对象异常 → 资源恢复;应用异常 → 配置/数据恢复 推荐恢复顺序 ① 恢复 etcd 快照 → ② 校验控制面与版本 → ③ 恢复集群资源 → ④ 恢复应用配置 → ⑤ 恢复持久化数据 → ⑥ 验证业务 每一步完成后必须验证,再进入下一步;禁止跳步恢复

二、etcd 备份:控制面回退的最后防线

etcd 保存了 OpenShift 全部集群状态,包括 API 对象、RBAC、证书、Operator 状态和节点注册信息。升级前必须对 etcd 做一次完整快照,并确认快照文件可读、可校验。OpenShift 提供了 cluster-backup.sh 脚本,通常位于控制面节点的 /usr/local/bin/ 目录下。

# 在控制面节点执行 etcd 快照备份
sudo /usr/local/bin/cluster-backup.sh /home/core/backup

# 输出示例
etcdctl version: 3.5.9
API version: 3.5
Snapshot saved at /home/core/backup/snapshot_2025-01-15_103000.db
Snapshot saved at /home/core/backup/static_kuberesources_2025-01-15_103000.tar.gz

执行完成后,应检查快照文件大小是否合理,通常为几十 MB 到几百 MB。随后使用 etcdutl snapshot status 校验快照完整性,确认 revision 和 hash 正常。快照文件必须复制到集群外部存储,例如对象存储、NFS 或专用备份服务器,不能只留在控制面节点本地,否则节点故障时快照同时丢失。

etcd 快照恢复会回退整个集群状态,包括升级后新增的资源对象。因此恢复 etcd 前必须确认:升级后创建的业务数据是否已经单独备份,否则这些数据会随 etcd 回退而丢失。

三、集群资源与应用配置备份

集群资源备份的目标是保留升级前的对象定义,便于在升级后出现对象不兼容时按命名空间恢复。常用做法是使用 oc get 导出关键资源清单,并按命名空间归档。需要重点备份的对象包括:自定义资源定义 CRD、Operator 订阅、ClusterRole 与 RoleBinding、NetworkPolicy、Route、BuildConfig、ImageStream 等。

# 导出集群级资源
oc get crd -o yaml > backup/crd.yaml
oc get clusterrole,clusterrolebinding -o yaml > backup/rbac.yaml
oc get subscription -A -o yaml > backup/subscriptions.yaml

# 按命名空间导出应用资源
for ns in app-prod app-test; do
  oc get all,configmap,secret,pvc,route -n $ns -o yaml > backup/${ns}.yaml
done

应用配置备份更强调“版本化”。如果应用已经使用 GitOps 管理,那么 Git 仓库本身就是配置基线,升级前只需记录当前同步的 commit 或 tag。如果使用 Helm,应保存 values.yaml 和 chart 版本。对于手工维护的 ConfigMap 和 Secret,建议在升级前导出为 YAML 并纳入版本控制。Secret 中包含敏感信息,导出后应加密存储,避免明文泄露。

四、持久化数据备份

持久化数据是升级回退中最容易被忽视、也最难恢复的部分。OpenShift 中常见的持久化方式包括:块存储 PV、文件存储 PV、对象存储,以及运行在 Pod 内的数据库。备份策略取决于存储类型。

如果底层存储支持 CSI VolumeSnapshot,可以创建 VolumeSnapshot 对象,对 PVC 做一致性快照。示例:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: mysql-data-snapshot
  namespace: app-prod
spec:
  volumeSnapshotClassName: csi-snapclass
  source:
    persistentVolumeClaimName: mysql-data

如果存储不支持快照,则需要使用逻辑备份。例如 MySQL 使用 mysqldump,PostgreSQL 使用 pg_dump,将数据导出到对象存储。逻辑备份的优点是跨版本兼容性好,缺点是恢复时间长、可能丢失备份点之后的数据。对于关键业务,建议同时保留快照和逻辑备份两份。

五、恢复演练:备份不演练等于没有备份

备份方案设计完成后,必须在非生产环境执行一次完整恢复演练。演练目标不是“能恢复”,而是“能在可接受时间内恢复到可接受状态”。演练应覆盖以下检查点:

  • etcd 快照能否成功恢复,恢复后 oc get nodes 是否正常返回。
  • 集群资源清单能否按命名空间重新应用,CRD 与 Operator 是否恢复。
  • 应用配置恢复后,Pod 能否正常启动并进入 Running 状态。
  • 持久化数据恢复后,业务数据是否完整,数据库能否正常读写。
  • 记录每个步骤的实际耗时,形成恢复时间基线。

演练结束后,应输出一份恢复演练记录,至少包含:备份时间点、恢复目标、实际恢复耗时、遇到的问题、修复措施和最终验证结果。这份记录在真实升级失败时可以直接作为操作依据,避免临时决策。

建议在升级窗口前 24 小时完成一次全量备份,并在升级前 1 小时再做一次增量 etcd 快照。两次快照之间如果发生配置变更,应以最近一次快照为准,同时保留变更记录。

六、回退决策与执行要点

升级失败后,不要立即执行恢复。先判断故障层级:如果控制面 API 不可用、etcd 无法启动,直接走 etcd 恢复;如果控制面正常但部分对象异常,优先恢复集群资源;如果集群正常但应用异常,只恢复应用配置和持久化数据。恢复顺序应遵循“先控制面、后资源、再应用、最后数据”的原则,每一步完成后验证,再进入下一步。

最后需要强调:备份与恢复策略不是升级前的临时任务,而应纳入日常运维流程。定期备份、定期演练、定期更新恢复文档,才能在真正需要回退时做到有据可依、有路可退。