文件
hyb-oa/.trellis/tasks/08-28-production-arm-backup-transfer-incident/prd.md
T
wangsli和Claude Opus 5.5 f6d1025d85 备份策略改为部署前手动快照:部署合同增加手动快照模式 [08-28-production-arm-backup-transfer-incident]
- 用户决定仅用部署前手动轻量快照,不再推进对象存储、ARM/hyinda-20c 备份
- refresh-deployment-contract 新增 /etc/hyb-oa-backup-mode 显式模式:
  无文件保持原自动模式;manual_snapshot 要求三个备份 timer 停用且备份
  service 已退出,ops timer 仍须运行;内容/属主/符号链接异常 fail-closed
- probe 部署前与 refresh 部署后均校验模式与 timer/service 一致性
- 新增 44 backup_mode_invalid / 45 backup_timer_not_disabled 分类及合同测试
- 记录 10-05 ARM 与 hyinda-20c 只读核验结果、远端切换顺序与回滚
- 远端切换未执行,需另行批准

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 17:28:45 +08:00

14 KiB

生产到 ARM 备份传输中断

2026-10-05 当前决策:仅使用手动快照

用户明确决定不使用其他厂商对象存储、ARM 或 hyinda-20c 备份,只使用已确认 OA 生产轻量实例的手动快照。此决策取代本任务继续修复异机链路、选型迁移及两个自然备份周期验收的目标;以下原始要求和 AC 保留为历史,未完成项不追认为通过。关联 08-23-isolated-backup-restore-drill 的历史部分恢复结果不变,本决策不授权继续真实恢复。

  • 当前备份方式为部署前手动快照;确认目标、磁盘覆盖和创建成功后再部署,不新增自动快照脚本或其他副本方案。恢复范围受现存成功快照的时间点与覆盖磁盘限制,不承诺每日恢复点或实例外副本。
  • 选择备份方式与实际停用分开记录。本轮落实本地合同;发布脚本适配、生产/ARM 定时任务停用方案见 design/implement,非微小代码实施和远端配置变更待方案批准。
  • 历史备份、快照、凭据和 unit 文件不因本决策自动删除;公网健康监控是独立功能,不把“停用备份”解释为关闭全部监控。

当前验收

  • S1:当前选择已同步到任务及部署规约,本地文档/治理检查通过;旧未验项与当前决策明确区分。文档审计保留既有未登记文件警告,详见 implement。
  • S2:获批的发布适配与备份任务停用完成,停用状态及发布兼容性有据;此前不得称“已经只运行手动快照方案”。

Goal

恢复腾讯云生产到 ARM 的自动异机备份链,消除持续扩大的异机恢复点缺口,同时把生产备份落盘容量恢复到可持续范围,并证明修复不是一次偶然成功。

Scope

  • 只读定位 partial 停止偏移、rsync 原始退出码、失败持续时间、生产本地批次累积与容量预算。
  • 基于证据设计并在另行批准后实施最小传输链修复和生产容量处置。
  • 验证新 ARM 原子归档、daily/watchdog/dead-man 的 timer 与 service,并连续观察两个自然调度周期。
  • 建立真实告警发送调用时刻、人工确认时刻和响应延迟的脱敏记录合同。
  • 维护与 08-23-isolated-backup-restore-drill 的阻塞交叉引用;不在本任务内执行恢复演练。

Background

  • 腾讯云服务器是真实 OA 生产;ARM 是异机备份、dead-man 和隔离恢复节点,不是生产。
  • 2026-08-27,任务 08-23-isolated-backup-restore-drill 的最新批次探针发现 ARM 最新原子归档已超过 24 小时目标;随后获批的只读调查确认生产 daily/watchdog timer 正常触发,但对应 service 最近均以 exit-code/1 失败。
  • ARM inbox 有两个未完成 .partial,其中最新一个与最近自然备份时点对应;两者均未满足三文件、manifest 身份和产物字节数的完整传输合同,正式归档事务临时对象为零。因此当前 finding 为 offhost_transfer_incomplete,不是调度漏跑或完整传输后的 finalize 失败。
  • partial 已证明 rsync 通过初始 SSH 认证、host key 校验和 receiver 授权并开始写入。密钥失效、authorized_keys 初始拒绝和 host key 初始拒绝不是首要假设;仍需调查传输中段的源端读取、网络/超时、目标写入和会话/传输限制。
  • ARM dead-man 以显式 93600 秒阈值正确判定 archive_stale,且 journal 聚合存在一次 sent=true。检测与发送调用没有被去抖静默抑制,但该告警没有形成及时人工响应;本次首次知晓时刻未采集,历史响应延迟不可补造。
  • 生产相关文件系统只读观测约为 82% 使用、10 GiB 可用。现有证据不能把本次传输中断直接归因于空间不足,但该余量不足以作为持续生成完整 dump、storage 归档和失败重试的安全基线,必须与传输故障并行处置。

Requirements

