《持续交付 发布可靠软件的系统方法》读书笔记

创建发布策略

当在项目一开始创建发布策略的第一个版本时,应该考虑下列内容:

  • 每个环境的部署和发布都是由谁负责的。
  • 创建一个资产和配置管理策略。
  • 部署时所用技术的描述,运维团队和开发团队应该对其达成共识。
  • 实现部署流水线的计划。
  • 枚举所有的环境,包括用于验收测试、容量测试、集成测试、用户验收测试的环境,以及每个构建在这些环境中的移动过程。
  • 描述在测试和生产环境中部署时应该遵循的流程,比如提交一个变更申请,以及申请授权等。
  • 对应用程序的监控需求,包括用于通知运维团队关于应用程序相关状态的 API 或服务。
  • 讨论部署时和运行时的配置方法如何管理,以及它们与自动化部署流程是如何关联在一起的。
  • 描述应用程序如何与所有外部系统集成。比如,在哪个阶段进行集成?作为发布过程里的一份子,如何对这种外部集成进行测试?一旦出现问题,运维人员如何与供应商进行沟通?
  • 如何记录日志详情,以便运维人员能够确定应用程序的状态,识别出错原因。
  • 制定灾难恢复计划,以便在灾难发生之后,可以恢复应用程序的状态。
  • 对软件的服务级别达成一致,比如,应用程序是否有像故障转移以及其他高可用性策略等方面的需求。
  • 生产环境的数量大小及容量计划:应用程序会创建多少数据?需要多少个日志文件或数据库?需要多少带宽或磁盘空间?客户对响应延迟的容忍度是什么?
  • 制订一个归档策略,以便不必为了审计或技术支持而保留生产数据。
  • 如何对生产环境进行首次部署。
  • 如何修复生产环境中出现的缺陷,并为其打补丁。
  • 如何升级生产环境中的应用程序以及迁移数据。
  • 如何做应用程序的生产服务和技术支持。

创建这个策略只是一个开始而已,随着项目的进行,它也会改变。发布策略的一个关键部分就是发布计划,它用来描述如何执行发布。

发布计划

通常来说,第一次发布风险最高,需要细致地做个计划。而这种计划活动的结果可能是产出一些文档、自动化脚本或其他形式的流程步骤(procedure),用来保证应用程序在生产环境上的部署过程具有可靠性和可重复性。除了在发布策略中的这些材料以外,还要包括以下内容:

  • 第一次部署应用程序时所需的步骤。
  • 作为部署过程的一部分,如何对应用程序以及它所使用的服务进行冒烟测试。
  • 如果部署出现问题,需要哪些步骤来撤销部署。
  • 对应用程序的状态进行备份和恢复的步骤是什么。
  • 在不破坏应用程序状态的前提下,升级应用程序所需要的步骤是什么。
  • 如果发布失败,重新启动或重新部署应用程序的步骤是什么。
  • 日志文件放在哪里,以及它包括什么样的信息描述。
  • 如何对应用程序进行监控。
  • 作为发布的一部分,对必要的数据进行迁移的步骤有哪些。
  • 前一次部署中存在问题的记录以及它们的解决方案是什么。

有时候,还要考虑一些其他方面的事情。例如,如果新系统是某个遗留系统的替代品,应该把向新系统迁移用户的步骤写下来,另外还有如何停止旧系统,特别是不要忘记制订一个回滚流程,以应对突发问题。

发布产品

对于商业产品软件来说,还有如下一些事情需要考虑:

  • 收费模式。
  • 使用许可策略。
  • 所用第三方技术的版权问题。
  • 打包。
  • 市场活动所需要的材料(印刷材料、网站、播客、博客、新闻发布会等)。
  • 产品文档。
  • 安装包。
  • 销售和售后支持团队的准备。

    应用程序的部署和晋级

    要让软件的部署活动能以一种可靠且一致的方式进行,其关键在于每次部署时都使用同样的实践方法,即使用相同的流程向每个环境进行部署,包括生产环境在内。在首次向测试环境部署时就应该使用自动化部署。写个简单的脚本来做这件事,而不是手工将软件部署到环境中。

    首次部署

    项目首个迭代的主要目标之一就是在迭代结束时,让部署流水线的前几个阶段可以运行,且能够部署并展示一些成果,即使可展示的东西非常少。尽管我们不建议让技术价值的优先级高于业务价值的优先级,但此时是个例外。

对发布过程进行建模并让构建晋级

随着应用程序变得越来越复杂,部署流水线的实现也会越来越复杂。
需要考虑的细节:

  • 为了达到发布质量,一个构建版本要通过哪些测试阶段(例如,集成测试、QA 验收测试、用户验收测试、试运行以及生产环境);
  • 每个阶段需要设置什么样的晋级门槛或需要什么样的签字许可;
  • 对于每个晋级门槛来说,谁有权批准让某个构建通过该阶段;

    部署回滚和零停机发布

    万一部署失败,回滚部署是至关重要的。在运行的生产环境中通过调试直接查找问题的这种做法几乎总会导致晚上加班、具有严重后果的错误和用户的不满。当出现问题时,你应该有某种方法恢复服务,以便自己能在正常的工作时间内调试所发现的错误。

声明两个重要的约束,首先是数据,如果发布流程会修改数据,回滚操作就比较困难。另一个是需要与其他系统集成。如果发布中涉及两个以上的系统,回滚流程也会变得比较复杂。

