《持续交付》(Continuous Delivery)是Jez Humble和David Farley的经典著作出版于2010年是,DevOps和持续交付领域的奠基之作被很多人称为"DevOps圣经"。

这本书我早就听说过,但是一直没静下心来读最近项目在做CI/CD改造遇到了很多问题才想起来读这本经典花了一个月时间终于读完了收获很大。

很多以前模糊的概念变得清晰了很多以前困惑的问题找到了答案很多以前觉得不重要的事情意识到其实很关键。

今天想分享一下我读完《持续交付》最大的收获以及对我日常工作的启发。

一、对持续交付的核心理解

读这本书之前,我对持续交付的理解很肤浅以为就是自动化部署代码提交后自动构建测试部署到服务器就叫持续交付。

读完才发现持续交付远不止自动化部署这么简单它是一套完整的软件交付方法论和,实践体系涵盖了从需求到上线的整个流程。

持续交付的定义

书中对持续交付的定义是:"持续交付是一种软件开发的方法它让软件在整个生命周期中都保持在,可发布的状态通过自动化的构建测试部署流水线确保每次变更都能快速安全地交付到生产环境。"

这个定义有几个关键点:

  1. 软件始终保持可发布状态:这是持续交付的核心目标,不管什么时候想发布都能发布不用为了发布专门做准备不用冻结代码不用加班测试。
  2. 自动化的构建、测试、部署流水线:这是实现持续交付的手段通过自动化减少人为错误提高效率让交付过程可重复可靠。
  3. 每次变更都能快速安全地交付:这是持续交付的结果小步快跑每次变更小风险小能快速反馈快速修复。

持续交付 vs 持续部署

以前我总是混淆持续交付(Continuous Delivery)和持续部署(Continuous Deployment)读完才搞清楚区别。

  • 持续集成(Continuous Integration):代码提交后自动构建和,测试确保代码能正常集成不破坏构建。
  • 持续交付(Continuous Delivery):在持续集成的基础上自动把代码部署到预发布环境(或者,生产环境但需要手动确认)确保软件始终保持可发布状态发布是一个业务决策不是技术问题。
  • 持续部署(Continuous Deployment):在持续交付的基础上代码通过所有,自动化测试后自动部署到生产环境不需要手动确认每次变更都自动上线。

简单说持续交付是"能随时发布"持续部署是"每次变更都自动发布"持续部署比持续交付更进一步对自动化测试的要求更高。

这个区别对我启发很大我们团队之前,总说要做持续部署,但是实际上,我们的自动化测试覆盖率很低根本不具备持续部署的条件应该先做到持续交付让软件保持可发布状态再考虑持续部署。

二、自动化是持续交付的基石

这本书反复强调自动化的重要性自动化是持续交付的基石没有自动化就没有持续交付。

为什么需要自动化

  1. 减少人为错误:手动构建测试部署容易出错漏了一步参数错了环境不一样等等都会导致问题自动化能避免这些人为错误。
  2. 提高效率:手动流程慢每次发布都要花很多时间自动化能大大缩短交付时间从几天缩短到几分钟。
  3. 可重复:自动化流程每次都一样可重复不会,因为人不同而有差异确保交付过程一致可靠。
  4. 解放人力:自动化能把人从重复的繁琐的工作中解放出来做更有价值的事情,比如开发新功能优化架构等等。

哪些需要自动化

书中强调几乎所有重复的步骤都应该自动化:

  1. 构建自动化:代码提交后自动拉取代码编译打包不需要手动操作。
  2. 测试自动化:单元测试集成测试接口测试UI测试等等都应该自动化每次构建自动运行确保质量。
  3. 部署自动化:部署到开发环境测试环境预发布环境生产环境都应该自动化一键部署不需要手动操作。
  4. 环境配置自动化:环境的安装配置也应该自动化用基础设施即代码(Infrastructure as Code)比如AnsiblePuppetChef等等确保环境一致可重复。
  5. 数据库变更自动化:数据库的变更也应该自动化版本控制自动执行迁移脚本不要手动改数据库。

自动化测试的重要性

书中特别强调自动化测试的重要性自动化测试是持续交付的安全网没有足够的自动化测试就不敢频繁发布,因为怕出问题。

自动化测试应该有不同的层次形成测试金字塔:

  1. 单元测试:最底层数量最多速度最快测试单个函数,或者类应该占大部分70%左右。
  2. 集成测试:中间层测试模块之间,的交互数量适中速度适中占20%左右。
  3. 端到端测试:最顶层数量最少速度最慢测试整个系统从UI到数据库占10%左右。