R1. 分阶段授权与数据保护

  • 任务创建和规划不授权连接生产或 ARM,也不授权任何远端写入。
  • 第一阶段只读调查必须另行批准,只允许读取聚合字节数、rsync 原始退出码、固定阶段时刻/耗时、systemd 状态、源端本地批次聚合和文件系统容量;不得输出远端地址、完整路径、run id、文件名、原始 stderr/journal/JSON、凭据或业务内容。
  • 清理空间、删除或移动本地/ARM partial、调整 SSH/rsync/systemd 参数、修改 timer、重启服务、手工触发备份、重跑传输或发送测试告警均属于生产/ARM 写操作,必须在根因和变更方案审阅后单独明确批准。
  • 不修改或删除已有 ARM 正式原子归档;诊断不得把真实备份下载到开发机。

R2. 只读根因定位

  • 第一项先判断生产本地是否至少存在一个完整可用批次,并对最新本地候选执行与异机归档相同的 manifest schema/status、精确三文件集合、run id 配对、字节数和 SHA-256 校验。输出只含 complete_local_recovery_point=yes|no、年龄、数量和聚合大小。若为 yes,当前风险是异机副本缺失/生产单点;若为 no,当前不存在任何已证明可用的备份,事件风险和过渡恢复点优先级立即升级。
  • 分别核对成功运行和失败运行对生产本地批次/临时对象的保留与清理行为:成功后是否按保留策略清理,失败后是否保留完整本地批次、是否残留生成期临时对象,以及连续失败是否逐轮累积。不得仅统计“是否累积”而遗漏清理语义。
  • 比较两个 partial 的聚合总字节数、各预期产物已写入字节数或安全比例,不输出文件名/路径。相同或接近停止偏移作为确定性限制信号,明显不同偏移作为网络/超时等间歇中断信号;阈值和计算口径须在取数前固定。
  • 从生产备份 wrapper 的私有状态/诊断中提取真实 rsync 退出码和稳定类别,不以 systemd/service 的通用 exit 1 替代。至少区分 rsync 23、30、12、11 与 SSH 层 255;不得输出原始错误文本。
  • 记录每次失败的传输阶段开始、失败时刻和持续秒数,判断是否收敛到相近时长;无法从现有状态可靠取得时明确标为未测,不从 mtime 或聊天时间猜测。
  • 只读统计生产当前可用空间、最近完整本地批次聚合大小、当前本地完整/不完整/临时批次数量及成功/失败路径的清理与累积行为,形成容量预算。
  • 将 partial 偏移、rsync 原始码、失败时长和两端容量交叉判定,输出一个主要根因类别及仍未排除的候选,不为尽快修复而伪造单一确定根因。
  • 若现有只读证据不能收敛,尤其是故障疑似位于不可控链路侧,不扩大远端读取范围或反复追加低信号探针;转为设计“一次受控观测性重传”,冻结输入、实时采集允许字段并有界停止,作为独立审批项。该路径不在只读调查授权内。

R3. 传输链修复

  • 只修复 R2 证据直接支持的最小故障面;不得顺手轮换已证明可以完成初始认证的密钥、重建 receiver、放宽 manifest/finalize 安全门禁或修改恢复 runner。
  • 若根因为超时/会话限制,变更须有明确的客户端、服务端或中间链路归属、取值依据、回滚值和有界失败行为;禁止无限超时或无界重试。
  • 若根因为源端读取、目标写入、网络或 rsync 行为,优先修复可机械验证的具体错误,并保留原子 finalize、partial 隔离和失败关闭。
  • 生产和 ARM 的实际变更必须先形成脱敏变更清单、备份/回滚点与验证命令,再单独申请执行批准。

R4. 生产容量处置

  • 基于最近成功批次和当前生成流程计算至少容纳一个完整新批次的实际峰值预算,并增加保守安全余量;容量阈值必须在生产写操作前写入设计和证据。
  • 优先识别可安全处置的自动备份自有产物、失败临时对象或保留策略问题;任何删除/移动必须精确匹配已验证身份,禁止宽泛清理、跨任务清理或触碰生产数据库/附件源数据。
  • 容量处置不得以降低备份保留、删除唯一恢复点或跳过本地完整批次为代价。若空间扩容比删除更安全,应选择扩容方案并单独审批。
  • 修复后生产必须具备“一个完整新批次实际峰值 + 安全余量”的可验证空间,且两个自然周期内空间趋势不继续逼近失败线。

R5. 恢复验证与持续观察

  • 修复后必须形成新的 ARM 原子归档批次,而不是仅出现 partial;该批次须通过 manifest schema/status、精确三文件集合、run id/目录配对、字节数和 SHA-256 校验。
  • daily、watchdog、dead-man 不得仅以 timer active 作为通过。对应 timer 必须正常触发,最近 service 必须 Result=success、退出码 0,状态摘要须与新鲜归档一致。
  • 必须连续观察至少两个自然 daily 调度周期,每个周期都形成新的完整原子归档并通过相同合同;手工补跑成功不能替代两个自然周期。
  • 两个周期都必须记录 ARM inbox partial 数量/聚合字节变化和 ARM 文件系统可用量/使用率趋势;不得只观察生产容量,避免传输失败对象在 ARM 侧继续累积形成新的容量故障。
  • 观察期间不得为通过验收而删除失败证据、改选旧批次或临时放宽新鲜度/完整性阈值。

