《持续交付 发布可靠软件的系统方法》读书笔记
基础设施(infrastructure)代表了你所在组织中的所有环境,以及支持其运行的所有服务,如 DNS 服务器、防火墙、路由器、版本控制库、存储、监控应用、邮件服务器,等等。基础设施不但应该具有自治特性,而且应该是非常容易重新搭建的。这样的话,当有硬件问题时,就能迅速重建一个全新的已知状态的环境配置。所以,基础设施的准备工作也应该是一个自动化过程。自动化的准备工作与自治性的维护相结合,可保证一旦出现问题就能在可预见的时间内重建基础设施。环境是指应用程序运行所需的 所有资源 和它们的 配置信息 。用如下这些属性来描述环境:
- 组成运行环境的服务器的硬件配置信息 - 比如CPU的类型与数量、内存大小、 硬盘和网络接口卡等,以及这些服务器互联所需的网络基础设施。
- 应用程序运行所需要的操作系统和中间件(如消息系统、应用服务器和 Web 服 务器,以及数据库服务器等)的配置信息。
为了减少在类生产环境(production-like environment)中的部署风险,需要精心管 理如下内容:
- 操作系统及其配置信息,包括测试环境和生产环境。
- 中间件软件栈及其配置信息,包括应用服务器、消息系统和数据库。
- 基础设施软件,比如版本控制代码库、目录服务以及监控系统。
- 外部集成点,比如外部系统和服务。
- 网络基础设施,包括路由器、防火墙、交换机、DNS 和 DHCP 等。
- 应用程序开发团队与基础设施管理团队之间的关系。
理解运维团队的需要
无需证明,大多数项目的失败原因在于人,而不是技术本身。对于“将代码部署到测试和生产环境中”这事来说,更是如此。几乎所有大中型公司都会将开发活动和基础设施管理活动(也就是常说的运维活动)分交给两个独立的部门完成。常常能看到这两拨人的关系并不是很好。这是因为往往鼓励开发团队尽可能快地交付软件,而运维团队的目标则是稳定。需要谨记的最重要的事情是:所有的项目干系人都能达成一个共识,即让发布有价值的软件成为一件低风险的事情。根据我们的经验,做这件事的最佳方法就是尽可能频繁地发布(即持续交付)。
文档与审计
运维主管希望确保其所管任意环境中的任意变更都要被记录在案并被审计。这样一旦出了问题,他们可以查到是由哪些修改引起的。软件开发团队的成员也需要熟悉运维团队掌控的这些系统和流程,并遵守它们。制定软件发布时所需遵循的流程也是开发团队发布计划的一部分。
异常事件的告警
运维团队会有自己的系统来监控基础设施和正在运行的应用程序,并希望当系统出现异常状况时收到警报,以便将停机时间最小化。要在项目一开始就了解运维团队希望怎样来监控应用程序,并将其列在发布计划之中,比如,他们想要如何监控?希望把日志放在什么位置?当系统出错时,应用程序要使用怎样的方式通知运维人员?了解并满足运维团队的监控需求,并把这些需求放到发布计划中是开发团队的责任。处理这些需求的最佳办法就是像对待其他需求那样对待它们。主动从运维人员的角度思考,想一下他们会如何应对应用程序——他们是应用程序用户中非常重要的一部分用户。
保障 IT 服务持续性的计划
运维经理要参与组织的 IT 服务连续性计划的创建、实现、测试和维护。运维团队掌管的每个服务都会设定一个 RPO(Recovery Point Objective, 恢复点目标,即灾难之前丢失多长时间内的数据是可接受的)以及一个 RTO(Recovery Time Objective,恢复时间目标,即服务恢复之前允许的最长停机时间)。作为业务持续性测试的一部分,应该对应用程序数据的备份、恢复以及归档工作进行测试,还要获取并部署任意指定版本的应用程序。另外,作为发布计划的一部分,还要将如何执行这些活动的流程提供给运维团队。
使用运维团队熟悉的技术
运维主管希望用运维团队自身熟悉的技术对其管理的环境进行变更操作,这样他们就能真正掌控和维护这些环境了。在每个项目开始时,开发团队和运维团队就应该坐下来,讨论并决定应用程序的部署应该如何执行。一旦所用技术达成一致,双方可能都需要学习一下这些技术。关键在于两个团队都要理解这个部署系统,因为我们必须使用相同的部署过程对每个环境的修改进行部署,这些环境包括开发环境、持续集成环境、测试环境和生产环境。部署系统是应用程序的一个部分。与应用程序的其他部分一样,它也应该被测试和重构,并放在版本控制库中。如果不这么做(我们曾看到过这种事情发生),其结果总是留下一堆疏于测试、易出问题且不易理解的脚本,让变更管理充满风险和痛苦。
基础设施的建模和管理
每种环境中都有很多种配置信息,所有这些配置信息都应该以自动化方式进行准备和管理。如果你对将要开发的系统所用技术有最终决定权的话,那么在项目的启动阶段,你应该回答一个问题:用这种技术做自动化部署和配置软硬件基础设置容易吗?对于系统的集成、测试和部署的自动化来说,使用能够以自动化方式进行配置和部署的技术是一个必要条件。假如你无权控制基础设施的选择,但还想全面自动化构建、集成、测试和部署的话,你必须解决下述问题:
- 如何准备基础设施?
- 如何部署和配置应用程序所依赖的各种软件,并作为基础设施的一部分?
- 一旦准备并配置好基础设施后,如何来管理它?
基础设施的访问控制
控制包括以下三方面:
- 在没有批准的情况下,不允许他人修改基础设施。
- 制定一个对基础设施进行变更的自动化过程。
- 对基础设施进行监控,一旦发生问题,能尽早发现。
因为我们相信,应该像对待生产环境一样对待测试环境,在这两种环境上要使用同样的流程。对生产环境和测试环境的变更请求应该执行一个变更管理流程。
对基础设施进行修改
高效的变更管理流程有如下几个关键特征:
- 无论是更新防火墙规则,还是部署 flagship 服务的新版本,每个变更都应该走同样的变更管理流程。
- 这个流程应该使用一个所有人都需要登录的 ticketing 系统来管理。这样就可以得到有用的度量数据,比如每个变化的平均周期时间。
- 做过的变更应该详细清楚地记录到日志中,这样便于以后做审计。
- 能够看到对每个环境进行变更的历史,包括部署活动。
- 想做修改的话,首先必须在一个类生产环境中测试通过,而且自动化测试也已经运行完成,以确保这次变更不会破坏该环境中的所有应用程序。
- 对每次修改都应该进行版本控制,并通过自动化流程对基础设施进行变更。
- 需要有一个测试来验证这次变更已经起作用了。
良好的变更管理的关键在于创建一个自动化流程,从版本控制库中取出基础设施的变更项进行部署。加强可审计性的最佳方法是用自动化脚本来完成所有变更。这样,万一后来有人想知道到底做了哪些修改的话,就很容易找到了。因此,通常情况下,我们认为使用自动化方式要优于手工文档。手工文档无法保证所记录的变更是完全正确的,比如“某人说他做过了什么事情”与“他实际上做了什么”,这之间的差异足以让你花上几小时甚至几天的时间去查找问题根源。
服务器的准备及其配置的管理
服务器的准备
创建操作系统基线有如下几种方法:
- 完全手工过程。
- 自动化的远程安装。
- 虚拟化。
我们不会考虑完全手工过程,因为它不具有可靠的重复性,所以也没办法扩展。
服务器的持续管理
一旦安装好操作系统后,就要保证任何配置的修改都是以受控方式进行的。也就是说,首先确保除运维团队之外,没有人能登录到这些服务器上,其次使用某种自动化系统来执行所有修改。这些修改包括应用操作系统的服务包(service pack)、升级、安装新软件、修改配置项,以及执行部署。一旦这个系统准备好之后,就能用一个被集中版本控制的配置管理系统对基础设施中的所有测试环境和生产环境进行管理了。之后,就可得到如下收益:
- 确保所有环境的一致性。
- 很容易准备一个与当前环境配置相同的新环境,比如创建一个与生产环境相同的试运行环境。
- 如果某个机器出现硬件故障,可以用一个全自动化过程配置一个与旧机器完全相同的新机器。
中间件的配置管理
在操作系统的配置项被恰当地管理起来后,就需要考虑在其之上的中间件的配置管理了。
管理配置项
数据库模式(schema)、Web服务器的配置文件、应用服务器的配置信息、消息队列的配置,以及为了系统能正常工作需要修改的其他方面都应该进行版本控制。
产品研究
在寻找低成本、低消耗的解决方案时,最好的着手点是绝对确保该中间件产品具有自动配置的选项。细心地读一下说明文档,找到这类选项,在互联网上搜索一些建议,与产品的技术支持人员聊一下,并在论坛或群组中征求一下意见。
考查中间件是如何处理状态的
如果已经确定所用中间件的确不支持任何形式的自动化配置,接下来就要看看是否能够通过对该产品后台的存储方式做版本控制了。大多数产品会用某种形式的文本文件来为其存储配置信息,那么你将面对的主要问题是该产品如何以及何时读取相关的配置信息。在那些对自动化提供友好支持的情况下,只要复制这些文件的最新版本到正确的位置就够了。如果这样可行的话,就能够进行下一步工作,将该产品的二进制包与它的配置相分离。
查找用于配置的 API
很多产品会提供某种可编程接口。有些产品会提供一些API足以让你对系统进行配置,满足你的需求。一种策略是自己为系统定义一个简单的配置文件。创建自定义的构建任务来解释这些脚本,并使用API对系统进行配置。
使用更好的技术
理论上,你可以尝试一些其他方法。例如,自行创建有利于版本控制的配置信息,然后写一些代码,通过产品自身的使用方式把它们映射到你所选产品的配置上。
基础设施服务的管理
经常看到一些已经成功通过部署流水线并正在生产环境中运行的软件因为基础设施服务的问题(比如路由、DNS和目录服务)而不能正常工作的情况。我们有如下几个建议:
- 网络基础设施配置的每个部分都应该进行版本控制。
- 安装一个好用的网络监控系统,保证当网络连接被破坏时你就会得到通知,而且监控应用程序所使用的每个路由的每个端口。
- 日志是你的好伙伴。
- 确保冒烟测试在部署时检查所有的连接,找出潜在的路由或连接问题。
- 确保集成测试环境的网络拓扑结构尽可能与生产环境相似,包括使用同样的硬件和物理连接(甚至使用相同的 socket 和同样的缆线)。
虚拟化
虚拟化有助于减少部署软件所花费的时间,并用一种不同的方式来降低与部署相关的风险。就在系统的宽度与深度两方面达到高效配置管理来说,部署领域中虚拟机的使用帮了很大的忙。
虚拟环境的管理
虚拟机技术的最重要特性之一就是一个虚拟机映像只是一个文件。这个文件叫做“磁盘映像”。磁盘映像的好处在于可以复制它们,并对它们进行版本控制。如果有虚拟化基础设施,那么就可以创建一个已准备好的服务器的磁盘映像,把它作为所有具有相同配置的服务器的模板。这些模板组成了基线,一个已知处于良好状态的环境版本。在这个版本上,其他所有配置和部署都可以正常运行。
虚拟环境和部署流水线
部署流水线的目的是,对应用程序做的每个修改都能通过自动化构建、部署和测试过程来验证它是否满足发布要求。
用虚拟环境做高度的并行测试
虚拟化提供了一种绝好的方法来处理多平台测试。只要为应用程序可能运行的每种平台创建虚拟机,并在其上创建VM模板。然后在所有这些平台上并行运行部署流水线中的所有阶段(验收、容量和UAT)就行了。现代持续集成工具对这种方法都提供直接支持。可以使用同样的技术让测试并行化,从而缩短代价高昂的验收测试及容量测试的反馈周期。假设所有的测试都是独立的,那么就可以在多台虚拟机上并行执行它们。
云计算
在云计算中,信息存储在因特网中,并通过因特网上的软件服务进行读取和使用。云计算的特征是:通过扩展所使用的计算资源(比如 CPU、内存、存储等)来满足需求,而只需要为自己所使用的这些资源付费就行了。云计算既包括它所提供的软件服务本身,也包括这些软件所用到的软硬件环境。云计算的大体上分为三类:云中的应用、云中的平台和云中的基础设施。
云中基础设施
云中基础设施是最高层次的可配置性,比如AWS。AWS提供了很多基础设施服务,除了著名的名为EC2的虚拟机托管服务以外,还包括消息队列、静态内容托管,流媒体托管,负载均衡和存储。利用这些服务,几乎可以对系统进行完全控制,但也要做一些工作把这些东西绑定在一起。
云中平台
云中平台的优点:
- 就成本结构和准备工作的灵活性而言,它与云中基础设施的收益是一样的。
- 服务供应商会处理非功能需求,比如可扩展性、可用性和某种程度的安全性。
- 将应用部署到完全标准化的应用栈上,就意味着不需要担心测试环境、试运行环境和生产环境的配置和维护,也不需要担心虚拟机映像的管理。
基础设施和应用程序的监控
确切了解生产环境中正在发生什么事情是非常关键的,原因有三。首先,如果有实时的商业智能(BI),业务人员可以更快地从他们的策略得到反馈,比如产生了多少收入,这些收入来自哪里。其次,当出了问题时,需要立即通知运维团队有事情发生,并利用必要的工具追溯事件的根因并修复它。最后,出于计划目的,历史数据也非常重要。
收集数据
收集什么样的数据?监控数据的来源可能有以下几个:
- 硬件:电压、温度、系统风扇速度、peripheral health,等等。
- 操作系统:内存使用、交换空间(SWAP)的使用、磁盘空间、I/O 带宽(每个磁盘和 NIC)、CPU 使用情况,等等。
- 中间件:如内存、数据库连接池、线程池,以及连接数、响应时间,等等。
- 应用程序:应用程序应该设计实现一些数据监控的钩子(hook)功能,这些数据应该是运维人员和业务人员比较关心的,比如业务交易数量、它们的价值、转换率,等等。
记录日志
日志也是监控策略的一个必要组成部分。操作系统和中间件都会有日志,对于了解用户的行为和追踪问题根源非常有用。应用程序也应该产生高质量的日志。尤其重要的是注重日志级别。大多数日志系统有几个级别,比如 DEBUG 、INFO 、WARNING 、ERROR 和 FATAL 。
建立信息展示板
就像使用持续集成的开发团队那样,运维团队也应该有一个大且易见的显示器。如果有任何突发事件,都可以在上面高亮显示。当出问题时,就可以查看细节找到问题原因。你能监控的信息有数千种之多,所以提前规划一下,让运维信息展示板不要太杂乱还是非常必要的。
行为驱动的监控
就像开发人员通过写自动化测试做行为驱动开发来验证应用程序的行为那样,运维人员也能写自动化测试来验证基础设施的行为。
小结
在本章中提出的建议以及描述的那些策略肯定会增加创建部署流水线的复杂性。它们可能会迫使你找出一些具有创造性的方法来解决第三方产品对配置管理的局限性问题。但是,如果你正在创建一个大而复杂的系统,并有很多配置点,还可能会使用了很多种技术,那么这个方法就可以拯救你的项目。假如比较容易做到基础设施的自动化,而且成本很低,那么谁都会想这么做,最好能直接创建一个生产环境的副本。答案显然就不必说了。可是,假如它是免费的,那么谁都会这么做。因此,对于在任何时刻都能完美重建任何环境的能力,我们唯一在意的问题就是它的成本。因此,在免费和非常高的成本之间的平衡点在哪儿才是值得我们考虑的。确保从项目一开始就有基础设施管理策略,并让开发团队和运维团队的干系人参与其中。