回滚手册
使回滚成一键、演练充分的行动使部署 5 分钟内可逆。
为什么
最快事件响应是回滚,但仅当回滚是练过的 30 秒命令。若回滚是 3 个月没人跑的多步手动流程,凌晨 3 点值班会花 20 分钟读 wiki、漏步、把宕机搞更糟。每部署须一键可逆(kubectl rollout undo、vercel --prod rollback、你平台等价物),且该命令须月度在 staging 测使首次愤怒中跑非 SEV1 时。一键回滚的团队报部署致宕机 5 分钟 MTTR;无它的团队报 45 分钟因回滚是压 力下研究项目。
何时使用
每部署须可逆。月度在 staging 测回滚;部署致事件首兆即在生产跑。
如何做
1. 使回滚单命令 - k8s:kubectl rollout undo deployment/checkout - Vercel:vercel --prod rollback - 自定义:指向 LB 上一镜像/标签的脚本 - 无多步 wiki;一命令、测过 2. 确保上一版本仍可用 - 保留最后 N(≥2)镜像/标签;别立即垃圾回收 - DB 迁移须向后兼容(expand-contract 模式)使回滚不丢数据 3. 月度在 staging 测回滚 - 部署 vN → 部署 vN+1 → 回滚到 vN → 验证 vN 服务流量 - 这是 10 分钟演练保持回滚路润滑 - 跟踪"回滚时间"作指标;目标 <2m 4. 事件开始决定回滚 vs 前进修复 - 部署致 + 无前进修复 → 立即回滚 - 配置致 + 前进修复 5m 内 → 前进修复 - 别辩论 20m;runbook 有决策树 5. 使回滚对有状态变更安全 - DB:用 expand-contract 迁移(加列、部署、回填、删旧 — 每步可逆) - 队列消息:旧版本须容忍新消息格式(否则不能回滚生产者)
示例
# 一键回滚(k8s): kubectl rollout undo deployment/checkout -n prod # 验证: kubectl rollout status deployment/checkout -n prod # 等部署 curl -s https://app.example.com/health # 确认 200 # 部署管道保留最后 5 镜像(别立即 GC): # gcr.io/app/checkout:v2.4.1 (当前) # gcr.io/app/checkout:v2.4.0 (上一 — 回滚目标) # gcr.io/app/checkout:v2.3.9 ... # gcr.io/app/checkout:v2.3.8 ... # gcr.io/app/checkout:v2.3.7 ... # DB 迁移(expand-contract、可逆): # 1. ADD COLUMN discount_code TEXT NULL (旧代码忽略它)← 部署 v2.4.1 # 2. 回填:UPDATE orders SET discount_code = ... WHERE ... # 3. 应用用 discount_code ← 部署 v2.4.2 # 4. (后)DROP old column ← 部署 v2.5 # 从步 3 回滚 → 步 2:应用忽略新列,安全 # 从步 4 回滚 → 步 3:旧列没了,不安全 → 别回滚过步 3 # 月度演练(staging): # 部署 v2.4.3-staging → 部署 v2.4.4-staging → 回滚 → 验证 v2.4.3 服务 # 指标:回滚时间 = 45s ✓(目标 <2m)
常见问题
- ⚠回滚是多步 wiki 非命令 — 值班花 20 分钟读并漏步,把宕机搞更糟。
- ⚠上一镜像部署后立即垃圾回收 — 回滚目标没了,唯一选项是压力下前进修复。
- ⚠DB 迁移不向后兼容 — 回滚会丢数据所以非选项,部署致宕机变 2 小时前进修复。
- ⚠回滚从不测 — 首次跑在 SEV1,笔误或过期配置使它失败,宕机翻倍。
最佳实践
- ✓使回滚单测试命令(kubectl rollout undo / vercel --prod rollback);无多步 wiki — 值班压力下不能读。
- ✓保留最后 ≥2 镜像/标签;别立即垃圾回收,否则回滚无目标。
- ✓用 expand-contract DB 迁移使每步可逆;不可逆迁移使回滚不可能并把 5m 宕机变 2h。
- ✓月度在 staging 演练回滚并跟踪回滚时间作指标;愤怒中首跑必非 SEV1 时。