正如第1章所述,部署软件有如下3个步骤。
环境是指应用程序运行所需的所有资源和它们的配置信息。用如下这些属性来描述环境。
通用术语基础设施(infrastructure)
代表了你所在组织中的所有环境,以及支持其运行的所有服务,如DNS服务器、防火墙、路由器、版本控制库、存储、监控应用、邮件服务器,等等。事实上,应用程序环境和所在组织的其他基础设施之间的分界限可能非常明确(比如,对于嵌入式软件),也可能极其模糊(比如,在面向服务架构的情况下,很多基础设施是在各应用程序之间共享和依赖的)。
准备部署环境的过程以及部署之后对环境的管理是本章的主要内容。然而为了能够做到这一点,就要基于下面这些原则,用一个整体方法来管理所有基础设施。
基础设施不但应该具有自治特性,而且应该是非常容易重新搭建的。这样的话,当有硬件问题时,就能迅速重建一个全新的已知状态的环境配置。所以,基础设施的准备工作也应该是一个自动化过程。自动化的准备工作与自治性的维护相结合,可保证一旦出现问题就能在可预见的时间内重建基础设施。
为了减少在类生产环境(production-like environment)中的部署风险,需要精心管理如下内容。
先从列表中的最后一项开始,因为它与其他那些技术条目不同。如果两个团队能够紧密合作解决问题的话,其他事情就会变得很容易。他们应该从项目一开始就在环境管理和部署方面进行全面合作。
强调合作是DevOps运动的核心原则之一。DevOps运动的目标是将敏捷方法引入到系统管理和IT运营世界中。这场运动的另一个核心原则是,利用敏捷技术对基础设施进行有效管理。本章所讨论的很多技术(如自治性的基础设施和行为驱动的监测,即behavior-driven monitoring)都是由这项运动的发起人研究开发出来的。
当阅读本章时,请记住指导原则:测试环境应该是与生产环境相似。也就是说,对于上面列出的所有条目,绝大多数应该是相似的(尽管不必完全相同)。其目的是为了尽早发现环境方面的问题,以及在向生产环境部署之前对关键活动(比如部署和配置)进行操作演练,从而减少发布风险。测试环境需要与生产环境足够相似,以达到这一目标。更重要的是,管理这些环境所用的技术应该是相同的。
这么做有一定的难度,而且很可能成本也较高,但有些工具和技术可以提供帮助,比如虚拟化技术和自动化数据中心管理系统。对于能够在开发早期就捕获那些令人费解、难以重现的配置和集成问题来说,这种方法的收益会很大,甚至在后期能得到数倍于这些成本的回报。
最后一点是,虽然本章假设应用程序所部署的生产环境由运维团队管理,但对于软件产品来说,原则和问题都是一样的。比如,虽然某个软件产品不必对其数据进行定期备份,但对于任意一个用户来说,数据恢复都是非常重要的。而对其他非功能需求来说也是一样,比如可恢复性(recoverability)、可支持性(supportability)和可审计性(auditability)。
无需证明,大多数项目的失败原因在于人,而不是技术本身。对于“将代码部署到测试和生产环境中”这事来说,更是如此。几乎所有大中型公司都会将开发活动和基础设施管理活动(也就是常说的运维活动)分交给两个独立的部门完成。常常能看到这两拨人的关系并不是很好。这是因为往往鼓励开发团队尽可能快地交付软件,而运维团队的目标则是稳定。
需要谨记的最重要的事情是:所有的项目干系人都能达成一个共识,即让发布有价值的软件成为一件低风险的事情。根据我们的经验,做这件事的最佳方法就是尽可能频繁地发布(即持续交付)。这就能保证在两次发布之间的变更很小。如果你所在的组织中,发布总是需要花上几天的时间,还要熬夜加班的话,你肯定会强烈反对这种想法。而我们的回答是:发布可以并且应该成为一种能在几分钟内执行完的活动。这听上去好像不太现实,但是,我们曾看到过在一些大公司中,很多大型项目从最初由甘特图驱动的整夜无眠的发布变为一天做几次分钟级别的低风险发布活动。
在小公司里,开发团队常常也要负责运维。而大多数大中型公司会有多个独立的部门。每个部门都有其独立向上汇报的途径:运维会有运维的领导,开发团队有开发团队的领导。当每次在生产环境上进行部署时,这些团队及其领导都会极力证明问题不是他们部门的错。很明显,这是两个部门关系紧张的潜在原因。每个部门都想将部署风险降到最低,但他们都有自己的手段。
运维团队依据一些关键的服务质量指标来衡量他们的效率,比如MTBF(Mean Time Between Failure,平均无故障时间)和MTTR(Mean Time To Repair Failure,平均修复时间)。运维团队常常还必须满足某些SLA(Service-Level Agreement,服务级别的条款)。对运维团队来说,任何变更都可能是风险(包括那些可能影响到运维团队达成这些目标或其他要求的流程的变更)。既然这样,运维团队就有几个最为重要的关注点。
运维主管希望确保其所管任意环境中的任意变更都要被记录在案并被审计。这样一旦出了问题,他们可以查到是由哪些修改引起的。
运维主管很关注他们追溯变更的能力,还有另外的原因。比如,拿萨班斯-奥克斯利法案来说,这个美国法案的目的是鼓励良好的企业审计和责任,希望确保环境的一致性。这么做大体上能够找出最后那个运行状态良好的环境和出问题的环境之间到底有哪些不同。
变更管理流程肯定是任何组织中最重要的流程之一,它用于管理受控环境的每一次变更。通常,运维团队会掌管生产环境,以及与生产环境近似的测试环境。这就意味着,任何人在任何时候想修改一下测试环境或生产环境,都必须提出申请,并被审批。很多低风险的配置变更可以由运维团队来执行。在ITIL中,这些变更叫做“标准”变更(standard change)
。
然而,部署应用程序的新版本常常是一个需要由CAB(Change Advisory Board,变更提议/咨询委员会)
提出申请,并由变更管理者审批的“常规”变更(normal change)。在变更申请中,需要包括详细的风险与影响分析,以及出错时的应对方案。这个申请应该在新版本的部署流程启动之前提交,而且不能是在业务人员期望上线前的几个小时才提交。当第一次执行这个流程时,可能要回答很多问题。
软件开发团队的成员也需要熟悉运维团队掌控的这些系统和流程,并遵守它们。制定软件发布时所需遵循的流程也是开发团队发布计划的一部分。
运维团队会有自己的系统来监控基础设施和正在运行的应用程序,并希望当系统出现异常状况时收到警报,以便将停机时间最小化。
每个运维团队都会用某种方法来监控他们的生产环境。它们可能用OpenNMS,也可能用Nagios或者是惠普的Operations Manager。他们很可能已经为自己定制了一个监控系统。无论他们用什么系统,他们都希望应用程序也能够挂到该系统中,以便一旦出错就能得到通知,并知道到哪儿查找详情,找到出错原因。
重要的是,要在项目一开始就了解运维团队希望怎样来监控应用程序,并将其列在发布计划之中,比如,他们想要如何监控?希望把日志放在什么位置?当系统出错时,应用程序要使用怎样的方式通知运维人员?
缺乏经验的开发人员最常犯的一个编码错误就是吞噬错误信息(swallow error)。与运维团队聊一下,你就会发现,应该把每个错误状态都记录下来,并放到某个已知的位置上,同时记录相应的严重程度,以便他们能确切知道发生了什么问题。这么做以后,若应用程序由于某种原因出问题了,运维人员能够很容易地重启或重新部署它。
再强调一次,了解并满足运维团队的监控需求,并把这些需求放到发布计划中是开发团队的责任。处理这些需求的最佳办法就是像对待其他需求那样对待它们。主动从运维人员的角度思考,想一下他们会如何应对应用程序——他们是应用程序用户中非常重要的一部分用户。当第一次发布临近时,要将重启或重新部署应用程序的流程放到你的发布计划当中。
首次发布仅仅是所有应用程序生命周期的一个开始。应用程序的每个新版本都会有所不同,比如错误的类型以及其生成的日志信息,可能被监控的方法也不同。它还可能以某种新的形式发生错误。因此,当要开发新版本时,让运维人员也参与其中是非常重要的,这样他们就可以为这些变更做一些准备工作。
运维经理要参与组织的IT服务连续性计划的创建、实现、测试和维护。运维团队掌管的每个服务都会设定一个RPO(Recovery Point Objective, 恢复点目标,即灾难之前丢失多长时间内的数据是可接受的)以及一个RTO(Recovery Time Objective,恢复时间目标,即服务恢复之前允许的最长停机时间)
RPO控制了数据备份和恢复策略,因为数据备份必须足够频繁,才能达到这个RPO。当然,如果没有应用程序以及其依赖的环境和基础设施,这些数据也就没有什么用,所以还要能重新部署应用程序的正确版本,以及它的运行环境和基础设施。也就是说,必须小心管理这些配置信息。只有这样,运维团队才能重建它们。
为了满足业务方面所需的RTO,可能要额外建立一个生产环境和基础设施的副本,以便当主系统出错时,可以启用这个后备系统。应用程序应该能应对这类突发事件。对于高可用性应用程序,这意味着当应用程序正在运行时,就要进行数据和配置信息的复制工作。
有个与之相关的需求,那就是归档问题:生产系统中应用程序所生成的数据量可能很快就变得非常大。为了审计或支持工作,应该用某种简便方法对生产数据进行归档,使磁盘空间不被占满,也不会降低应用程序的运行速度。
作为业务持续性测试的一部分,应该对应用程序数据的备份、恢复以及归档工作进行测试,还要获取并部署任意指定版本的应用程序。另外,作为发布计划的一部分,还要将如何执行这些活动的流程提供给运维团队。
运维主管希望用运维团队自身熟悉的技术对其管理的环境进行变更操作,这样他们就能真正掌控和维护这些环境了。
对运维团队来说,熟练使用Bash或PowerShell是很平常的事情,但成为Java或C#专家的可能性却不大。可是,我们几乎可以肯定的是,他们还是希望能够检验对环境和基础设施的配置所要作出的变动。如果由于应用程序用了运维团队不熟悉的技术和语言,使他们无法理解它的部署过程的话,这无疑会增加这些修改的风险。运维团队可能抵触他们无法维护的部署系统。
在每个项目开始时,开发团队和运维团队就应该坐下来,讨论并决定应用程序的部署应该如何执行。一旦所用技术达成一致,双方可能都需要学习一下这些技术(可能是某种脚本语言,比如Perl、Ruby或Python,或者某种打包技术,比如Debian打包系统或者WiX。
关键在于两个团队都要理解这个部署系统,因为我们必须使用相同的部署过程对每个环境的修改进行部署,这些环境包括开发环境、持续集成环境、测试环境和生产环境。而开发人员是最早负责创建这一过程的人。它们会在某个时间点被移交给运维团队,运维团队是负责维护这些脚本的人。因此,这就需要运维团队从开始写脚本时就参与其中。用于部署或修改环境和基础设施的技术也应该是发布计划中的一个组成部分。
部署系统是应用程序的一个部分。与应用程序的其他部分一样,它也应该被测试和重构,并放在版本控制库中。如果不这么做(我们曾看到过这种事情发生),其结果总是留下一堆疏于测试、易出问题且不易理解的脚本,让变更管理充满风险和痛苦。
除了项目干系人管理之外,从广义上讲,本章的其他内容都可以算做是配置管理的一个分支。然而,对测试和生产环境实现全面的配置管理并不是一件小事,所以它占用了本章的很大篇幅。即便这样,本章也只讨论了环境和基础设施管理的高层次原则。
每种环境中都有很多种配置信息,所有这些配置信息都应该以自动化方式进行准备和管理。图11-1展示了一些根据抽象层次的不同,对各种服务器进行分类以后的例子。
如果你对将要开发的系统所用技术有最终决定权的话,那么在项目的启动阶段
(inception),你应该回答一个问题:用这种技术做自动化部署和配置软硬件基础设置容易吗?对于系统的集成、测试和部署的自动化来说,使用能够以自动化方式进行配置和部署的技术是一个必要条件。
假如你无权控制基础设施的选择,但还想全面自动化构建、集成、测试和部署的话,你必须解决下述问题。
现代操作系统有数千种安装方式:不同的设备驱动器、不同的系统配置信息设置,以及一大堆会影响到应用程序运行的参数。某些软件系统比其他的软件更能容忍这种层次的差异。大多数COTS软件会运行在很多不同的软硬件配置中,所以它们不应该在这个层面上过多地考虑不同点,虽然作为安装和升级过程的一部分,应该总是检查商业套装软件对系统的要求。然而,一个高性能Web应用可能会对一个微小的变化也非常敏感,比如数据包大小或文件系统配置项的变化。
COTS即Commercial Off-The-Shelf 翻译为“商用现成品或技术”或者“商用货架产品”,指可以采购到的具有开放式标准定义的接口的软件或硬件产品,可以节省成本和时间。
对于运行于服务器上的多用户应用程序来说,直接使用操作系统和中间件的默认设置通常并不合适。操作系统需要有访问控制、防火墙配置以及其他强化措施(比如禁用不必要的服务)等。数据库也需要配置,给用户设置正确的权限,应用服务器需要部署多个组件,消息代理服务器需要定义消息以及订阅注册,等等。
与交付流程的其他方面一样,你应该把创建和维护基础设施需要的所有内容都进行版本控制。至少对下述内容应该这么做。
与源代码一样,版本控制库中的这些文件也是部署流水线输入的一部分。对于基础设施的变更来讲,部署流水线的工作包括三部分。
在图11-1中值得注意的是,那些用于部署配置应用程序、服务和组件的脚本和工具
通常与那些准备和管理基础设施其他部分工具
有所不同。有时候,部署应用程序的流程也要执行部署和配置中间件的任务。通常,这些部署流程由当前正在负责应用程序开发的开发团队来创建,但执行这些部署流程的前提条件是基础设施的其他部分已经准备好并且处于正确的状态。
当处理基础设施时,需要重点考虑的一个因素是共享到什么程度。如果某些基础设施的配置信息只与某个特定的应用程序相关,那么它就应该是那个特定应用程序的部署流水线的一部分,而不需要它自己的一个独立生命周期管理。然而,如果某些基础设施是多个应用程序共享的,那么你就面临这样一个问题:管理应用程序和应用程序所依赖的基础设施之间的版本依赖。也就是说,为了能够正常工作,就要记录每个应用程序需要哪个版本的基础设施。这样就要再建立另一个流水线,用于推送对基础设施的变更,确保那些影响多个应用程序的变更能以某种遵守依赖规则的方式完成其交付流程。
如果组织很小或者刚成立,那么这是一个制定所有基础设施的配置管理策略的大好机会。如果面对的是一个没有良好控制的遗留系统的话,那么就要找出让它处于受控状态的方法。控制包括以下三方面。
尽管我们并不是限定行为、建立审批流程的狂热者,但对生产基础设施进行修改是一个严肃的问题。因为我们相信,应该像对待生产环境一样对待测试环境,在这两种环境上要使用同样的流程。
锁定生产环境以避免非授权访问是非常必要的,其对象既包括组织之外的人,也包括组织之内的人,甚至是运维团队的员工。否则,当出问题时,直接登录到出问题的环境上去尝试解决问题的做法是非常有诱惑力的[这种做法有时候被礼貌地称为“试探式的问题解决方法”(problem-solving heuristic)]。这是个可怕的想法,原因有二。
如果无法通过一个自动化过程从头重新创建基础设施的话,首先要做的事情就是实现访问控制。这样,如果没有通过审批,就无法对任何基础设施作出修改。
当然,有时还是需要对基础设施进行修改的。高效的变更管理流程有如下几个关键特征。
**良好的变更管理的关键在于创建一个自动化流程,从版本控制库中取出基础设施的变更项进行部署。**如果想做到这一点,最有效的方法是要求所有对环境的修改都要通过一个集中式系统。在测试环境中不断尝试,最终确定要做哪些变更,然后在一个全新的类生产试运行环境上对它进行测试,再把它放在配置管理库中,以便后续的构建中包含这一变更,得到批准后,用自动化系统对生产环境进行变更。很多组织已经自行开发了这样一个系统来对这一问题进行管理。如果你还没有的话,可以使用数据中心自动化工具(比如Puppet、CfEngine、BladeLogic、Tivoli或HP Operations Center)。
**加强可审计性的最佳方法是用自动化脚本来完成所有变更。**这样,万一后来有人想知道到底做了哪些修改的话,就很容易找到了。因此,通常情况下,我们认为使用自动化方式要优于手工文档。手工文档无法保证所记录的变更是完全正确的,比如“某人说他做过了什么事情”与“他实际上做了什么”,这之间的差异足以让你花上几小时甚至几天的时间去查找问题根源。
在中小型企业中,服务器的准备及其配置管理常常被忽视,因为它看上去太复杂了。几乎对每个人来说,搭建服务器并让它运行起来的初次经历都是先找到安装盘,把它放在计算机中,遵循非受控的配置管理流程,以人机交互的方式进行安装。然而,这很快就会使服务器的安装工作变成一种“艺术工作”。这会导致服务器和出错后就很难重建的系统之间行为的不一致。而且,服务器准备工作是一个手工的、重复性的、资源密集且易出错的过程,而这种问题恰恰可以用自动化来解决。
从较高的抽象层次上来说,服务器的准备工作(不管是为测试环境还是生产环境)最开始都要把一台机器放到数据中心,把它连接好。完成之后,后续的所有活动(包括首次加电)都可以用完全自动化的方式通过远程控制来完成。可以使用带外(out-of-band)远程管理系统(比如IPMI或LOM)启动那台机器,通过网络启动并使用PXE(描述如下)安装一个基本的操作系统,该基本操作系统中应安装数据中心管理工具(如图11-2中的Puppet)的一个代理器。然后,这个数据中心管理工具(图11-2中的Puppet)就会管理这台机器的配置。整个自动化过程如图11-2所示。
CMS一般指内容管理系统。 内容管理系统(Content Management System,CMS),是一种位于WEB前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。
PXE(Preboot Execution Environment,远程引导技术)是RPL(Remote Initial Program Load,远程启动服务)的升级产品。它们的不同之处为:RPL是静态路由,PXE是动态路由。不难理解:RPL是根据网卡上的ID号加上其它的记录组成的一个帧向服务器发出请求,而服务器那里早已经有了这个ID数据,匹配成功则进行远程启动;PXE则是根据服务器端收到的工作站MAC地址(就是网卡号),使用DHCP服务给这个MAC地址指定一个IP地址,每次重启动可能同一台工作站有与上次启动有不同的IP,即动态分配地址。
创建操作系统基线有如下几种方法。
方法对比:
PXE是通过以太网启动机器的一个标准。当在机器的BIOS中选择通过网络启动的话,那实际上就是PXE。这个协议使用DHCP的修订版来寻找那些提供启动映像的服务器。当用户选择了从哪个映像启动后,客户端就会通过TFTP加载相应的映像到RAM中。可以通过配置的标准Internet Service Consortium DHCP服务器——dhcpd(所有Linux发行版都有提供)使其提供PXE服务,然后再配置一个TFTP服务器,提供那个真正的映像。如果使用的是RedHat,那么就有个叫做Cobbler的应用程序可能通过PXE来选择Linux操作系统映像。如果在用RedHat机器的话,它还支持用操作系统映像生成一个新的虚拟机。Hudson也有一个插件提供这种PXE服务。BMC的BladeLogic中也包含一个PXE服务器。
几乎每个常见的UNIX 风格的系统都提供与PXE相适应的映像。当然,也可以自己定制映像——RedHat和Debian的包管理系统允许你将一个已安装系统的当前状态保存到一个文件中,这样就可以用它来做其他系统的初始化工作。
一旦拿到了一个已准备好的基础系统,你就能对它进行配置了。做这件事的一种方式是用操作系统中的无人参与安装过程:RedHat的Kickstart、Debian的Preseed,或者Solaris的Jumpstart。这些都可以用来执行系统安装之后的一些活动,比如安装操作系统补丁,并决定运行哪个守护进程。下一步就是把基础设施管理系统的代理客户端安装到这台机器上,然后就让那些基础设施管理工具来管理操作系统的配置。
PXE在Windows平台上的对应软件是WDS(Windows Deployment Services,事实上,它的底层也是PXE)。WDS包含在Windows Server 2008企业版中,也可以安装在Windows Server 2003上。虽然这些在Vista之后才成为主流,但它还是可以启动Windows 2000及之上的版本(不包含ME)。为了使用WDS,你需要有ActiveDirectory域、一个DHCP服务器和一个DNS服务器。然后再安装(如果需要的话)并启用WDS。为了配置一下后从WDS启动,需要准备两个映像:一个启动映像和一个安装映像。启动映像是由PXE加载到 RAM 的 [ 在 Windows 上,有个软件叫作 WinPE ( Windows Preinstallation Environment)],这个软件是当你启动Vista安装光盘时使用的。这个安装光盘是一个自启动的完整安装盘,它会把映像加载到机器上。从Vista以后,这两个映像都在DVD安装盘的源目录下,叫做BOOT.WIM和INSTALL.WIM。有了这两个文件,WDS就可以通过网络启动并进行所有必要的配置。
也可以为WDS创建自己的安装映像。使用微软的Hyper-V(如Ben Armstrong [9EQDL4]所述)非常容易做。只要启动一个你想要的操作系统的虚拟机来创建一个映像即可。按你想要的方式把它配置一下,并在之上运行Sysprep,然后使用ImageX把这个驱动映像转成可以注册到WDS的一个WIM文件即可。
一旦安装好操作系统后,就要保证任何配置的修改都是以受控方式进行的。也就是说,首先确保除运维团队之外,没有人能登录到这些服务器上,其次使用某种自动化系统来执行所有修改。这些修改包括应用操作系统的服务包(service pack)、升级、安装新软件、修改配置项,以及执行部署。
配置管理过程的目标是,保证配置管理是声明式且幂等的(idempotent),即无论基础设施的初始状态是什么样,一旦执行了配置操作后,基础设施或系统所处的状态就一定是你所期望的状态,即使某个配置项进行了重复设置对配置结果也没有影响。这在Window平台和UNIX平台都是可行的。
一旦这个系统准备好之后,就能用一个被集中版本控制的配置管理系统对基础设施中的所有测试环境和生产环境进行管理了。之后,就可得到如下收益。
- 在Windows上,除了WDS,微软还为管理微软基础设施提供了另一个解决方案:SCCM(System Center Configuration Manager,系统中心配置管理器)。SCCM使用ActiveDirectory和Windows Software Update Services来管理操作系统的配置,包括组织中每台机器的更新和设置。也可以使用SCCM部署应用程序。SCCM还能与微软的虚拟技术方案相连通,使你能像管理物理机一样来管理虚拟服务器。使用与ActiveDirectory集成的Group Policy来管理访问控制,自Windows 2000以后,它就被打包在所有的微软服务器上了。
- 而在UNIX世界里,LDAP通常是UNIX进行访问控制的工具,用于控制谁在哪台机器上能做什么。对于当前操作系统配置(比如安装了哪种软件和版本更新)的管理来说,有很多解决方案。也许最流行的工具就是CfEngine、Puppet和Chef,但还有几个类似的工具,比如Bcfg2和LCFG [9bhX9H]。在撰写本书时,唯一支持Windows平台的这类工具只有WPKG,但它不支持UNIX平台。然而,Puppet和Chef正在开发对Windows平台的支持。另外,值得一提的是难以置信的Marionette Collective(简称mcollective),它是使用某种消息总线(message bus)来查找和管理大量服务器的一种工具。它有一些插件可以远程控制其他服务,并能与Puppet和Facter通信。
你应该能够做到:拿到一些服务器后,就可以从头至尾将它们部署好。在构建、部署、测试或发布策略中引入自动化或虚拟化的一个好办法就是将它看做对环境准备工作的一个测试。检验这一结果的最佳问题是:如果生产环境出了灾难性问题,准备一个全新的生产环境需要多长时间?
对大多数开源工具来说,环境配置信息都保存在一系列的文本文件中,而这些文本文件都保存在版本控制库中。也就是说,基础设施的配置信息是自我描述的(self-documenting),即想看配置信息的话,直接到版本控制库中就可以查到。而商业工具通常都会使用数据库来管理配置信息,并且需要通过UI来编辑它。
我们将重点介绍一下Puppet,因为它是目前最流行的开源工具(当然CfEngine和Chef也很流行)。对于其他工具来说,基本原则是相同的。Puppet通过一种声明式的外部配置信息领域专属语言来管理配置。对于那些复杂的企业级配置信息来说,可以通过常见模式将它们抽取成可以共享的模块。这样就可以避免大量的重复配置信息了。
Puppet的配置由一个集中式主服务器(central master server)来管理。这个服务器运行Puppet后台主服务进程(puppetmasterd),它有一个列表,所有需要管理的机器都在该列表当中。每台受控机器都运行了一个Puppet代理客户端(puppetd)。它与主服务器通信,确保Puppet管理的那些机器与最新的配置信息保持同步。
当一个配置发生变化时,后台主服务器进程将会通知所有的客户端有新的变更了,客户端就会更新、安装并配置新软件。如果需要的话,它还会重启某些服务器。配置信息是声明式的,描述了每台服务器最终需要达到的状态。也就是说,这些服务器的初始状态可以是不同的,比如它可能是一个虚拟机的新副本,或是一个刚刚准备好的机器。
在操作系统的配置项被恰当地管理起来后,就需要考虑在其之上的中间件的配置管理了。无论是Web服务器、消息系统,还是商业套装软件,这些中间件都可以被分成三部分内容:二进制安装包、配置项以及数据。这三部分有不同的生命周期,所以分别对待是非常重要的。
数据库模式(schema)、Web服务器的配置文件、应用服务器的配置信息、消息队列的配置,以及为了系统能正常工作需要修改的其他方面都应该进行版本控制。
对于大多数系统来说,操作系统和中间件之间的差异是相当模糊的。例如,如果使用的是Linux上的开源软件,那么几乎所有中间件的管理都可以与操作系统管理的方式相同,即使用Puppet或其他相似的工具。在这种情况下,就不必特意花精力做中间件的管理了。只要遵循前面讲过的关于Postfix那个例子的模式来管理其他中间件就可以了。让Puppet确保正确的安装包已经被安装好,并从Puppet主服务器中受版本管理的模板中获取并更新相应的配置信息即可。像添加新网站或新组件这类操作也可以用同样的方式进行管理。在微软的世界中,可以用System Center Configuration Manager或其他商业工具,比如BladeLogic或者Operations Center。
如果中间件不是操作系统标准安装的一部分,最好是用操作系统的包管理系统将其打包,并把它放在组织级的包管理服务器上。然后就能通过所用的服务器管理系统以相同的方式对其进行管理了。
然而,有些中间件无法使用这种方式,通常来说,是那些设计时就没有考虑脚本化或后台安装方式的产品。下节讨论这种中间件的管理。
我们认为,除非能以自动化方式进行部署和配置,否则它就不适合企业级应用。如果不能把重要的配置信息保存在版本控制中,并以可控的方式来管理变更的话,那么这种技术会成为高质量交付的障碍。过去我们被这样的事情折磨过很多次。
通常,在脚本化配置这方面,走在前面的往往是开源的系统和组件。因此,对于基础设施的问题来说,开源解决方案通常更容易管理和集成。遗憾的是,并不是整个软件行业对这件事都达成了共识,有些人有不同的观点。在我们做过的项目中,对于这件事,我们经常没有自由的选择权。那么,当优雅的、模块化的、可配置的、版本控制的且自动化的构建和部署流程遇到了如铁板一块的系统时,又要采取什么样的策略呢?
在寻找低成本、低消耗的解决方案时,最好的着手点是绝对确保该中间件产品具有自动配置的选项。细心地读一下说明文档,找到这类选项,在互联网上搜索一些建议,与产品的技术支持人员聊一下,并在论坛或群组中征求一下意见。简而言之,一定要确保在使用下面描述的策略之前,再也找不到更好的选择了。
如果已经确定所用中间件的确不支持任何形式的自动化配置,接下来就要看看是否能够通过对该产品后台的存储方式做版本控制了。现在,很多产品使用XML文件来存储它们的配置信息。这种文件很适合使用现代版本控制系统,很少会出现问题。如果第三方系统把它的状态保存在二进制文件中,那么可以考虑对这些二进制文件进行版本控制。随着项目开发的进展,它们通常也会频繁变更。
大多数产品会用某种形式的文本文件来为其存储配置信息,那么你将面对的主要问题是该产品如何以及何时读取相关的配置信息。在那些对自动化提供友好支持的情况下,只要复制这些文件的最新版本到正确的位置就够了。如果这样可行的话,就能够进行下一步工作,将该产品的二进制包与它的配置相分离。此时,对安装过程进行反向工程是必要的,而且关键是要写一个你自己的安装程序。你要找到该产品把它的二进制包和库文件安装到了哪里。
在这之后,你有两种选择。最简单的选择就是将相关的二进制文件与安装它们到相关环境的自动化脚本一起放到版本控制库中。第二种选择是再向前一步,自己写一个安装器(或者某种安装包,比如当你用衍生自RedHat系统的Linux系统时,就是RPM)。创建RPM安装包(或其他安装程序)并不是那么难,对问题的解决有多大帮助,就取决于你的环境了。这样,你就能使用自己的安装包将这个产品部署到一个新环境中,并从版本控制库到获取配置信息,应用到其上。
有些产品使用数据库来保存它们的配置信息。这种产品通常会有一个高级的管理控制台,将它所存信息的复杂性隐藏了起来。对于自动化环境管理来说,这些产品将是很大的困难。基本上你不得不把数据库看做一个整体。可是,产品供应商至少应该提供对这个数据库进行备份和恢复的指南。如果情况的确是这样的,你应该毫不犹豫地创建一个自动化过程来做这件事。幸运的话,我们也许会拿着这个备份,分析出如何修改其中的数据,从而把修改放到其中后再恢复到数据库里。
很多产品会提供某种可编程接口。有些产品会提供一些API足以让你对系统进行配置,满足你的需求。一种策略是自己为系统定义一个简单的配置文件。创建自定义的构建任务来解释这些脚本,并使用API对系统进行配置。这种“创造自己的”配置文件的方式让配置管理权回到了你的手中(你可以对配置文件进行版本控制,并以自动化的方式来使用它们)。根据以往的经验,对于微软的IIS,我们就是用这种方法通过它自己的XML元数据库(metabase)进行自动化配置管理的。现在,IIS的新版本已经可以通过PowerShell
进行脚本化了。
理论上,你可以尝试一些其他方法。例如,自行创建有利于版本控制的配置信息,然后写一些代码,通过产品自身的使用方式把它们映射到你所选产品的配置上——如通过管理控制台的用户交互回放方式或对数据库结构进行反向工程。现实中,我们还没有真正这么做过。虽然曾经遇到过这种情况,但通常都找到了一些API,让我们能完成我们想做的事。
尽管对基础设施产品的二进制文件格式或数据库结构进行反向工程是可能的,但你应该检查一下这么做是否违反了许可协议。如果真是这样的话,就要问一下供应商,看他们是否能帮帮忙,提供一些技术支持,之后可以和供应商分享一下你在这个过程中得到的经验。某些供应商(特别是小供应商)会在不同程度上欢迎此类事情,所以值得一试。然而,很多供应商也可能不感兴趣,因为这种方案做技术支持比较难。如果这样的话,我们强烈推荐采纳另一种更易处理的技术。
对于改变组件目前所用的软件平台来说,很多组织是非常谨慎的,因为它们已经在该平台上花了不少钱。然而,这种说法,被称为沉没成本谬误,它并没有考虑转移到新技术上失去的机会成本。邀请一些足够资深的人或者友好的核审员来评估你所面临的效率损失的财务后果,然后让他们找到更好的代替品。在我们的一个项目中,我们维护了一个“痛苦注册表
”(pain-register),即每天因低效技术而损失的时间。一个月后就很容易展示出该技术对快速交付产生的影响
经常看到一些已经成功通过部署流水线并正在生产环境中运行的软件因为基础设施服务的问题(比如路由、DNS和目录服务)而不能正常工作的情况。Michael Nygard为InfoQ写了一篇文章,其中有个故事,说某个系统在每天的同一时间都会神秘死机。最后证明,问题出在某个防火墙每运行一个小时后会扔掉不活跃的TCP连接。由于系统在夜间处于空闲状态,当早上开始有活动时,数据库连接的TCP包就会被悄悄扔掉。
这样的问题总是会在你身边发生,而且一旦发生,常常很难诊断。虽然网络技术的历史已经很长了,但真正理解整个TCP/IP栈(和一些像防火墙这样的基础设施如何破坏规则)的人很少,尤其是当几个不同的实现并存于同一网络时,更是如此。可是,这种情况在生产环境中比比皆是。
我们有如下几个建议。
最后,当出现问题时,使用一些辅助工具。Wireshark
和Tcpdump
都是相当有用的工具,用它很容易查看和过滤包,从而完全隔离你想要找的包。UNIX的工具Lsof
以及在Windows上类似的工具Handle
和TCPView
(是Sysinternals套件的一部分)也很容易用来查看机器上被打开的文件或套接字。
多宿主系统
生产系统的一个重要的增强部分是为不同类型的流量使用多个隔离网络,并与多宿主服务器结合使用。多宿主服务器有多个网络接口,每个接口对应一个不同的网络。至少,有一个网络用来监控和管理生产服务器,一个用于运行备份,一个用于在服务器间做生产数据的传输。这种拓扑结构如图11-3所示。
安全起见,管理网络与生产环境网络是物理隔离的。通常,要求控制监管生产服务器的任何服务(如ssh或SNMP)都会被配置成只绑定nic2,这样就不可能从生产环境网络中访问到这些服务。备份网络与生产环境网络也是物理隔离的,以便当备份时大量数据的移动不会影响性能或管理网络。高可用性高性能系统有时会为了生产数据而使用多个NIC,也许是为了故障转移,也许是为了专属服务,比如可能有一个隔离的专属网络作为组织的消息总线或数据库。
网卡,NIC (Network Interface Controller)
我们讨论过因服务器管理成为“艺术工作”令环境产生差异而导致问题的情况。本章前面已经讨论过,通过虚拟化这一技术来自动化服务器和环境的准备。
这里将描述一个在环境虚拟化的帮助下提供一个受控且完全可重复的部署和发布流程。虚拟化有助于减少部署软件所花费的时间,并用一种不同的方式来降低与部署相关的风险。就在系统的宽度与深度两方面达到高效配置管理来说,部署领域中虚拟机的使用帮了很大的忙。
尤其是,虚拟化还提供了下列收益。
当将其应用到部署流水线中时,它可以算是简化环境维护和准备工作最有用的技术了。
虚拟化也有助于提高对功能需求和非功能需求的测试能力。
虚拟机技术的最重要特性之一就是一个虚拟机映像只是一个文件。这个文件叫做“磁盘映像
”。磁盘映像的好处在于可以复制它们,并对它们进行版本控制(当然不一定要在文件版本控制系统中,除非版本控制系统可以处理大量的大二进制文件)。这样,就能把它们作为模板或者基线(这是配置管理术语)。有些VMM认为“模板”和“磁盘映像”是不同的,但实质上它们是一回事儿。很多VMM甚至允许用正在运行的虚拟机创建模板。这样,就可以用这个模板随时创建任意多个运行实例了
这些模板组成了基线,一个已知处于良好状态的环境版本。在这个版本上,其他所有配置和部署都可以正常运行。相对于调试并修改那些因不受控的修改而导致系统进入不确定状态的环境来说,我们认为用这种方式准备好一个新环境更快捷,因为你只要把有问题的虚拟机停掉,再用基线模板启动一个新的虚拟机就可以了。
现在,我们就能以增量的方式来实现一个自动化的环境准备过程了。为了避免每次都要从头做起,可以用一个已处于良好状态的基线映像(仅包含一个安装好的全新操作系统也行)作为基线来开始实现这个自动化的准备过程。要在每个模板中都安装有数据中心自动化工具的一个代理器(如图11-5中的Puppet),以便实现虚拟机的全自动管理,一旦做到这种全自动化,向整个系统推送变更信息时就可以保持一致性了。
现在,就能用自动化过程来配置操作系统,并安装和配置应用程序所需要的软件。与此同时,再次将环境中每种类型的机器保存一份副本,作为基线。这个流程如图11-5所示。
虚拟化还能让另外两种(本章前面提到过的)不可追踪的场景更容易管理:
部署流水线的目的是,对应用程序做的每个修改都能通过自动化构建、部署和测试过程来验证它是否满足发布要求。一个简单的流水线如图11-6所示。
部署流水线的一些特性值得我们再重新想一想,看一看如何在虚拟化技术中使用这些特性。
从中可以看出,在部署流水线中所测试的内容不仅仅是应用程序本身。的确,当在流水线中发生测试失败时,第一件事就是确定失败的原因。如下是五个最可能的原因。
所以,环境的配置信息也是配置信息中的一个维度。也就是说,应用程序的某个好版本不仅仅与版本控制系统中的某个版本号相关联(因为这个版本号是该版本所对应的二进制包、自动化测试、部署脚本和配置信息的源头)。而且它还要和该版本成功通过部署流水线时的那个运行环境配置信息相关联。即使它在多种环境中运行,它们也应该有相同的类生产环境配置。
构建和发布管理系统应该能记住用来运行部署流水线的虚拟机模板,当部署到生产环境时,也应该能够启动同一套虚拟机模板。
虚拟化提供了一种绝好的方法来处理多平台测试。只要为应用程序可能运行的每种平台创建虚拟机,并在其上创建VM模板。然后在所有这些平台上并行运行部署流水线中的所有阶段(验收、容量和UAT)就行了。现代持续集成工具对这种方法都提供直接支持。
可以使用同样的技术让测试并行化,从而缩短代价高昂的验收测试及容量测试的反馈周期。假设所有的测试都是独立的(参见8.7节中我们的建议),那么就可以在多台虚拟机上并行执行它们。当然,也可以通过不同的线程来并行运行它们,但线程方式有一定的局限性。为构建版本创建一个专门的计算网格能大大地加速运行自动化测试。
最终,测试的性能仅仅受限于那个运行得最慢的测试用例的时间和硬件预算问题了。现代持续集成工具和像Selenium Grid这样的软件都让这件事变得非常简单。
云计算的概念很久之前就出现了,但直到最近几年它才变得无所不在。在云计算中,信息存储在因特网中,并通过因特网上的软件服务进行读取和使用。云计算的特征是:通过扩展所使用的计算资源(比如CPU、内存、存储等)来满足需求,而只需要为自己所使用的这些资源付费就行了。云计算既包括它所提供的软件服务本身,也包括这些软件所用到的软硬件环境。
效用计算
与云计算相关联的一个概念就是效用计算(utility computing)。它是指像家中的电力和燃气一样,把计算资源(如CPU、内存、存储和带宽)也作为一种计量服务方式来提供。
效用计算的主要收益在于它在基础设施方面不需要资金投入。很多刚起步的公司开始使用AWS(Amazon Web Services )来部署它们的服务。因为它不需要预付费,所以,刚起步的公司可以用信用卡来支付AWS费用。当他们从他们自己的用户身上收到钱之后再偿还就行了。效用计算对大公司也很有吸引力,因为它是一种续生成本(recurring cost),而不是资本开支的资产负债表。由于成本相对较低,所以采购也不需要高级管理层审批。另外,它使你能非常容易地进行扩展。假设软件可以运行在由多台机器组成的集群上,再增加一台新机器(或1000台)都只是一个简单的API调用就完成了。如果你想到一个新点子,可以只用一台机器资源(费用也不高),那么,即使没有成功,损失也不多。
所以云计算鼓励创业。在大多数组织中,采纳云计算的主要障碍之一就是对“将公司信息放在第三方的手中”感到紧张,担心安全问题。然而,随着像Eucalyptus这样的技术出现,在公司内做自己的云计算也变成了可能。
云计算的大体上分为三类:云中的应用、云中的平台和云中的基础设施。云中的应用指像WordPress、SalesForce、Gmail和Wikipedia这样的软件服务,即将传统的基于Web的服务放到云基础设施上。
云中基础设施是最高层次的可配置性,比如AWS。AWS提供了很多基础设施服务,除了著名的名为EC2的虚拟机托管服务以外,还包括消息队列、静态内容托管,流媒体托管,负载均衡和存储。利用这些服务,几乎可以对系统进行完全控制,但也要做一些工作把这些东西绑定在一起
很多项目正在使用AWS作为它们的生产环境。如果应用程序架构合理(最理想的情况是那种无共享架构),那么在这种基础设施上对它进行扩展是相当直接的。现在有很多这种服务的供应商,可以利用它们来简化资源管理,并且一些特定的服务和应用已经部署在AWS之上了。然而,这种服务用得越多,应用程序与它们的架构绑定得越深。
即使不用AWS作为生产环境基础设施,对于软件交付流程来说,它仍旧是一个极其有用的工具。EC2使我们很容易根据需要在其中建立一个新的测试环境。可以在其上并行执行测试以加快它的反馈周期。正如本章前面提到过的,还可以做容量测试、多平台验收测试。
打算迁移到云基础设施的人会提出两个非常重要的问题:安全问题和服务级别问题。
安全常常是大中型企业提到的第一个障碍。当生产环境基础设施放在别人手上时,如何防止别人危害你的服务,偷取你的数据呢?云计算的供应商已经意识到这个问题,并建立了多种机制来解决它,比如高度可配置的防火墙,以及连接用户公司VPN的私有网络。最终,尽管使用基于云的基础设施的风险有所不同,而且还需要筹备推入基于云的计划,但“基于云的服务的安全性比部署到公司自己的基础设施上的对外开发服务低”这种说法是缺少基本理由支持的。
在使用云计算时,常常提到“遵从性”(compliance),并把它看为一种约束条件。然而,问题通常不是说:因为没有遵守各种规定,所以限制使用太多的云计算。由于很多规定(regulation)没有考虑到云计算的问题,所以在云计算这个上下文中,这些规定的含义没有被很好地诠释,或者没有被充分地解释清楚。如果能细心地进行计划和风险管理,这两种情况都是可以解决的。为了能够将服务放在AWS中,医疗公司TC3对它的数据进行了加密,所以也能遵守HIPAA。有些云供应商提供了符合某一个级别的支付卡行业数据安全标准,而有些则提供已通过支付卡行业数据安全标准认证的付款服务,因此你不必自己处理信用卡付款问题。即使是那些需要一级规定的大型组织也可以使用一种混合方法,即付费系统放在公司内部,而其他系统放在云中。
当整个基础设施都外包以后,服务级别就特别重要了。比如,在安全性方面,需要做一些调研以确保供应商能满足你的需求。当遇到性能问题时,这尤其重要。根据你的需求,Amazon提供了不同层次的性能参考,但即使它们提供的最高级的性能也无法与真实的高性能服务器相比。如果你的关系型数据库上有大量数据集且高负载的话,也许就不适合放在虚拟环境上。
云中平台的例子包括一些服务,比如Google App Engine和Force.com,服务供应商给你提供了一个标准的应用栈来使用。作为你使用它们提供的应用栈的回报,它们会帮你解决应用程序和基础设施的扩展问题。关键是,你牺牲了灵活性,所以供应商可以很容易地应对非功能需求,比如容量和可用性。云中平台的优点如下。
最后一点尤其是革命性的。在本书中,用了大量的篇幅来讨论如何自动化你的部署、测试和发布流程,以及如何搭建和管理测试和部署环境。使用云中平台几乎完全不需要考虑这些方面。通常,可能只运行一条命令就可以将应用程序部署到因特网上。甚至能够在几分钟内就能从什么都没有的状态到完成一个应用程序发布。从自身的角度来说,一键部署也可以说是零投资的。
云中平台的特点是对应用程序总会有些约束。这也是这些服务能够提供部署简单化和高可扩展性和性能的根源。例如,Google App Engine只提供BigTable的实现方式,而不是标准的关系型数据库系统。不能启动新线程和调用SMTP 服务器等。
和云中基础设施一样,云中平台也面临着同样的不适用性。特别值得指出的是,在便携性和供应商绑定方面要比云中平台更严重。
无论如何,我们都希望,对于更多应用程序来说,这种云计算都是向前迈了一大步。的确,我们希望这类服务的可用性会改变人们进行应用程序架构设计的方法。
当然,可以混合和匹配使用不同的服务来实现系统。例如,可以把静态内容和流媒体放在AWS上,把应用程序放在Google App Engine,把专有服务放在自己的基础设施上。
为了实现这种方式,应用程序就要被设计成可以在这种混合环境中工作。这种部署方式也要求实现一种松耦合的架构。就成本和满足非功能需求而言,松耦合架构让这种混合解决方案带来引人瞩目的业务价值。当然,如何设计出这种架构是比较难的问题,也超出了本书的范围。
云计算仍处于其发展历程的早期阶段。我们认为,它并不是一个过分炒作、言过其实的最新技术,而是一个真正的进步,其重要性将在未来几年内快速增长。
对等服务
(peer-to-peer service)似乎是最有可能构建大型分布式可扩展系统的技术。然而,对等服务的愿景并不清晰,因为对于供应商来说,很难从对等服务中赚到钱,而云计算仍旧遵循那个很容易理解的如何赚钱的效用计算模型。本质上来说,这也意味着你的应用和你的数据最终都在供应商的掌握中。这可能比你当前的基础设施要好,也可能不好。确切了解生产环境中正在发生什么事情是非常关键的,原因有三。
当创建监控策略时,需要考虑以下四个方面。
首先,最重要的是决定你想收集什么样的数据。监控数据的来源可能有以下几个。
Splunk
近几年里IT运维领域的杀手级工具之一就是Splunk。Splunk会对整个数据中心中的日志文件和其他包含时间戳的文本文件(前面提及的那些数据源都可以通过配置提供时间戳)进行索引。这样,就可以进行实时搜索,精确找到非正常事件,进行根因分析。Splunk甚至可以作为运维信息展示板来使用,并可以通过配置来发送通知。
实际上,为了监控,这些产品使用了各种开放技术。最主要的是SNMP,以及它的后继者CIM和JMX(用于Java系统)
SNMP是监控领域最可敬且最常见的标准。SNMP有三个主要组成部分:受管理的物理设备(如服务器、交换机、防火墙等物理系统),代理器(通过SNMP与那些你想监控和管理的应用或设备进行联系的代理),以及监控被管理设备的网络管理系统。网络管理系统和代理通过SNMP协议进行通信,它是标准TCP/IP栈最顶层的一个应用层协议(application-layer protocol)。SNMP的架构如图11-9所示。
在SNMP中,所有的都是变量。通过查看这些变量来监控系统,通过修改变量来控制它们。而某种类型的SNMP代理使用哪些变量,以及这些变量的描述、类型、是否可写还是只读等这些信息都在一个MIB
(Management Information Base,一种可扩展的数据库格式)中描述。每个供应商都为其所提供的SNMP代理器系统定义了MIB,并且IANA维护了一个中央注册表。与很多设备一样,几乎每个操作系统和大多数常见的中间件(比如Apache、WebLogic和Oracle)及很多设备都自带SNMP。当然,尽管这是一个很平常的事儿,但通过开发和运维团队之间的密切合作,也能为自己的应用程序创建SNMP代理和MIB。
日志也是监控策略的一个必要组成部分。操作系统和中间件都会有日志,对于了解用户的行为和追踪问题根源非常有用。
应用程序也应该产生高质量的日志。尤其重要的是注重日志级别。大多数日志系统有几个级别,比如DEBUG、INFO、WARNING、ERROR和FATAL。默认情况下,应用程序应该只显示WARNING、ERROR和FATAL级别的消息,但当需要做跟踪调试时,可以在运行时或部署时配置成其他级别。由于日志只对运维团队可见,所以在日志信息中打印潜在的异常是可接受的。这对调试工作非常有帮助。
需要记住的是,运维团队是日志文件的主要用户群。对于开发人员来说,当与技术支持团队一起解决用户报告的问题,以及与运维团队解决生产环境的问题时,日志文件是很有启发作用的。开发人员会很快意识到,那些可恢复的应用程序错误(比如某个用户不能登录)不应该属于DEBUG之上的级别,而应用程序所依赖的外部系统的超时就应该是ERROR和FATAL级别(取决于应用程序没有这个外部服务是否还可以处理事务)。
像其他的非功能需求一样,应该把属于审计中的部分日志也作为第一级的需求来对待。与运维团队沟通,找出他们需要什么,并从一开始就把这些需求纳入计划。尤其要考虑日志的全面性与可读性之间的权衡。对于人来说,能够一页一页地翻看日志文件或从中很容易地找出他们想要的数据是非常关键的。也就是说,每一项都应以表格或使用基于列的格式在一行中给出,使时间戳、日志级别,以及错误来自应用程序的什么地方、错误代码和描述能够一目了然。
就像使用持续集成的开发团队那样,运维团队也应该有一个大且易见的显示器。如果有任何突发事件,都可以在上面高亮显示。当出问题时,就可以查看细节找到问题原因。所有开源工具和商业工具都提供这种功能,包括能够看到历史趋势,并生成某种报告。Nagios的一个截屏如图11-10所示。能够知道每个应用程序的哪个版本运行在哪个环境中也是极其有用的,而这也需要一些工具和集成工作
绿灯代表以下条目都已成事实。
黄灯代表以下条目至少有一项是事实。
红灯代表以下条目中至少有一项是事实。
就像开发人员通过写自动化测试做行为驱动开发来验证应用程序的行为那样,运维人员也能写自动化测试来验证基础设施的行为。可以先写个测试,验证它是失败的,然后定义一个Puppet manifest(或者任何所用的配置管理工具)让基础设施达到所期望的状态。接下来运行这个测试来验证这种配置可以正确工作,且基础设置的行为与期望的行为一致。
正如我们说过的,基础设施的配置管理需要做到什么程度,这依赖于它的特性。一个简单的命令行工具对其运行环境的要求不会太高,而一个网站就需要考虑很多基础设施问题。根据我们的经验,对于大多数企业应用来说,当前做的一些配置管理工作是远远不够的,这还会导致开发进度的推迟,以及效率损失,并且会持续增加拥有成本。
我们在本章中提出的建议以及描述的那些策略肯定会增加创建部署流水线的复杂性。它们可能会迫使你找出一些具有创造性的方法来解决第三方产品对配置管理的局限性问题。但是,如果你正在创建一个大而复杂的系统,并有很多配置点,还可能会使用了很多种技术,那么这个方法就可以拯救你的项目。假如比较容易做到基础设施的自动化,而且成本很低,那么谁都会想这么做,最好能直接创建一个生产环境的副本。答案显然就不必说了。可是,假如它是免费的,那么谁都会这么做。因此,对于在任何时刻都能完美重建任何环境的能力,我们唯一在意的问题就是它的成本。因此,在免费和非常高的成本之间的平衡点在哪儿才是值得我们考虑的。
我们相信,使用本章所描述的技术,并选择更广泛的部署流水线策略,你在某种程度上可以承受这些成本。尽管这会增加创建版本控制、构建和部署系统的成本,然而,这部分支出不但会在应用程序的整个生命周期中大大抵消手工环境管理带来的成本,而且在最初的开发阶段也会有所体现。
如果你正在对企业系统中的第三方产品进行可用性评估,那么请确保“是否满足自动化配置管理策略”在评估标准列表中占有较高的优先级。哦,请帮个忙,如果供应商的产品在这方面表现较差的话,给他们一个硬性时间作出响应。在严格的配置管理支持方面,很多供应商都马马虎虎,并不上心。
最后,确保从项目一开始就有基础设施管理策略,并让开发团队和运维团队的干系人参与其中。