⏪ 第14课:回滚策略

📚 核心概念

🎯 回滚策略:快速止血的艺术

当部署出现问题时,回滚速度直接影响故障时长。好的策略让你几分钟内恢复,不好的策略可能在恐慌中浪费数小时。

📋 回滚策略决策树

发现问题 → 评估影响
    ┌─────────┼─────────┐
    ▼                   ▼
 影响严重              影响可控
 (P0/P1)             (功能降级)
    │                   │
    ▼                   ▼
 立即回滚            金丝雀调权重
 (秒~分钟级)         (渐进修复)
    │                   │
    ▼                   ▼
 恢复后分析          持续监控

📝 回滚策略分类

策略速度数据影响适用场景
蓝绿回切秒级蓝绿部署环境
K8s Rollout Undo秒级K8s Deployment
Git Revert+重新部署分钟级代码级回退
镜像版本回退分钟级容器环境
数据库Schema回滚分钟~小时有风险含DB变更
Feature Flag关闭秒级特性开关控制

⌨️ 命令实操

1. Kubernetes回滚操作 ✅

K8s回滚
# 查看部署历史
kubectl rollout history deployment/myapp
# 查看特定版本详情
kubectl rollout history deployment/myapp --revision=3

# 回滚到上一版本
kubectl rollout undo deployment/myapp
# 回滚到指定版本
kubectl rollout undo deployment/myapp --to-revision=2
# 查看回滚状态
kubectl rollout status deployment/myapp

# 设置历史版本数量
kubectl patch deployment myapp -p '{{"spec":{{"revisionHistoryLimit":5}}}}'

# 紧急回滚脚本
cat > /usr/local/bin/k8s-rollback.sh << 'SCRIPT'
#!/bin/bash
set -euo pipefail
DEPLOY="${{1:?Usage: k8s-rollback  [ns] [rev]}}"
NS="${{2:-default}}"; REV="${{3:-}}"
echo "🚨 回滚 $DEPLOY..."
if [[ -n "$REV" ]]; then
    kubectl rollout undo deployment/"$DEPLOY" -n "$NS" --to-revision="$REV"
else
    kubectl rollout undo deployment/"$DEPLOY" -n "$NS"
fi
kubectl rollout status deployment/"$DEPLOY" -n "$NS" --timeout=120s
echo "✅ 回滚完成"
SCRIPT
chmod +x /usr/local/bin/k8s-rollback.sh

2. Git回滚与版本回退 ✅

Git回滚
# 回滚最近一次提交(保留历史)
git revert HEAD && git push origin main

# 回滚指定提交
git revert abc1234 && git push origin main

# 回滚多个提交(逆序)
git revert HEAD~3..HEAD --no-commit
git commit -m "revert: rollback last 3 commits" && git push

# 基于Tag回滚
git tag -l 'v*' --sort=-v:refname | head -5
git checkout v2.0.0

# GitHub Actions自动回滚Workflow
cat > .github/workflows/auto-rollback.yml << 'EOF'
name: Auto Rollback on Failure
on:
  issues:
    types: [labeled]
jobs:
  rollback:
    if: contains(github.event.label.name, 'rollback')
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with: {{fetch-depth: 0}}
    - name: Get previous tag
      id: prev
      run: echo "tag=$(git tag -l 'v*' --sort=-v:refname | sed -n '2p')" >> $GITHUB_OUTPUT
    - name: Rollback
      run: |
        kubectl set image deployment/myapp myapp=myregistry/myapp:${{ steps.prev.outputs.tag }}
        kubectl rollout status deployment/myapp --timeout=300s
EOF

3. 数据库迁移回滚 ✅

DB回滚
# Flyway undo迁移
cat > db/migration/U5__undo_add_phone.sql << 'EOF'
ALTER TABLE users DROP COLUMN IF EXISTS phone;
EOF
flyway undo -url="jdbc:postgresql://db:5432/mydb" -user=admin -password=secret

# Django迁移回滚
python manage.py migrate myapp 0004

# Rails迁移回滚
rails db:rollback STEP=3

# 最佳实践:Expand-Contract模式
# Step 1: Expand(加新列,兼容旧代码)
# ALTER TABLE users ADD COLUMN phone VARCHAR(20);
# Step 2: 切换应用代码到新版本
# Step 3: Contract(确认后删旧列)
# ALTER TABLE users DROP COLUMN old_phone;

4. Feature Flag快速回滚 ✅

Feature Flag
# LaunchDarkly风格Flag
cat > feature-flags.yaml << 'EOF'
flags:
  new-checkout:
    enabled: false
    rules:
    - variation: true
      percentage: 5
EOF

# 应用中检查Flag(Python)
# if ld_client.variation("new-checkout", user, False):
#     return new_flow(request)
# return old_flow(request)

# 紧急关闭Feature(秒级回滚)
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/default/new-checkout" \
  -H "Authorization: " \
  -H "Content-Type: application/json" \
  -d '{{"on": false}}'

# Unleash(开源Feature Flag)管理
curl -X POST "http://unleash:4242/api/admin/features/new-checkout/toggle/off" \
  -H "Authorization: " 

📐 架构图

⏪ 回滚策略全景

故障发现 → 评估影响
   ┌─────┼──────┐
   ▼     ▼      ▼
 P0紧急  P1重要  P2一般
   │     │      │
   ▼     ▼      ▼
Feature  K8s    Git
Flag关闭 Undo  Revert
(秒级)  (秒级) (分钟)
   └─────┼──────┘
         ▼
  数据库回滚?
  ├─ 无DB变更 → 完成 ✅
  ├─ Expand-Contract → 安全回滚
  └─ 破坏性变更 → 数据修复

🔧 故障排查

❌ K8s回滚后Pod CrashLoopBackOff

排查
kubectl get pods -l app=myapp
kubectl describe pod  | grep -A10 "Last State"
kubectl logs  --previous
# 常见:ConfigMap/Secret版本不匹配/DB Schema不兼容/镜像拉取失败
# 紧急:回滚到更早版本
kubectl rollout history deployment/myapp | head -10
kubectl rollout undo deployment/myapp --to-revision=1

❌ Feature Flag切换未生效

排查
# 检查Flag状态
curl -s "https://app.launchdarkly.com/api/v2/flags/default/new-checkout" \
  -H "Authorization: " | jq '.on'

# 常见原因:
# 1. 客户端缓存未刷新 → 重启应用
# 2. Flag规则优先级问题
# 3. 环境不匹配(staging vs production)
# 4. 用户Targeting规则覆盖了全局开关

🏆 成就解锁:回滚策略专家!

掌握K8s Rollout Undo、Git Revert、DB迁移回滚、Feature Flag秒级关闭——回滚不是失败,是工程智慧

📝 回滚检查清单

检查项确认内容负责人
回滚版本确认上一版本号/镜像Tag是否正确发布负责人
数据库兼容性回滚版本是否兼容当前DB SchemaDBA
配置文件同步ConfigMap/Secret是否需要同步回滚运维
缓存清理Redis/CDN缓存是否需要清理运维
监控验证回滚后错误率/延迟是否恢复正常SRE
通知相关方通知业务方、客服、管理层On-Call

K8s原生回滚

适用于Deployment滚动更新

GitOps回滚

适用于ArgoCD/Flux管理

Feature Flag回滚

适用于新功能开关

💡 回滚黄金法则:每次部署前都确认回滚方案,就像飞机起飞前确认逃生路线。