持续交付搞了半年,为什么发布还是像上刑?

🔑 关键词:持续交付,部署流水线,特性开关,数据库迁移,发布策略

📖 摘要:持续交付不是搭个Jenkins就完事。这篇聊聊真正卡住团队的几个隐蔽问题——数据库变更、特性开关滥用、以及把CD当成工具安装而不是流程改造。

去年我们团队把Jenkins换成了GitLab CI,流水线从原来的3个stage扩到9个stage,自动部署到测试环境,听起来挺像回事。结果半年下来,生产环境的发布频率从每周一次降到了每两周一次,事故率反而翻了一倍。后来复盘才发现,我们只是在工具层面实现了持续交付,真正的瓶颈根本不在工具上——数据库迁移永远需要DBA手动跑,特性开关越攒越多没人清理,每次发布前还要开两小时的预发验证会。持续交付最讽刺的地方在于:你越是把精力花在自动化流水线上,越容易忽略那些无法自动化的组织决策和人的行为习惯。

图片

对比一下我们之前用的传统发布模式:每个月固定两天发版,每次发布要冻结代码、提前准备回滚脚本、运维全程盯着终端。好处是流程简单清晰,坏处是任何紧急修复都要等下一次窗口。而持续交付宣称的优势是让发布变成低风险常规操作,但前提是你必须同时搞定三个东西:可重复的部署过程、一键回滚能力、以及让团队敢于频繁变更的心理安全网。我们当时只做到了第一条——把部署脚本写成了Ansible playbook,但回滚机制从来没真正演练过,DBA对自动执行ALTER TABLE极度不信任。所以表面上流水线是绿的,实际上每次发布前都要人工确认一堆东西,这跟以前的冻结期有什么区别?

图片

后来我们花了三个月拆解这些问题,发现最核心的是数据库变更和代码发布的生命周期不同步。代码可以同时存在多个版本,但数据库schema只有一个版本。我们试着用了Flyway做版本化管理,但第一次把migration脚本放进流水线就出事了——一个加索引的迁移在预发环境跑了18秒,到了生产跑了两分钟,直接导致线上请求堆积。后来才明白,必须把数据库变更拆成向前兼容的小步骤:先加可空列,再逐步填充数据,最后才加约束。这个教训比任何流水线优化都值钱。另外特性开关也是个坑,我们最多的时候代码里挂了47个开关,有些开关开了三个月都没人关,导致每次发布都要手动核对开关状态。后来定了规矩:开关必须有负责人、有创建时间、有预计关闭日期,超过两周没关的自动在周报里标红。

图片

如果你正在考虑引入持续交付,我的建议是别先买工具、别先搭流水线,先去看你上个季度发布失败的那一次,到底栽在什么环节。如果是环境配置差异,那就做基础设施即代码;如果是数据库问题,那就先搞迁移自动化;如果是业务方临时改需求,那要解决的其实是需求变更流程。持续交付的本质是把发布能力做成组织级的能力,而不是某个团队的工具选型。我们到现在也不敢说做得多好,只是最近一次发布,从点击按钮到全量上线用了22分钟,其中还包括了自动跑完的1200个回归测试。这个数字不算惊艳,但比起之前每次发布都像上刑,已经是天壤之别了。

图片

🏷️ 标签: