跳转到内容
use-cases / snapshot-before-migration / hero
USE CASE / SNAPSHOT BEFORE MIGRATION

在每晚迁移前给容器拍快照

加一条 hoody-cron 条目,在 03:00 迁移作业前 5 分钟触发。它 curl 快照 URL,并把产物标记为回滚点。如果迁移失败,一条 PATCH 就能在 30 秒内恢复。

use-cases / snapshot-before-migration / mechanism

两个 URL,一个睡前习惯

cron 服务调度一条 curl。快照服务负责冻结。两者都不知道五分钟后会跑迁移作业——这正是关键。

POST cron/entries
调度器
# register the recurring snapshot job (one-time setup)
curl -X POST \
  cron.containers.hoody.com/users/root/entries \
  -H "Content-Type: application/json" \
  -d '{
    "schedule": "55 2 * * *",
    "command": "curl -X POST $SNAP_URL -d '{\"alias\":\"rollback-point\"}'",
    "comment": "pre-migration snapshot"
  }'
FIRES
POST containers/[id]/snapshots
冻结器
# what the cron entry curls every night at 02:55 UTC
curl -X POST \
  api.hoody.com/api/v1/containers/$ID/snapshots \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"alias": "rollback-point", "expiry": 7}'

# response from the snapshots service
200 OK · snap-2026-05-04 created in 8s

cron 条目是 Hoody 某个 Postgres 表里的一行。快照 URL 把内容寻址的 blob 写入容器存储后端。两者都持久、都有版本,都不需要在你的笔记本上保留长进程。

use-cases / snapshot-before-migration / anatomy

昨夜的解剖

四个时刻,四个 URL,安全网与变更之间隔着五分钟。迁移在多数工程师第一个闹钟响起前就完成了。

0102:55:00ZCron 触发schedule: 55 2 * * *
0202:55:08Z快照落盘alias rollback-point
0303:00:00Z迁移运行ALTER TABLE invoices
0403:01:42Z审计闭环快照保留 7 天

如果第 03 步失败,回滚就是 `PATCH /snapshots/snap-2026-05-04`,你回到了 02:55:08Z。上方的审计时间线就是同一份数据,以 JSON 形式提供。

use-cases / snapshot-before-migration / powers

这种形状解锁了什么

不是快照本身,是这种形状:在变更之前就存在的备份,以 URL 寻址,名字带着今天的日期。

01 / 安全

备份恰好在变更之前 5 分钟

大多数事故复盘都以“我们忘了备份”开头。当备份是一条 cron 条目,你忘不了。02:55 的快照就是 runbook 的第一句话——已经提前写好。

02 / 速度

回滚是一次 PATCH,不是 40 步

恢复 snap-2026-05-04 是对 api.hoody.com 的一次 HTTP 调用。容器在 30 秒内回到 02:55:08Z 的状态。无工单,无 on-call 升级,无“谁还有 AWS 控制台”。

03 / 闲置成本

如果迁移成功,快照不花钱

快照按内容寻址,以增量形式存储。你只为 412 MB 的增量(叠在未变的基础磁盘上)付费,且只在 7 天保留窗口内付。成功的迁移几乎不留痕。

use-cases / snapshot-before-migration / rollback

回滚:之前 vs 之后

过去的 runbook 是什么样,而当快照以今天的日期命名、以 URL 寻址时,它收缩成什么样。

OLD RUNBOOK9 个手动步骤,20-40 分钟,1-2 个人
  • 01
    呼叫 on-call DBA,确认迁移搞挂了生产中位:4 分钟确认
  • 02
    在 AWS 控制台找最近的备份祈祷它还不到 24 小时
  • 03
    起一个恢复实例,等它上线db.r6g.xlarge 上 8-15 分钟
  • 04
    用手写的 DOWN 脚本手动反转 ALTER TABLE前提是 DOWN 脚本存在,而它通常不存在
  • 05
    重启应用服务器,刷缓存,盯错误率顺手写复盘
ops@acme 2024 事故平均回滚时间:27 分钟
NEW RUNBOOK1 次 HTTP 调用,~30 秒,0 个人
# rollback last night's migrationcurl -X PATCH api.hoody.com/api/v1/containers/$ID/snapshots/snap-2026-05-04# response200 OK · container reverted to snap-2026-05-04 in 28s
PATCH 是幂等且可逆的

右栏新出现的内容不是工具,而是 runbook 里的一句话。这句话不再以“先做备份”开头,因为备份已经存在。

use-cases / snapshot-before-migration / punchline

回滚方案,就是你预先调度好的一个 URL。

之前:一份没人读的 Notion 页面之后:cron 里的一行,加对象存储里的一个 blob
first, take a backuprunbook 的第一句话,03:02 由疲惫的人手动执行
备份已经存在,以今天的日期命名,在变更前 5 分钟拍下runbook 的第一句话,由一条 cron 条目提前写下
查看快照 API
use-cases / snapshot-before-migration / replaces

它替代了什么

围绕迁移前备份的种种繁琐仪式。安排好快照,然后安心睡过迁移窗口。

  • 手动迁移前快照02:54 起床去点备份按钮
  • Runbook 检查清单条目14 步里第 1 步,而页面没人找得到
  • 回滚的 on-call 待命花钱让工程师等待空气
  • 上线前临时跑 pg_dump祈祷你没忘,祈祷它跑完了
  • "我们小心点就行" 的发布把事故运出去的乐观主义
  • AWS RDS 自动快照固定 5 分钟窗口,按 GB-day 计费
use-cases / snapshot-before-migration / cta

回滚方案,就是你预先调度好的一个 URL。

阅读快照参考
use-cases / snapshot-before-migration / related

阅读其他内容