持续交付中常见的反模式
到目前为止,DevOps还没有一个通用的定义,没有一种规范说,如果你做到了某某某事,就做到了DevOps。但是,有一些常见的反模式,只要做了,就能说明你没有做到DevOps。
1、手工部署
特征
- 有一份非常详尽的文档,该文档描述了执行步骤及每个步骤中易出错的地方。
- 以手工测试来确认该应用程序是否运行正确。
- 在发布当天开发团队频繁地接到电话,客户要求解释部署为何会出错。
- 在发布时,常常会修正一些在发布过程中发现的问题。
- 如果是集群环境部署,常常发现在集群中各环境的配置都不相同,比如应用服务器的连接池设置不同或文件系统有不同的目录结构等。
- 发布过程需要较长的时间(超过几分钟)。
- 发布结果不可预测,常常不得不回滚或遇到不可预见的问题。
- 发布之后凌晨两点还睡眼惺忪地坐在显示器前,绞尽脑汁想着怎么让刚刚部署的应用程序能够正常工作。
为什么需要自动化部署
- 如果部署过程没有完全自动化,每次部署时都会发生错误。唯一的问题就是“该问题严重与否”而已。即便使用良好的部署测试,有些错误也很难追查。
- 如果部署过程不是自动化的,那么它就既不可重复也不可靠,就会在调试部署错误的过程中浪费很多时间。
- 手动部署流程不得不被写在文档里。可是文档维护是一项复杂而费时的任务, 它涉及多人之间的协作,因此文档通常要么是不完整的,要么就是未及时更新
的,而把一套自动化部署脚本作为文档,它就永远是最新且完整的,否则就无 法进行部署工作了。 - 自动部署本质上也是鼓励协作的,因为所有内容都在一个脚本里,一览无遗。要读懂文档通常需要读者具备一定的知识水平。然而在现实中,文档通常只是为执行部署者写的备忘录,是难以被他人理解的。
- 以上几点引起的一个必然结果:手工部署过程依赖于部署专家。如果专家去度假或离职了,那你就有麻烦了。
- 尽管手工部署枯燥且极具重复性,但仍需要有相当程度的专业知识。若要求专家做这些无聊、重复,但有技术要求的任务则必定会出现各种我们可以预料到
的人为失误,同时失眠,酗酒这种问题也会接踵而至。然而自动化部署可以把 那些成本高昂的资深高技术人员从过度工作中解放出来,让他们投身于更高价
值的工作活动当中。 - 对手工部署过程进行测试的唯一方法就是原封不动地做一次(或者几次)。这往往费时,还会造成高昂的金钱成本,而测试自动化的部署过程却是既便宜又容易。
- 另外,还有一种说法:自动化过程不如手工过程的可审计性好。我们对这个观点感到很疑惑。对于一个手工过程来说,没人能确保其执行者会非常严格地遵循文档完成操作。只有自动化过程是完全可审核的。有什么会比一个可工作的
部署脚本更容易被审核的呢? - 每个人都应该使用自动化部署过程,而且它应该是软件部署的唯一方式。这个准则可以确保:
在需要部署时,部署脚本就能完成工作。在本书中我们会提到多个原则,而其中之一就是“使用相同的脚本将软件部署到各种环境上”。如果
使用相同的脚本将软件部署到各类环境中,那么在发布当天需要向生产环境进行部署时,这个脚本已经被验证过成百上千次了。如果发布时出现任何问题的话,你可以百分百地确定是该环境的具体配置问题,而不是这个脚本的问题。
2、开发完成之后才向类生产环境部署
特征
如果测试人员一直参与了在此之前的过程,那么他们已在开发机器上对软件进行了测试。
只有在向试运行环境部署时,运维人员才第一次接触到这个新应用程序。在某些组织中,通常是由独立的运维团队负责将应用程序部署到试运行环境和生产
环境。在这种工作方式下,运维人员只有在产品被发布到生产环境时才第一次 见到这个软件。有可能由于类生产环境非常昂贵,所以权限控制严格,操作人员自己无权对该环境进行操作,也有可能环境没有按时准备好,甚至也可能根本没人去准备环境。
开发团队将正确的安装程序、配置文件、数据库迁移脚本和部署文档一同交给那些真正执行部署任务的人员,而所有这些都没有在类生产环境或试运行环境
中进行过测试。开发团队和真正执行部署任务的人员之间的协作非常少。
如下问题会使整个交付流程更加恶化
- 假如一个应用程序是全新开发的,那么第一次将它部署到试运行环境时,可能会非常棘手。
- 发布周期越长,开发团队在部署前作出错误假设的时间就越长,修复这些问题的时间也就越长。
- 交付过程被划分到开发、DBA、运维、测试等部门的那些大型组织中,各部门 之间的协作成本可能会非常高,有时甚至会将发布过程拖上“地狱列车”。此时
为了完成某个部署任务(更糟糕的情况是,为了解决部署过程中出现的问题), 开发人员、测试人员和运维人员总是高举着问题单(
不断地互发电子邮件)。 - 开发环境与生产环境差异性越大,开发过程中所做的那些假设与现实之间的差 距就越大。虽然很难量化,但我敢说,如果在Windows系统上开发软件,而最
终要部署在Solaris集群上,那么你会遇到很多意想不到的事情。 - 如果应用程序是由用户自行安装的(你可能没有太多权限来对用户的环境进行操作),或者其中的某些组件不在企业控制范围之内,此时可能需要很多额外的测试工作。
3、生产环境的手工配置管理
特征
多次部署到试运行环境都非常成功,但当部署到生产环境时就失败。
集群中各节点的行为有所不同。例如,与其他节点相比,某个节点所承担的负载少一些,或者处理请求的时间花得多一些。
运维团队需要较长时间为每次发布准备环境。
系统无法回滚到之前部署的某个配置,这些配置包括操作系统、应用服务器、
关系型数据库管理系统、Web服务器或其他基础设施设置。
不知道从什么时候起,集群中的某些服务器所用的操作系统、第三方基础设施、依赖库的版本或补丁级别就不同了。
直接修改生产环境上的配置来改变系统配置。
4、 ClearCase以及从源代码重新构建的反模式
这种流模式开发的问题之一就是晋升是在源代码级别完成的,而不是二进制级 别。因此,每次将一个修改晋升到更高层级的流上时,都必须签出代码并重新构建
二进制包。在很多使用ClearCase的组织里,下面这种事情在运维团队很常见,他们 只会部署那些自己亲自从发布分支上签出源代码并重新编译出来的二进制包。其他
问题不说,仅这件事也会导致一种巨大的浪费。
而且,它破坏了我们建议的一个关键实践:发布时所用的二进制包就应该是那 个已经顺利通过部署流水线的原始的二进制包,这样才能确保发布的东西就是测试
过的东西。除了没有人测试过这个来自于发布流重新编译的二进制包以外,在构建 流程中,还有一处可能会引入差异,那就是当运维团队使用编译器的某个小版本或
者某个依赖的不同版本进行构建时。这种差异可能会导致需要花几天的时间来追踪 生产环境中的bug。
持续交付中常见的反模式