这个测试金字塔对我启发很大我们团队之前,自动化测试主要是端到端的UI测试数量多速度慢不稳定经常,因为环境问题失败维护成本高效果不好。

读完才意识到应该多写单元测试和集成测试少写端到端测试单元测试速度快稳定维护成本低能快速反馈大部分问题端到端测试只需要覆盖核心业务流程就够了。

三、配置管理和环境管理

这本书花了很多篇幅讲配置管理和环境管理这是我以前忽视的地方读完才意识到这非常重要。

配置管理

配置管理包括代码配置环境的版本控制和管理核心原则:

  1. 一切都要版本控制:代码配置脚本数据库迁移环境配置等等一切都要放到版本控制系统(比如Git)里不要有东西只存在于某个人的电脑上,或者服务器上。
  2. 配置和代码分离:应用的配置(数据库连接API地址开关等等)应该和,代码分离不同环境用不同的配置不要把配置硬编码在代码里。
  3. 配置也要版本控制:配置也要版本控制和,代码一样有历史可追溯出了问题能回滚。
  4. 不要在运行时修改配置:不要在生产环境直接修改配置所有配置变更都应该通过版本控制和,自动化部署流程来做确保可追溯可回滚。

环境管理

环境管理是确保不同环境(开发测试预发布生产)一致可靠的关键。

  1. 环境要一致:开发测试预发布生产环境应该尽量一致操作系统软件版本配置等等都应该一样避免"在我机器上能跑"的问题。
  2. 用基础设施即代码:环境的创建和配置应该用代码来管理(Infrastructure as Code)比如AnsiblePuppetChefTerraform等等环境可重复可版本控制可回滚。
  3. 环境不要共享:每个环境应该独立不要多个项目共享一个环境避免互相干扰也方便管理。
  4. 环境要能快速创建:环境应该能快速创建和销毁需要新环境的时候,几分钟就能创建好不用花几天手动配置。

这部分对我启发很大我们团队之前,环境管理很混乱开发测试生产环境不一致配置散落在各个地方有人在代码里硬编码有人在服务器上直接改出了问题很难排查。

读完才意识到配置管理和环境管理是持续交付的基础基础不牢上面的自动化构建部署都做不好应该先把配置和,环境管理好再做上层的自动化。

四、数据库变更管理

这本书专门有一章讲数据库变更管理这也是我以前忽视的地方。

数据库变更是软件交付中最容易出问题的地方,因为数据库有状态不能像代码一样简单替换,而且数据库变更出错后果严重可能导致数据丢失,或者系统不可用。

数据库变更的原则

  1. 数据库变更也要版本控制:所有数据库变更脚本都要放到版本控制里和,代码一起管理有历史可追溯。
  2. 数据库变更要自动化:数据库变更应该自动执行不要手动执行SQL脚本用数据库迁移工具,比如FlywayLiquibase等等自动管理版本和执行。
  3. 数据库变更要向前兼容:数据库变更应该向前兼容也就是新的数据库结构要能支持旧的代码这样才能做到零停机部署先部署数据库变更(向前兼容)再部署代码最后清理旧的结构。
  4. 大表变更要小心:大表的变更(比如加字段改类型)可能会锁表导致系统不可用要用在线DDL工具,或者分步骤做避免影响生产。
  5. 数据迁移要测试:数据迁移脚本要在测试环境充分测试确保正确不会丢数据,或者产生脏数据。

这部分对我启发很大我们团队之前,数据库变更都是手动执行SQL脚本没有版本控制经常出现漏执行执行错的问题,而且大表变更经常导致系统卡顿甚至不可用。

读完才意识到数据库变更管理非常重要应该用迁移工具自动化管理所有,变更都版本控制向前兼容充分测试避免出问题。

五、分支策略和版本控制

这本书也讲了分支策略和版本控制的最佳实践。

分支策略

持续交付推荐用主干开发(Trunk-Based Development)也就是所有,人都在主干(master/main)上开发频繁提交小的变更不用长期的特性分支。

为什么推荐主干开发:

  1. 减少合并冲突:长期的特性分支和主干差异大合并的时候,冲突多难解决主干开发频繁提交小变更合并冲突少。
  2. 快速集成:代码频繁集成到主干能快速发现集成问题早发现早解决不会等到最后才发现大问题。
  3. 始终可发布:主干始终保持可发布状态随时能发布不用为了发布专门合并和,测试。

如果确实需要特性分支(比如大的功能开发周期长)应该用短生命周期的分支最多几天就合并回主干不要长期维护特性分支。