R5a. 过渡恢复点决策

  • R2 得出本地备份可用性后,必须单独记录 transition_recovery_point_action=wait_natural|request_manual_run 及理由。
  • 若生产本地已有完整可用批次且下一自然周期时间/容量风险可接受,优先等待自然调度;若生产本地也没有完整可用批次,手工补跑建立过渡恢复点的优先级显著上升,但仍须先有根因/容量停止条件并取得单独批准。
  • 手工补跑即使形成过渡恢复点,也不计入 AC5 的两个自然周期;若没有获批,不得为缩短风险窗口自行执行。

R6. 告警送达与响应闭环

  • 保留本次“检测与发送调用正常、响应未及时形成”的双重结论,不把 sent=true 等同于人员已阅读。
  • 从本任务开始,每次真实备份/dead-man 告警须分别记录脱敏的发送调用时刻和首位责任人确认时刻,并计算响应延迟;不得记录 webhook、群标识、人员账号或消息原文。
  • 若后续告警仍只有 sent=true 而无人确认,调查群送达、可见性、责任人和升级流程;发送测试告警须单独批准。

R7. 与恢复演练解耦

  • 本任务优先级为 P1、scope 为 operations,高于 P2 的 08-23-isolated-backup-restore-drill。
  • 演练任务保持 in_progress,明确被本任务阻塞;在新鲜原子批次形成并通过 24 小时身份门禁前不得继续实际恢复。
  • 既有恢复候选 SHA 保持有效,无需因本事件重新渲染;本任务不修改恢复 runner 或冒充恢复可用性结论。

Acceptance Criteria

  • AC1:只读调查首先明确生产本地是否存在通过完整合同校验的可用批次,并区分“异机副本缺失/生产单点”与“当前无已证明可用备份”;同时取得成功/失败运行的清理保留语义、两个 partial 的聚合停止偏移、真实 rsync 退出码、可靠失败持续时间(或明确未测原因)、生产空间与累积状态,形成证据支持的根因分类和过渡恢复点建议。
  • AC2:经单独批准的最小传输修复与容量处置完成,变更、回滚点和最终容量预算有脱敏证据;未修改正式归档、恢复门禁或业务数据。
  • AC3:ARM 形成至少一个新的完整原子归档批次,并通过 manifest、精确文件集、run id 配对、字节数和 SHA-256 校验;partial 不得冒充完成。
  • AC4:生产 daily/watchdog 与 ARM dead-man 的 timer 正常触发,最近 service 均 Result=success、exit 0,新鲜度状态与最新原子归档一致。
  • AC5:连续两个自然 daily 调度周期均产生新的完整原子归档并通过 AC3/AC4;手工补跑不计入这两个周期;两个周期的 ARM partial 数量/聚合字节和 ARM 容量趋势均已记录且未继续恶化。
  • AC6:生产容量达到经审阅的“一个完整新批次实际峰值 + 安全余量”预算,两个自然周期内无继续逼近失败线的趋势。
  • AC7:告警响应计时合同已启用;观察窗口内若出现真实告警/恢复通知,则同时记录发送调用时刻、人工确认时刻和响应延迟;若没有自然通知,明确标为未触发,不发送未批准的测试消息,也不把缺样本写成响应闭环已验证。
  • AC8:演练任务保留阻塞交叉引用;task validate、Trellis governance、流程合同、文档审计、敏感扫描和 git diff --check 通过。

Out of Scope

  • 本轮规划不授权连接生产/ARM、不授权只读调查执行,也不授权任何修复、清理、重跑或告警发送。
  • 不恢复数据库或附件,不启动隔离 OA,不修改恢复候选、migration、业务代码、生产数据库或业务附件。
  • 不轮换备份 SSH 密钥、不重建 receiver,除非后续只读证据推翻“初始认证已成功”的当前事实并重新审阅设计。
  • 不删除 ARM 正式归档或历史 partial;历史 partial 的清理须在身份与保留价值审阅后单独批准。
  • 不把一次手工成功、timer active、service 通用 exit 或 sent=true 单独作为结案依据。

Blocking Open Questions

  • 无。第一阶段只读调查、任何本地实现以及生产/ARM 写操作仍分别需要后续明确批准。

Test Plan

  • 本地使用合成 fixture 验证 partial 聚合比较、rsync 退出码映射、失败时长聚类、容量预算和敏感输出 allowlist。
  • 获批后对生产/ARM 只读采集 R2 字段,保持原始日志、路径、身份和业务数据不出远端私有边界。
  • 修复候选先通过 Bash/Python 语法、既有自动异机备份/receiver/dead-man 合同和回滚演练;实际变更另行批准。
  • 实际修复后校验新原子批次与三组 timer/service,并连续观察两个自然调度周期。
  • 运行 task validate、Trellis governance、process baseline、docs registry、敏感扫描和 git diff --check。