当制定发布回滚计划时,需要遵循两个通用原则。首先,在发布之前,确保生产系统的状态(包括数据库和保存在文件系统中的状态)已备份。其次,在每次发布之前都练习一下回滚计划,包括从备份中恢复或把数据库备份迁移回来,确保这个回滚计划可以正常工作。

通过重新部署原有的正常版本来进行回滚

如果你有自动化部署应用程序的流程,让应用程序恢复到良好状态的最简单方法就是从头开始把前一个没有问题的版本重新部署一遍。这包括重新配置运行环境,让它能够完全和从前一样。

零停机发布

零停机发布(也称为热部署),是一种将用户从一个版本几乎瞬间转移到另一个版本上的方法。更重要的是,如果出了什么问题,它还要能在瞬间把用户从这个版本转回到原先的版本上。

零停机发布的关键在于将发布流程中的不同部分解耦,尽量使它们能独立发生。尤其是,在升级应用程序之前,就应该能将应用程序所依赖的共享资源(比如数据库、服务和一些静态资源)的新版本放在适当的位置。

蓝绿部署

有两个相同的生产环境版本,一个叫做“蓝环境”,一个叫做“绿环境”。

系统的用户被引导到当前正在作为生产环境的绿环境中。现在我们要发布一个新版本,所以先把这个新版本发布到蓝环境中,然后让应用程序先热身一下(你想多长时间都行),这根本不会影响绿环境。我们可以在蓝环境上运行冒烟测试,来检查它是否可以正常工作。当一切准备就绪以后,向新版本迁移就非常简单了,只要修改一下路由配置,将用户从绿环境导向蓝环境即可。这样,蓝环境就成了生产环境。这种切换通常在一秒钟之内就能搞定。

在做这种蓝绿部署时,要小心管理数据库。通常来说,直接从绿数据库切换到蓝数据库是不可能的,因为如果数据库结构有变化的话,数据迁移要花一定的时间。解决这个问题的一种方法是在切换之前暂时将应用程序变成只读状态一小段时间。然后把绿数据库复制一份,并恢复到蓝数据库中,执行迁移操作,再把用户切换到蓝系统。如果一切正常,再把应用程序切换到读写方式。如果出了什么问题,只要把它再切回绿数据库就可以了。

金丝雀发布

金丝雀发布就是把应用程序的某个新版本部署到生产环境中的部分服务器中,从而快速得到反馈。这是一个能大大减少新版本发布风险的方法。

紧急修复

总会遇到这种情况:发现了一个严重的缺陷,必须尽快修复。此时,需要牢记在心的最重要的事情是:任何情况下,都不能破坏流程。紧急修复版本也要走同样的构建、部署、测试和发布流程,与其他代码变更没什么区别。

为什么这么说呢?因为我们看到过很多场合,修复版本直接被放到生产环境中,而产生一个未受控版本。这会导致两个不幸的后果。首先是这种紧急修改没有做适当的测试,可能引发回归问题,或者该补丁不但没有修复问题,反而引起了更严重的问题。

有时候并不真正需要紧急修复一个缺陷。你需要考虑多少人会受到缺陷的影响,这个缺陷是否经常发生,发生后对用户有多大的影响。如果缺陷只影响少数人,而且发生频率不高,影响较低,而部署一个新版本的风险相对较高的话,可能就没有必要做紧急修复了。当然,通过有效的配置管理和自动部署过程来减少部署风险还有一些争议。

持续部署

使用部署流水线,并让最后一步(部署到生产环境)也自动化。这样,如果某次提交的代码通过了所有的自动化测试,就直接部署到生产环境中。如果想让这种做法不引发问题,自动化测试(应该包括自动化的单元测试、组件测试、功能性和非功能性验收测试)就必须异乎寻常的强大,覆盖整个应用程序。必须先写所有的测试(包括验收测试),然后再写代码。这样你才能做到,只有用户故事完成的最后那次代码提交才能使验收测试通过。

持续部署可以与金丝雀发布结合使用。首先通过一个自动化过程将一个新版本发布给一小撮用户使用。一旦确认(可能是人为决策)新版本没有问题,就把它发布给所有的用户。由良好的金丝雀发布系统提供的这层安全网让持续部署的风险甚至更小。

小贴士和窍门

  • 真正执行部署操作的人应该参与部署过程的创建;
  • 记录部署活动;
  • 不要删除旧文件,而是移动到别的位置;
  • 部署是整个团队的责任;
  • 服务器应用程序不应该有 GUI;
  • 为新部署留预热期;
  • 快速失败;
  • 不要直接对生产环境进行修改;

    小结

    只要权限正确的话,部署流水线应该能够通过“单击按钮”就能将任意一个已通过前面几个阶段的构建版本部署到任意一种环境中。还应该让团队中的每个人都明确地看到哪个构建版本被部署到了哪个环境中,该构建版本包含哪些修改。

降低发布风险的最佳方法是真正地做发布演练。越频繁地将应用程序发布到不同的测试环境中越好。尤其是,你越频繁地将应用程序发布到新的测试环境上,这个过程就越可靠,从而在生产环境上发布时遇到问题的可能性就越小。

发布计划最关键的部分是将来自组织各部门参与交付的代表组织起来:构建、基础设施、运维团队、开发团队、测试团队、DBA 和技术支持团队。在整个项目周期中,这些人应该不断地交流,持续合作,从而使交付过程更加高效。

推荐阅读