技术 · 熟练
自托管 Agent 的备份,为什么恢复了却起不来?
备份能拷走,是「代次」拷不走
备份任务退出码是 0,不等于你能恢复。自托管 Agent 把三样东西分开放:配置文件、数据库、还有凭据 —— 它们各写各的、各存各的备份,而恢复时你要的是同一个时刻的完整一份。这一页讲四件事:① 把「备份成功」重新定义为「在空环境里起得回来」② 恢复必须落进一个全新的目录、核对完再切换 ③ 配置 / 数据 / 凭据必须来自同一次备份 ④ 口令、标记、命名空间这三样要单独存好,且每个运行实例用不同的命名空间。前三条是纪律,第四条是唯一一处「必须提前写下来」的东西。
方法 · 一图看懂
1
先把验收口径换掉 — 「备份跑完了」不是判据,判据是「在一个空目录里能不能起回来」;退出码 0 只说明文件写出去了,不说明它们凑得成一份
2
恢复到全新目录再启用 — ⛔ 不覆盖正在跑的实例:恢复进一个空目录 → 逐项核对 → 再切换;直接覆盖跑着的实例,等于用一份没验过的替掉那份还能用的
3
三样东西必须同一代 — 配置 / 数据 / 凭据三件要来自同一次备份;跨代拼装(上月的配置配这周的数据)会得到一种事后没人能解释的状态
4
口令 · 标记 · 命名空间单独存 — 恢复要用的这三样不能只躺在备份里;且每个运行实例一个命名空间,否则恢复时互相盖
原理 · 为什么有效
备份系统的默认设计是「每样东西各自定期导出」—— 配置导一份、数据库导一份、凭据留在原处。这在单件损坏的场景下够用,但恢复要解决的是整体替换:你要把一个实例从零起回来。这时三份不同时刻的导出就是三份互相对不上的账:数据库里有一条上周写入的记录,配置里没有它对应的开关,凭据对得上但指向的是旧库。判据一句话:备份的单位不是「文件」,是「代次」—— 同一次导出的三件才算一份。而口令 / 标记 / 命名空间之所以要单独存,是因为它们恰好不在备份里(它们本来就是用来解备份的钥匙)—— 把钥匙锁进保险箱、再把保险箱钥匙锁进另一个保险箱,是这类系统最常见的自锁。
适用场景
适用:① 你在自托管一个 Agent / 助手,靠本机脚本或对象存储做备份 ② 你用的平台提供「全量备份 + 恢复」,但你把恢复当成最后手段、从没演练过 ③ 你同时跑多个实例(开发 / 生产各一份)。⛔ 不适用:① 托管服务已经替你保证恢复(这时该做的是核对它的保留期与导出通道,不是自建备份)② 数据本身可重建(能重跑出来的东西不需要精心备份)③ 单机单实例、数据无关紧要的试验环境。
自测 · 6 问
我说得出「上一次恢复演练是什么时候、在哪个目录里做的」,不是只记得备份跑完了
我的恢复是「落进空目录 → 核对 → 切换」,不是直接覆盖在跑的实例
我能指出配置 / 数据 / 凭据三件的备份时间戳,并确认它们来自同一次
口令 · 标记 · 命名空间我另存了一份,且不在同一台机器上
我的每个运行实例有各自的命名空间,恢复时不会互相盖
我知道归档体积与剩余空间的检查点(低于阈值就该报错,而不是写个半份)
怎么上手 · 验证步骤
① 找一台空机器(或一个空目录),把最近一次备份恢复进去,⛔ 先别管原来那台。② 记下第一处对不上的地方:多半是配置的键、数据库的表结构、或一个读不到的凭据。③ 按「配置 / 数据 / 凭据」三列,各自写下最近一次导出时刻;三列时刻不一致 ⇒ 你实际拥有的不是一份备份,是三份。④ 把口令 / 标记 / 命名空间抄到一个离线的地方,并注明「恢复时要用」。⑤ 把这次演练的结论写成一行,放进你的运行手册:恢复验收 = 空环境起得来。
自检动作:不看任何文档,向别人复述「如果这台机器现在坏了,我按什么顺序把它起回来」。如果你说到一半必须去翻某个脚本或某个平台页面才知道下一步,说明这条恢复路径目前只存在于环境里、不存在于你手上 —— 而这正是备份要解决的那件事。