6.3. 发布与变更:灰度、特性开关与回滚
发布不是「把镜像推上去」,而是一次受控的变更:谁批准、影响哪些用户、失败如何回滚、数据库能否兼容。把发布当成工程问题,而不是勇气问题。
- 层级:
L4 · 实战
- 难度:
进阶
- 预计:
45 分钟
- 前置:
Deployment、GitOps、可观测性
6.3.1. 发布单元
一次发布至少包含四类变更:
变更 |
例子 |
回滚方式 |
|---|---|---|
应用 |
新镜像 |
切回旧 digest |
配置 |
ConfigMap/Secret/values |
回滚 Git commit |
数据库 |
加字段/索引/迁移 |
兼容性设计 + 反向迁移 |
基础设施 |
节点池/网络/CRD |
基础设施回滚计划 |
只回滚应用、不回滚数据库,是最常见的发布事故来源。数据库迁移必须遵循 expand/contract:先加新字段(expand),双写/回填,再切读,最后删旧字段(contract)。
6.3.2. 环境晋级
dev → staging → prod
dev:每次合并自动部署,快速反馈。
staging:与生产同构,跑 E2E、性能、安全扫描。
prod:人工审批或自动策略(SLO 达标 + 变更窗口)。
环境差异用 Helm values/Kustomize overlay 管理,镜像 digest 保持一致。
6.3.3. 渐进式发布
金丝雀:5% → 25% → 50% → 100%,每步看错误率/延迟。
蓝绿:两套环境,切流量;回滚快,但资源翻倍。
特性开关:代码已部署,功能按用户/租户开启;适合长期灰度。
影子流量:复制生产流量到新版本,不影响用户;适合高风险变更。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: demoapp
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 5m}
- setWeight: 100
没有指标分析的灰度只是「慢一点的全量发布」。至少接错误率与 P95 延迟两个指标。
6.3.4. 数据库迁移
Expand:加字段/表,旧代码仍可运行。
Dual write:新旧字段同时写,校验一致性。
Backfill:批量回填历史数据。
Switch read:读新字段,观察。
Contract:删除旧字段/代码。
迁移脚本要幂等、可重入;大表加索引用在线 DDL 或分批,避免锁表。回滚不是「执行反向 SQL」这么简单,必须提前演练。
6.3.5. 变更管理
变更单/PR 记录:改什么、为什么、影响面、回滚步骤、验证指标。
冻结窗口:大促、财务结账、重大节假日避免高风险变更。
发布负责人(Release Manager)与值班(On-call)要分离,避免既发布又救火。
发布后 30 分钟是观察期,不要立刻下班。
6.3.6. 实验:一次可回滚的发布
kubectl argo rollouts set image demoapp demoapp=ghcr.io/example/demoapp:v2.0
kubectl argo rollouts get rollout demoapp --watch
# 如果错误率上升
kubectl argo rollouts abort demoapp
kubectl argo rollouts undo demoapp
数据库实验:先加 email_v2 字段,双写并回填,再切读,最后删旧字段。每一步都能独立回滚。
6.3.7. 验证清单
发布有明确的变更说明与回滚步骤。
镜像使用 digest,配置在 Git 中。
灰度有指标分析,失败自动/手动 abort。
数据库迁移遵循 expand/contract,回滚已演练。
发布后观察期与值班安排明确。
变更窗口避开业务高峰。
6.3.8. 排错表
现象 |
原因 |
处理 |
|---|---|---|
灰度卡住 |
没有 promote/分析失败 |
|
回滚后仍报错 |
数据库 schema 不兼容 |
用 expand/contract,先回滚应用再处理数据 |
配置未生效 |
ConfigMap 未更新/Pod 未重启 |
|
只有部分用户异常 |
灰度规则/缓存/租户 |
查 header/用户分群与缓存键 |
发布后延迟升高 |
新版本资源不足/连接池 |
看指标,调 resources/HPA |
6.3.9. 进阶挑战
用 Argo Rollouts + Prometheus 做自动金丝雀。
用特性开关控制一个新功能,按租户灰度。
设计一次「加字段 + 双写 + 回填 + 切读 + 删字段」的迁移。
写一份发布检查表,覆盖应用、配置、数据库、基础设施。
6.3.10. 小结
发布是受控变更,不是一次
kubectl apply。应用、配置、数据库、基础设施要分别设计回滚。
灰度必须绑定指标,否则只是延迟切换。
数据库迁移用 expand/contract,先兼容再清理。