持续集成之“自动化部署”
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
持续集成之“自动化部署”
在前文《依赖管理》中,我们讨论了如何在代码变得庞大,组件增多的情况下,做好外部库和内部组件依赖管理,从而提高构建效率。可以应用的实践包括:一次生成,多次复用;建立统一制品库,外部依赖库可以使用像Maven或Ivy这样的工具进行统一管理;对架构进行调整,使一个大的代码库分成多个组件;每个组件有自己的持续集成体系;对多个组件做持续集成。然而,解决一个问题后,总会有另一个问题等在那里,需要你来解决。这次Joe的团队遇到了部署问题。
星期一早上,Alice一进办公室,就看到一脸倦意的Joe坐在椅子上,喝着咖啡。
“今天怎么来得这么早?看样子,你没睡好啊?”Alice问道。
“当然啦,昨天晚上我就来了。”Joe无精打采地回答道。
“怎么啦?”
“还不是因为新版本上线出了点儿问题”,Joe说道。“看来我们要把部署这件事好好讨论一下,再这样下去,不只我要来,你们也要和我一样啦!呵呵!”
当天下午,Joe邀请了运维团队的主要负责人Tom和Steven,召开了一个关于部署问题的讨论会。
Joe说道:“先请运维部门的Tom介绍一下上周末的新版本上线过程和发现的问题吧。”
Tom描述了上线部署全过程。
不可重复且不可靠、易出错的手工部署过程
1.当新版本开发测试完成后,由开发团队的成员在浏览器上登录运维平台,填写上线
申请单。申请单的内容包括新版本的上线部署步骤。
2.测试人员为了保证能够升级部署成功,首先要复制生产环境中的程序和数据到本地
的测试环境中,然后根据上线申请单中所描述的上线部署步骤进行操作,对上线步骤进行验证。
3.运维人员登录到运维平台,收到上线申请单后,确认“已收到”。
4.运维人员发现上线部署步骤有问题,生产环境的路径与上线部署步骤中描述的不一
致。于是与开发人员进行沟通,让开发人员修改上线部署步骤。
5.开发人员修改后,再次通知测试人员和运维人员查看并确认。
6.确认无误后,运维人员根据部署计划,登录到生产环境中,依照上线部署步骤,手
工操作完成。
“上周末上线部署时出现的情况是:在本次部署之前,我们的集群中,有两台机器因HotFix,其程序配置被修改过,与其它机器不一致。因此,该机器上的部署失败,导致部分服务不可用。运维人员查了很长时间没有发现问题,星期日打电话把Joe叫来帮助我们查问题时,Joe才回忆起有那么一次 HotFix,但当时
负责的运维人员已经离职,没人其它运维人员知道这件事情。”Tom说道,“我们对问题进行了分析,认为应该加强我们的上线流程管理,对于那种HotFix
也应该发起一个审批流程,并且在该流程中不但要主要负责人审批,而且要对相关人发出周知通报。另外,我们的运维人员应该对上线单进行严格审核,并对部署中所涉及的机器进行更详细的验证,对生产环境中的任何修改都要进行登记。即使非常紧急,也要在事后补充记录一下。”
“这些方法固然很好,但其实我们可以采用更好的办法来解决。”Joe接着说到,“假如我们在部署运维工作也能够借鉴持续集成的做法,利用一些最佳实践,那么这次部署事故根本就不会发生。比如(1)将部署操作脚本化;(2)进行持续部署验证测试;(3)部署脚本通用化,环境变量等使用配置方式传入; (4)让测试环境尽可能与生产环境一致,至少在成本条件允许的情况下尽量保持相似;(5)对环境配置进行版本控制;(6)任何人不得直接对生产环境进行直接的手工操作,等等。”
将部署操作脚本化,并进行部署验证测试
Bob说道:“嗯,其实那些上线步骤中所描述的内容都可以进行脚本化,之前也讨论过这一问题。目前上线步骤中的内容基本都可以写成自动化脚本,即使现在不行,也可以通过少量改造,使其可以自动化。但问题是... ...”Bob犹豫
了一下,接着说道,“如何来验证这些脚本是正确的呢?”
Joe 说道:“保证运维人员是如何验证上线申请单上的上线步骤是正确的呢?同样,我们也可以做一些部署验证就行了。这些部署的验证也可以通过脚本方式来进行,比如在安装之前验证程序所用端口没有被占用,安装之后验证该端口已被该程序所使用;比如安装之前验证程序日志中记录了该程序已停止运行,在安装之后验证程序日志中刻录该程序已重新启动;等等”。
Alice问道:“那我们还要调试这些部署脚本呀?没有线上生产环境,我们怎么调试呢?”
各类环境尽可能相似,并使部署脚本通用化
Joe 回答道:“首先我们应该加强基础设施这方面的投入。在力所能及的情况下,让测试环境与生产环境相似。比如,生产环境可能有100台机器的集群,那我们至少要找两台机器的集群做测试环境。生产环境中使用Tomcat,我们的测试环境和开发环境中也应该使用相同的Tomcat,而不用Jetty。”
另外,它们通常能与版本控制工具集成。所以,只要将我们的软件堆栈配置管理信息放到版本控制库中,就可以同时管理数台机器。”
“oh, 对不起,Joe,我想打断一下,”Tom问道:“你能画一个图来解释一下你刚才所说的这种软件环境配置管理工具吗?”
“当然没问题。”Joe拿起笔在白板上画了一个Puppet的工作示意图,如下图所示。
“看上去清楚多啦。”Tom笑道,“通过这种方式,我们就只需要将版本控制库中保存的配置信息检出到本地,进行相应的修改,再提交到版本控制库中,这种工具就会自动帮我们完成必要的配置更新了。是这样的吗?”
“对,”Joe点了点头,说道,“如果我们的部署脚本也是通过这种方式来做的,那么我们就根本没有必要登录到生产环境的机器上,进行手工操作了。而且,Puppet还提供一种Try Run功能,可以进行配置变更的模拟,让你能够对比一下变更前后的不同之处。”
Tom说道:“你说的这些听上去都不错。但并不是所有人都能够修改生产环境的配置信息的。所以我们还是需要一个软件平台来管理上线的申请审批流程。”
“在任何企业中,这种申请审批流程和生产环境变更的授权都是必要的,但这仅仅是审核流程的操作。而真正与软件部署相同的具体操作都不应该在这种审批流程当中。”Joe回答道。
Tom接过话来,说道:“嗯,这样的话,我们仍旧能够做到:有权限的人才能真正修改生产环境的配置文件,同时达到了无人真正直接操作生产环境的目的,避免了手工误操作带来的问题。”
参加本次会议的测试人员和运维人员对这种做法产生了浓厚的兴趣,并要求开发人员给予配合,将目前游戏平台的部署自动化。Tom说道:“这就是我们运维工作的一个方向。让枯燥易出错的重复性手工操作变成受控的自动化,从而解放运维人员,让我们可以关注于更加有价值的运行监控等工作中。”