《持续交付 发布可靠软件的系统方法》读书笔记
当在项目一开始创建发布策略的第一个版本时,应该考虑下列内容:
创建这个策略只是一个开始而已,随着项目的进行,它也会改变。发布策略的一个关键部分就是发布计划,它用来描述如何执行发布。
通常来说,第一次发布风险最高,需要细致地做个计划。而这种计划活动的结果可能是产出一些文档、自动化脚本或其他形式的流程步骤(procedure),用来保证应用程序在生产环境上的部署过程具有可靠性和可重复性。除了在发布策略中的这些材料以外,还要包括以下内容:
有时候,还要考虑一些其他方面的事情。例如,如果新系统是某个遗留系统的替代品,应该把向新系统迁移用户的步骤写下来,另外还有如何停止旧系统,特别是不要忘记制订一个回滚流程,以应对突发问题。
对于商业产品软件来说,还有如下一些事情需要考虑:
要让软件的部署活动能以一种可靠且一致的方式进行,其关键在于每次部署时都使用同样的实践方法,即使用相同的流程向每个环境进行部署,包括生产环境在内。在首次向测试环境部署时就应该使用自动化部署。写个简单的脚本来做这件事,而不是手工将软件部署到环境中。
项目首个迭代的主要目标之一就是在迭代结束时,让部署流水线的前几个阶段可以运行,且能够部署并展示一些成果,即使可展示的东西非常少。尽管我们不建议让技术价值的优先级高于业务价值的优先级,但此时是个例外。
随着应用程序变得越来越复杂,部署流水线的实现也会越来越复杂。
需要考虑的细节:
万一部署失败,回滚部署是至关重要的。在运行的生产环境中通过调试直接查找问题的这种做法几乎总会导致晚上加班、具有严重后果的错误和用户的不满。当出现问题时,你应该有某种方法恢复服务,以便自己能在正常的工作时间内调试所发现的错误。
声明两个重要的约束,首先是数据,如果发布流程会修改数据,回滚操作就比较困难。另一个是需要与其他系统集成。如果发布中涉及两个以上的系统,回滚流程也会变得比较复杂。
当制定发布回滚计划时,需要遵循两个通用原则。首先,在发布之前,确保生产系统的状态(包括数据库和保存在文件系统中的状态)已备份。其次,在每次发布之前都练习一下回滚计划,包括从备份中恢复或把数据库备份迁移回来,确保这个回滚计划可以正常工作。
如果你有自动化部署应用程序的流程,让应用程序恢复到良好状态的最简单方法就是从头开始把前一个没有问题的版本重新部署一遍。这包括重新配置运行环境,让它能够完全和从前一样。
零停机发布(也称为热部署),是一种将用户从一个版本几乎瞬间转移到另一个版本上的方法。更重要的是,如果出了什么问题,它还要能在瞬间把用户从这个版本转回到原先的版本上。
零停机发布的关键在于将发布流程中的不同部分解耦,尽量使它们能独立发生。尤其是,在升级应用程序之前,就应该能将应用程序所依赖的共享资源(比如数据库、服务和一些静态资源)的新版本放在适当的位置。
有两个相同的生产环境版本,一个叫做“蓝环境”,一个叫做“绿环境”。
系统的用户被引导到当前正在作为生产环境的绿环境中。现在我们要发布一个新版本,所以先把这个新版本发布到蓝环境中,然后让应用程序先热身一下(你想多长时间都行),这根本不会影响绿环境。我们可以在蓝环境上运行冒烟测试,来检查它是否可以正常工作。当一切准备就绪以后,向新版本迁移就非常简单了,只要修改一下路由配置,将用户从绿环境导向蓝环境即可。这样,蓝环境就成了生产环境。这种切换通常在一秒钟之内就能搞定。
在做这种蓝绿部署时,要小心管理数据库。通常来说,直接从绿数据库切换到蓝数据库是不可能的,因为如果数据库结构有变化的话,数据迁移要花一定的时间。解决这个问题的一种方法是在切换之前暂时将应用程序变成只读状态一小段时间。然后把绿数据库复制一份,并恢复到蓝数据库中,执行迁移操作,再把用户切换到蓝系统。如果一切正常,再把应用程序切换到读写方式。如果出了什么问题,只要把它再切回绿数据库就可以了。
金丝雀发布就是把应用程序的某个新版本部署到生产环境中的部分服务器中,从而快速得到反馈。这是一个能大大减少新版本发布风险的方法。
总会遇到这种情况:发现了一个严重的缺陷,必须尽快修复。此时,需要牢记在心的最重要的事情是:任何情况下,都不能破坏流程。紧急修复版本也要走同样的构建、部署、测试和发布流程,与其他代码变更没什么区别。
为什么这么说呢?因为我们看到过很多场合,修复版本直接被放到生产环境中,而产生一个未受控版本。这会导致两个不幸的后果。首先是这种紧急修改没有做适当的测试,可能引发回归问题,或者该补丁不但没有修复问题,反而引起了更严重的问题。
有时候并不真正需要紧急修复一个缺陷。你需要考虑多少人会受到缺陷的影响,这个缺陷是否经常发生,发生后对用户有多大的影响。如果缺陷只影响少数人,而且发生频率不高,影响较低,而部署一个新版本的风险相对较高的话,可能就没有必要做紧急修复了。当然,通过有效的配置管理和自动部署过程来减少部署风险还有一些争议。
使用部署流水线,并让最后一步(部署到生产环境)也自动化。这样,如果某次提交的代码通过了所有的自动化测试,就直接部署到生产环境中。如果想让这种做法不引发问题,自动化测试(应该包括自动化的单元测试、组件测试、功能性和非功能性验收测试)就必须异乎寻常的强大,覆盖整个应用程序。必须先写所有的测试(包括验收测试),然后再写代码。这样你才能做到,只有用户故事完成的最后那次代码提交才能使验收测试通过。
持续部署可以与金丝雀发布结合使用。首先通过一个自动化过程将一个新版本发布给一小撮用户使用。一旦确认(可能是人为决策)新版本没有问题,就把它发布给所有的用户。由良好的金丝雀发布系统提供的这层安全网让持续部署的风险甚至更小。
只要权限正确的话,部署流水线应该能够通过“单击按钮”就能将任意一个已通过前面几个阶段的构建版本部署到任意一种环境中。还应该让团队中的每个人都明确地看到哪个构建版本被部署到了哪个环境中,该构建版本包含哪些修改。
降低发布风险的最佳方法是真正地做发布演练。越频繁地将应用程序发布到不同的测试环境中越好。尤其是,你越频繁地将应用程序发布到新的测试环境上,这个过程就越可靠,从而在生产环境上发布时遇到问题的可能性就越小。
发布计划最关键的部分是将来自组织各部门参与交付的代表组织起来:构建、基础设施、运维团队、开发团队、测试团队、DBA 和技术支持团队。在整个项目周期中,这些人应该不断地交流,持续合作,从而使交付过程更加高效。