提交策略

  1. 小步提交:每次提交应该小做一件事不要一次提交一大堆改动这样出了问题容易定位和回滚。
  2. 提交信息清晰:提交信息应该清晰说明这次提交做了什么为什么做方便以后追溯和,理解。
  3. 不要提交半成品:不要提交不能运行的半成品代码提交前确保代码能编译通过基本测试通过不破坏构建。
  4. 用特性开关:大的功能开发中可以用特性开关(Feature Toggle)把未完成的功能隐藏代码提交到主干,但是不对外可见等完成了再打开开关。

这部分对我启发很大我们团队之前,用Git Flow每个功能一个分支开发完才合并经常出现合并冲突大集成问题多发布前要花很多时间合并和测试。

读完才意识到Git Flow太重了不适合持续交付应该改用更简单的主干开发,或者GitHub Flow小步提交频繁集成减少合并冲突和集成问题。

六、发布策略和回滚

这本书也讲了发布策略和回滚的最佳实践。

发布策略

  1. 蓝绿部署(Blue-Green Deployment):准备两套环境蓝和绿一套在,运行一套备用发布时把新版本部署到备用环境测试通过后切换流量到新环境出了问题快速切回旧环境。
  2. 金丝雀发布(Canary Release):先把新版本部署到一小部分服务器,或者一小部分用户观察没有问题再逐步扩大范围直到全量发布出了问题影响小能快速回滚。
  3. 滚动发布(Rolling Update):逐个,或者分批更新服务器先更新一部分验证没问题再更新下一批直到全部更新完不需要两套环境,但是回滚相对麻烦。

回滚

  1. 回滚要快:出了问题要能快速回滚到上一个稳定版本减少影响时间回滚应该是,一键的自动化的不要手动操作。
  2. 回滚要测试:回滚流程也要测试确保能正常回滚不要等到出了问题才发现回滚不了。
  3. 数据库回滚要小心:数据库回滚比代码回滚复杂,因为数据可能已经变了,所以数据库变更要向前兼容代码回滚了数据库不用回滚也能跑。

这部分对我启发很大我们团队之前,发布都是全量发布出了问题影响大回滚慢经常要加班修复读完才意识到应该用蓝绿部署,或者金丝雀发布降低发布风险出了问题影响小能快速回滚。

七、最大的收获和启发

读完《持续交付》我最大的收获和启发总结一下:

收获1:持续交付是一种文化不只是工具

以前我以为持续交付就是搭个Jenkins写个部署脚本就完事了读完才意识到持续交付更是一种文化和理念需要团队每个人都认同和参与开发测试运维都要转变思维共同对交付负责不是某一个人,或者某一个团队的事。

工具只是手段文化和理念才是核心没有文化支撑再好的工具也用不起来。

收获2:质量是每个人的责任

以前我们团队质量主要靠测试团队开发写完代码就扔给测试测试测出bug再回来改效率低质量也不好。

读完才意识到质量是每个人的责任开发要对自己的代码质量负责写单元测试做代码审查确保代码质量测试团队应该做更有价值的事情,比如探索性测试自动化测试框架建设等等而不是当人工QA。

收获3:小步快跑快速反馈

以前我们项目都是大版本开发几个月才发布一次每次发布都很痛苦问题多风险大加班多。

读完才意识到应该小步快跑频繁发布每次变更小风险小能快速得到用户反馈快速调整持续改,进而不是憋几个月发布一个大版本问题一大堆。

收获4:自动化一切

以前我们很多事情都是手动做手动构建手动测试手动部署效率低容易出错。

读完才意识到应该自动化一切能自动化的都自动化构建测试部署环境配置数据库变更等等都自动化减少人为错误提高效率把人解放出来做更有价值的事情。

收获5:持续改进

持续交付不是一次性的项目不是搭好流水线就完事了而是一个持续改进的过程需要不断优化流程工具实践提高交付效率和质量。

不要追求完美先做到基础的持续集成再做到持续交付再考虑持续部署一步步来持续改进。

八、写在最后

以上就是我读完《持续交付》最大的收获和启发。

这本书,虽然出版于2010年,但是里面的理念和实践在今天依然非常有价值甚至更有价值,因为现在软件交付越来越快用户要求越来越高持续交付已经成为了软件团队的必备能力。

如果你还没读过《持续交付》推荐你读一读特别是做DevOpsCI/CD的同学这本书会给你很多启发和指导。

如果你读过也推荐你重读一遍每次读都会有新的理解和收获,因为随着工作经验的增加对书中的理念和实践会有更深的理解。

最后用书中的一句话结束这篇文章:"持续交付的目标不是更快地发布软件而是更可靠地发布软件让发布变成一件平常的低风险的事情。"

愿每个软件团队都能做到持续交付让发布不再是噩梦而是一件平常的愉快的事情。