跳转至

ExitVideo-Bot · Release 发布手册

版本发布全过程的操作手册。涵盖 Semver / 金丝雀发布 / 回滚 / 异常处理。


🎯 发布原则

  1. 可回滚:每次发布必须能在 5 分钟内回滚到上一版本
  2. 金丝雀:所有生产发布必须经过 5% → 25% → 50% → 100% 灰度
  3. 不破坏:发布期间 SLO 指标不允许恶化 >10%
  4. 可追溯:每次发布必须有 GitHub Release 记录 + Slack 通知

📅 发布类型

类型 频率 审批 是否需 RC 全自动
Patch (v1.2.3) 每周 TL 否 是
Minor (v1.3.0) 每月 TL + PM 是(RC 3 天) 部分
Major (v2.0.0) 每季 TL + CTO + PM 是(3 个 RC) 否(手动)
Hotfix (v1.2.4) 紧急 oncall TL 否 是

🚀 流程总览

1. PR 合并到 main
       ↓
2. CI: lint + test + smoke + docker build
       ↓
3. CI: build-and-push → GHCR (tag=<sha>)
       ↓
4. Image Updater 改 Helm values(3 分钟内)
       ↓
5. ArgoCD 同步 + Argo Rollouts 金丝雀
       ↓
6. Analysis 模板通过 → 自动 promote
       ↓
7. 监控 30 分钟无降级 → 完成
       ↓
8. GitHub Release 自动创建 + Slack 通知

🔧 Patch 发布(每周)

前置准备

# 1. 确认 main 分支 CI 绿色
gh pr checks --watch

# 2. 确认 staging 环境已 soak ≥ 24h
# Grafana → SLO Dashboard → staging

触发发布

# 选项 A:推 tag 触发 release.yml workflow
git tag v1.2.3
git push origin v1.2.3

# 选项 B:手动触发 release workflow
gh workflow run release.yml -f version=v1.2.3 -f channel=stable

自动化执行(CI 自动完成)

  1. CI 触发:release.yml 工作流自动启动
  2. 测试:完整 pytest + smoke
  3. 构建不可变镜像:
  4. ghcr.io/<owner>/exitvideo-bot:v1.2.3
  5. ghcr.io/<owner>/exitvideo-bot:v1.2
  6. ghcr.io/<owner>/exitvideo-bot:v1
  7. ghcr.io/<owner>/exitvideo-bot:latest
  8. Cosign 签名:SLSA Level 3 keyless
  9. 触发 Image Updater:Helm values 改 tag
  10. ArgoCD 同步 + 金丝雀发布:
  11. 5% → 暂停 5 分钟
  12. 25% → 暂停 5 分钟
  13. 50% → 暂停 5 分钟
  14. 100%
  15. Analysis 模板(每次 pause 前):
  16. 成功率 > 99.5%
  17. P99 < 500ms
  18. CPU/Memory 不超过 80%
  19. GitHub Release + Changelog 自动生成
  20. Slack 通知:#releases 频道

发布完成确认

# 1. 检查 Argo Rollouts 状态
kubectl argo rollouts get rollout exitvideo-bot-api -n exitvideo-bot
# 期望:Status: Healthy, Current Step: 100%

# 2. 检查所有 deployment 都升级
kubectl get deploy -n exitvideo-bot -o jsonpath="{.items[*].spec.template.spec.containers[0].image}"
# 期望:所有镜像都是新版本

# 3. Grafana SLO Dashboard 确认
make grafana-ui
# 期望:可用性 / P99 / 错误率 全部正常

🎯 Minor / Major 发布(含 RC)

RC 流程(仅 Minor / Major)

# 1. 发布 RC.1
git tag v2.0.0-rc1
git push origin v2.0.0-rc1
# → 自动发布到 staging 环境

# 2. soak 3 天
# 3. 修复 bug → RC.2 → soak 3 天
git tag v2.0.0-rc2
git push origin v2.0.0-rc2

# 4. RC 通过后发布正式版
git tag v2.0.0
git push origin v2.0.0

RC vs Stable 区别: - RC 镜像 tag 不覆盖 latest(避免污染) - RC 镜像推送到 staging 集群,不推 prod - RC 默认 24 小时无异常 → 自动 promote 到 stable


⏪ 4. 异常回滚

触发条件

任一条件满足,立即回滚:

  • [ ] API 错误率 > 1%(5 分钟平均)
  • [ ] API P99 > 1s(5 分钟平均)
  • [ ] Pod CrashLoopBackOff > 10%
  • [ ] Database connection error > 5/s
  • [ ] 任何 P0/P1 用户感知问题
  • [ ] Analysis 模板 fail

自动回滚(Argo Rollouts)

Analysis 模板 fail → Argo Rollouts 自动 abort → 流量回退到 stable 版本。

配置(infra/argo-rollouts/analysis-templates.yaml):

- name: success-rate
  spec:
    metrics:
      - name: success-rate
        provider: prometheus
        inlineResponseTemplate: |
          sum(rate(http_requests_total{status!~"5..", rollout="exitvideo-bot-api"}[5m]))
          /
          sum(rate(http_requests_total{rollout="exitvideo-bot-api"}[5m]))
        successCondition: result >= 0.995
        failureLimit: 2

手动回滚

# 选项 A:ArgoCD rollback(推荐,5 秒回退)
argocd app rollback exitvideo-bot-prod

# 选项 B:手动改 Helm values
argocd app set exitvideo-bot-prod -p image.tag=v1.2.2
argocd app sync exitvideo-bot-prod

# 选项 C:Argo Rollouts 手动 abort
kubectl argo rollouts abort exitvideo-bot-api -n exitvideo-bot
# → 自动回退到上一个 stable revision

回滚后必须做

# 1. 立即锁 tag,避免再被同步
kubectl annotate application exitvideo-bot-api -n argocd \
  argocd.argoproj.io/paused=true --overwrite

# 2. Slack 通知
make release-rollback-notify VERSION=v1.2.3 STATUS=auto

# 3. 48 小时内出 Postmortem
# 模板:infra/ops/postmortem-template.md

# 4. 修复后发新版本(v1.2.4 或 v2.0.1)

⏸ 5. Argo Rollouts 卡在 Pause

症状:kubectl argo rollouts get rollout 显示 Status: Paused

诊断:

kubectl argo rollouts get rollout exitvideo-bot-api -n exitvideo-bot --watch=false
# 输出包含:Current Step / Pause Reason / Age

修复:

# 选项 A:手动 promote
kubectl argo rollouts promote exitvideo-bot-api -n exitvideo-bot

# 选项 B:手动 abort(紧急)
kubectl argo rollouts abort exitvideo-bot-api -n exitvideo-bot

# 选项 C:如果 Analysis 卡太久,skip
# 修改 Analysis 模板的 failureLimit / delay

📦 6. Helm chart 升级失败

症状:helm upgrade 报错 / kubectl apply 失败

诊断:

# 1. 看 ArgoCD 同步错误
kubectl describe application exitvideo-bot-api -n argocd | grep -A 10 "Sync Status"

# 2. 看 helm release 历史
helm history exitvideo-bot-api -n exitvideo-bot

# 3. 看具体错误
kubectl get events -n exitvideo-bot --sort-by=".lastTimestamp" | tail -20

修复:

# 选项 A:helm rollback
helm rollback exitvideo-bot-api -n exitvideo-bot 1

# 选项 B:ArgoCD 重试
argocd app sync exitvideo-bot-api --retry-limit=5

# 选项 C:如果 chart 本身 bug,revert chart 修改
git revert <commit>
git push origin main
# → 触发自动 release

🌙 7. 灰度发布到特定租户

场景:仅给企业租户发新版本,普通租户保持稳定

# 1. 创建专门的 Application(仅企业租户 namespace)
kubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: exitvideo-bot-api-enterprise
  namespace: argocd
spec:
  source:
    repoURL: ghcr.io/<owner>/exitvideo-bot
    chart: exitvideo-bot
    targetRevision: v2.0.0-rc1
  destination:
    server: https://kubernetes.default.svc
    namespace: exitvideo-bot-enterprise
  syncPolicy:
    automated:
      selfHeal: true
EOF

# 2. soak 1 周

# 3. 通过后 promote 到主 Application
kubectl patch application exitvideo-bot-api -n argocd --type merge \
  -p '{"spec":{"source":{"targetRevision":"v2.0.0"}}}'

📋 发布前 CheckList

  • [ ] main 分支 CI 全绿
  • [ ] staging 已 soak ≥ 24h(Minor/Major ≥ 3 天)
  • [ ] 所有 PR 已合并到 main
  • [ ] CHANGELOG.md 已更新
  • [ ] 已知 issue 已确认不阻塞发布
  • [ ] oncall 工程师已通知(Slack #releases)
  • [ ] 监控告警已确认(PagerDuty 测试)
  • [ ] 备份已就绪(make db-backup)
  • [ ] Vault 密钥无即将过期(>30 天)

📋 发布后 CheckList

  • [ ] Argo Rollouts 已到 100%
  • [ ] 所有 Pod 镜像 tag 正确
  • [ ] SLO Dashboard 全部正常
  • [ ] Smoke 测试通过(pytest tests/e2e/)
  • [ ] Slack #releases 已通知
  • [ ] GitHub Release 已创建
  • [ ] CHANGELOG.md 已发布
  • [ ] 后 24h 监控指标无异常

🔗 相关资源


最后更新:第 13 轮 Runbook 补写 覆盖场景:4 类发布 / 自动 + 手动回滚 / 灰度策略 / Pre + Post CheckList