4.1 KiB
4.1 KiB
id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week, order
| id | title | type | domain | stack | tags | level | prerequisites | est_hours | related | week | order | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| devops.cicd.release-rollback | 发布与回滚:镜像标签、环境、滚动 / 蓝绿 / 金丝雀、数据库迁移 | lesson | devops |
|
|
intermediate |
|
3 |
|
|
2 |
发布与回滚:镜像标签、环境、滚动 / 蓝绿 / 金丝雀、数据库迁移
解释说明
不可变产物:一次构建出镜像(标签 = 提交哈希或版本号),测试、预发、生产用同一个镜像,只是配置不同。这样测试过的东西就是上线的东西,回滚就是切回上一个标签。
环境:开发 → 测试 → 预发(和生产配置尽量一致)→ 生产。配置通过环境变量注入,不打进镜像。
发布策略
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 重建 | 停掉旧版本再启动新版本 | 最简单 | 有停机 |
| 滚动 | 逐台替换实例 | 无停机、资源占用少 | 新旧版本同时在线一段时间;回滚也要逐台 |
| 蓝绿 | 准备一整套新环境,验证后切流量 | 切换和回滚都是瞬间 | 需要双倍资源 |
| 金丝雀 | 先给小部分流量,观察指标后逐步放大 | 风险最小 | 需要流量控制能力和监控 |
回滚:应用回滚 = 部署上一个镜像标签。难点在数据库:新版本已经改了表结构,旧版本可能跑不起来。
数据库迁移的原则:迁移脚本放在仓库里、有版本号、由工具执行(Go 的 golang-migrate / goose,Python 的 Alembic);每次迁移都要向后兼容——新旧代码都能在新表结构上运行。删除或重命名字段要分多次发布(“扩展 → 迁移 → 收缩”):
- 加新字段(旧代码不受影响),新代码同时写新旧字段;
- 回填历史数据,新代码改为读新字段;
- 确认不再回滚到旧版本后,再删除旧字段。
特性开关:代码先上线但功能默认关闭,通过配置打开;出问题直接关开关,比回滚代码更快。
案例
一次发布要把 users.name 改名为 display_name,迁移脚本直接执行了 RENAME COLUMN。发布后发现新版本有 bug,回滚到旧版本——旧代码找不到 name 字段,全站报错,故障时间翻倍。按“扩展 → 迁移 → 收缩”分三次发布就能避免。
代码示例
单机部署 + 健康检查 + 失败自动回滚(完整脚本 examples/pipeline/deploy.sh):
previous="$(cat "$STATE_FILE" 2>/dev/null || true)" # 上一次成功部署的标签
deploy "$IMAGE_TAG"
if healthy; then
echo "$IMAGE_TAG" > "$STATE_FILE"
else
echo "健康检查失败,回滚到 $previous" >&2
[[ -n "$previous" ]] && deploy "$previous"
exit 1
fi
“扩展 → 迁移 → 收缩”的迁移脚本(PostgreSQL):
-- 第 1 次发布:扩展(旧代码不受影响)
ALTER TABLE users ADD COLUMN display_name TEXT;
-- 第 2 次发布前:回填(大表要分批执行)
UPDATE users SET display_name = name WHERE display_name IS NULL;
-- 第 3 次发布:确认不再回滚到读 name 的版本后,收缩
ALTER TABLE users DROP COLUMN name;
易错点
- 每个环境重新构建镜像:测试过的和上线的不是同一个东西。
- 迁移不向后兼容:应用无法回滚。
- 应用启动时自动执行破坏性迁移:多实例同时启动会并发迁移;迁移失败导致所有实例起不来。迁移作为单独的发布步骤执行。
- 只看“部署成功”不看业务指标:容器起来了不代表功能正常。发布后观察错误率、延迟、关键业务指标。
- 回滚流程从来没有演练过:真出事时脚本跑不通。
- 特性开关从不清理:代码里分支越来越多。功能稳定后删除开关。
面试常问
见 CI/CD 面试题:蓝绿和金丝雀的区别、怎么回滚、数据库变更怎么做到可回滚。