封面
译者介绍
数字版权声明
扉页
版权
版权声明
O’Reilly Media, Inc.介绍
目录
中文版推荐序
译者序
前言
第一部分 基础
第1章 挑战与原则
1.1 为什么采用基础设施即代码
1.2 什么是基础设施即代码
基础设施即代码是一种基于软件开发实践的基础设施自动化方法。它强调系统及其配置的日常置备和变更具有一致性和可重复性。先修改配置的定义代码,再通过包括全面验证的无人值守过程应用到系统中去。
这种方法的前提是,现代工具可以把基础设施作为软件和数据进行处理
本书旨在解释如何利用云时代的基础设施即代码方法来管理 IT 基础设施。本章探讨了组织在采用新一代基础设施技术时经常掉进的陷阱,详述了避开这些陷阱的核心原则以及基础设施即代码的关键实践。
基础设施即代码的目标
1.3 动态基础设施的挑战
1.3.1 服务器蔓延
很多团队和组织期待通过基础设施即代码实现如下目标。• IT 基础设施支持并允许变更,而不是成为阻碍或者约束。• 对系统的变更是家常便饭,不应该对用户或者 IT 人员造成惊吓或者压力。•IT 人员把时间花费在体现自身能力的有价值的事情上,而不是花费在处理日常的重复性工作上。• 用户可以自行定义、置备和管理他们需要的资源,不需要 IT 人员参与。• 团队能够轻松、快速地从故障中恢复,而不是假设可以完全避免故障。• 持续地改进,而不是通过昂贵且危险的“大爆炸”项目去改进。• 通过实施、测试和测量来验证问题解决方案,而不是利用会议和文件进行讨论。
想法:2023-11-15 10:14:05
期待IaC具有的能力:支持变更常态化、自动化;支持用户自行处置资源;有轻松处理故障的能力;有渐进式增减功能的能力;通过实际行动(实施、测试、测量,而非会议)解决问题;
本节关注团队采用动态基础设施和自动化配置工具时常见的一些问题。这些问题是基础设施即代码要着力解决的
服务器蔓延利用云和虚拟化,从资源池置备新的服务器可谓小菜一碟。这会导致服务器的数量飞速增长,甚至超过团队能够管理或者希望管理的规模。
当这种情况发生时,团队会忙于给服务器打补丁并且让它们保持更新,系统容易受到已知漏洞的影响。当发现问题时,补丁无法及时地应用到可能受影响的所有系统上。服务器之间的版本和配置差异意味着在一些机器上运行良好的软件和脚本无法在其他机器上运行。这会导致服务器之间的不一致,也叫作配置漂移。
1.3.2 配置漂移
1.3.3 雪花服务器
配置漂移即便服务器在最初创建和配置的时候是一致的,其差异也会随着时间而增加。
不一样并非不好。相比负载较低的服务器,负载高的 JBoss 服务器理应有不同的调优配置。但是这些变化应该以一种易于重现和重建服务器及服务的方式进行捕获和管理。服务器间未经管理的变化会导致雪花服务器的产生和对自动化的恐惧。
雪花服务器雪花服务器和网络中的其他所有服务器都不同。它非常特殊,无法复制。
大多数 IT 运维团队都有过这样的尴尬:不能触碰或者难以复制服务器。如此脆弱的原因并非总是神秘莫测,有时是因为某个重要的软件运行在与其他服务器完全不同的操作系统上
1.3.4 脆弱的基础设施
1.3.5 自动化恐惧症
再次强调,不一致并非坏事。问题在于拥有服务器的团队对于服务器如何以及为何不一致一无所知,并且无法重建服务器。运维团队应当能够自信、快速地重建基础设施中的任意服务器。如果有任何服务器不能满足这个需求,团队的最高优先级应该是设立一个可复制的全新流程,来构建一台新的服务器并替换掉老的服务器。
脆弱的基础设施脆弱的基础设施很容易中断,而且不容易修复。这是由于雪花服务器问题扩展到了整个系统组合。解决方案是逐步将基础设施中的一切迁移到可靠、可复制的基础设施里
自动化恐惧症
我之所以不敢完全信任自动化工具,是因为我对它们做的事情缺乏信心。我之所以缺乏对自动化的信心,是因为我的服务器不一致。我的服务器之所以不一致,是因为我没有频繁和一致地执行自动化。这就是自动化恐惧恶性循环,如图 1-1 所示。基础设施团队需要打破这种恶性循环,才能成功实施自动化。最有效的方式是直面恐惧。挑选一组服务器,调整配置定义,确保它们可以工作,并安排它们至少每小时以无人值守的方式运行一次。然后,挑选另一组服务器并重复这个过程,直到所有的服务器都持续更新。
1.3.6 侵蚀
1.4 基础设施即代码的原则
1.4.1 系统能够轻松复制
侵蚀
侵蚀的意思是,问题随着时间的推移蔓延到正常工作的系统之中。
基础设施即代码的原则
系统能够轻松复制我们应该能够毫不费力并且可靠地重建基础设施中的任何元素。毫不费力意味着无须对于如何构建元素做出任何重大的决策。在服务器上安装什么软件、安装软件的什么版本以及选择什么主机名等决策都应该包括在置备基础设施元素的脚本和工具中。
1.4.2 系统是用完可扔的
系统是用完可扔的动态基础设施的好处之一是可以轻松创建、销毁、替换、扩容和移动资源。为了利用这一点,设计系统时必须假设基础设施始终在变更。即使服务器消失了、出现了或者大小改变了,软件也应该依然正常运行。这种优雅处理变更的能力让增强和修复正在运行的基础设施变得更容易,也使得服务具有更强的容错性。当共享大规模的云基础设施无法保证底层硬件的可靠性时,这种能力变得尤为重要。
铁器时代和云时代的根本差异在于,铁器时代是不可靠的软件运行于可靠的硬件之上,而云时代是软件可靠地运行于不可靠的硬件之上
1.4.3 系统是一致的
1.4.4 过程是可重复的
1.4.5 设计经常变更
系统是一致的假设两个基础设施元素提供相似的服务,例如同一个集群中的两台应用程序服务器,那么这些服务器应该几乎完全相同。它们的系统软件和配置应该是一样的,除了一点点区分彼此的配置,比如 IP 地址。
遵循了可复制性原则的团队可以轻松构建多个完全相同的基础设施元素。如果需要修改其中一个元素(例如一台文件服务器需要更大的磁盘分区),有两种方式可以保持一致性。一是修改对服务器的配置定义,使得所有的文件服务器都拥有足够大的分区。二是添加新的类型或者角色,比如 xl-file-server,其硬盘比标准的文件服务器大得多。每种类型的服务器都能被重复构建,而且保持了一致性。
过程是可重复的基于可复制性原则,对基础设施执行的任何操作都应该是可重复的。
设计经常变更
1.5 实践
1.5.1 使用定义文件
1.5.2 自文档化的系统和流程
前提是一切设计都支持变更。软件和基础设施的设计必须在满足当前需求的同时尽可能简单。变更管理必须能安全和快速地交付变更。
本节将介绍基础设施即代码的一些通用实践
使用定义文件基础设施即代码的基础实践是使用定义文件(definition file)。定义指定了基础设施元素以及应该如何配置它们。定义文件作为输入,供置备或配置这些元素实例的工具使用。
基础设施元素可以是一台服务器、服务器的一部分(比如用户账号)、网络配置(比如负载均衡规则),等等。不同的工具对此有不同的术语,例如 playbook(Ansible)、recipe(Chef)或者 manifest(Puppet)。本书使用“配置定义文件”作为这些术语的统称。
定义文件以文本文件的形式进行管理。它们可能会使用标准的格式,如 JSON、YAML 或者 XML,也可能会定义自己的领域特定语言(domain-specific language,DSL)
自文档化的系统和流程IT 团队通常要尽全力保持文档的相关性、实用性和准确性
1.5.3 一切版本化
有了基础设施即代码,执行流程的步骤会保存在脚本、定义文件以及实现这个过程的工具中。人们只需要添加极少量的文档,就可以开始工作了。已经存在的文档应当离源代码很近,保证这些文档在人们做出变更时触手可及、触目可见。
一切版本化版本控制系统(version control system,VCS)是基础设施即代码的一个核心部分。VCS 是基础设施期望状态的真实数据来源。基础设施的变更由提交到 VCS 的变更所触发。
为什么 VCS 对基础设施管理来说至关重要呢?
想法:2023-11-15 14:02:14
可追溯:调试问题时能查看变更历史、变更者、变更原因; 可回滚:出现问题可恢复之前状态; 相关性:一整套内容通过版本号关联,便于问题追踪和修复; 可见性:增加了变更的感知能力,变更更新后,人人可见,可对照是否和期望对应上; 可执行:变更提交时自动触发执行脚本;
1.5.4 持续测试系统和流程
1.5.5 小的变更,而不是批量变更
1.5.6 让服务持续可用
持续测试系统和流程
自动化测试是高效能开发团队的一个核心实践。他们在编写代码的同时实现测试,并持续运行测试。随着每天对代码库做增量的变更,他们一天通常会运行数十次自动化测试。
在开发过程中持续运行测试可以对变更给出快速的反馈。快速反馈让人们有信心快速、更频繁地进行变更。这在自动化的基础设施中尤其强大,因为一个小小的变更就可以非常快地造成很大的破坏(即 DevOops,详见 12.2 节结尾)。良好的测试实践是消除自动化恐惧的关键因素。
小的变更,而不是批量变更
即使针对较大的任务,一个一个地找出可以独立开发、测试和发布的增量变更也是很有帮助的。我们有很多理由选择小的增量变更,而不是大的批量变更。• 小的变更更容易测试和确认可靠性,且工作量更少。• 与大批量变更相比,小的变更出现问题更容易找到原因。• 小的变更修复和回滚起来更迅速。• 大批量变更中的一个小问题会造成变更中的所有内容都延迟发布,即使变更中的绝大部分内容都没问题。• 问题的修复和改进会鼓舞士气,而堆积如山的待完成工作会让士气低落。
想法:2023-11-15 14:09:27
小的变更:容易测试、可靠性高、工作量少、问题查找修复更快、发布更快、能鼓舞士气
让服务持续可用无论基础设施发生了什么,服务总是能够响应请求,做到这一点很重要
1.6 反脆弱性:超越“稳健性”
反脆弱IT系统的秘诀
不管服务器发生了什么,服务数据都需要保持完整。这个目标可以通过数据复制和其他一些已经存在了数十年的方法来达到。当设计基于云的系统时,重要的是拓宽“需要留存的数据”的定义,通常包括应用程序配置、日志文件等。
反脆弱性:超越“稳健性”
同样,通过减少变更次数来保护 IT 系统,并不会使它更稳健。相反,那些持续变更和改善系统的团队则能更好地应对灾难和事故。
反脆弱 IT 基础设施的关键是,保证对突发事件的默认响应动作是改善。当系统出现问题时,当务之急并不是修复它,而是提高系统在未来对类似事故的响应能力。
自动化是指自动运行系统而无须人类参与
持续改善 IT 系统的关键在于那些构建并运行它的人,所以要设计可适应变化的系统,秘诀就是围绕人进行设计
1.7 结语
1.8 下一步
高效基础设施团队的标志在于,它能够很好地处理不断变化的需求。高效团队会将需求分解成小的任务,并在低风险、低影响的快速变更流中流转这些任务,从而轻松地处理变更和新需求。
以下迹象标志着团队做得很好。• 基础设施的每一个元素都可以迅速且毫不费力地重建。• 所有系统都持续打了补丁,并保持一致和最新。• 在没有基础设施团队成员的参与之下,标准的服务请求(包括置备标准的服务器和环境)都可以在几分钟内完成。SLA 不是必要的。• 很少需要维护窗口。在工作时间执行包括软件部署和其他高风险活动在内的变更。• 团队跟踪平均恢复时间(mean time to recover,MTTR),并重点关注如何改善它。尽管也可以跟踪平均故障间隔时间(mean time between failure,MTBF),但团队并不依赖于它去避免故障。9• 团队成员觉得他们的工作给组织增加了可衡量的价值。
接下来的 4 章将重点关注基础设施即代码的工具。如果你已经熟悉了这些工具,可以快速浏览或跳过这几章
我将工具介绍分为 4 章。如同任何分类模型一样,这样的划分并不是绝对的。许多工具会跨越边界或者与这些定义不甚相符。这样分组只是为了方便地对运行动态基础设施所涉及的许多工具进行探讨。
动态基础设施平台用于提供和管理基本的基础设施资源,尤其是计算(服务器)、存储和网络。这些包括公有和私有的云基础设施服务、虚拟化和物理设备的自动配置。这是第 2 章的主题。基础设施定义工具用于管理服务器、存储设备和网络资源的分配和配置。这些工具在高层次上置备和配置基础设施。这是第 3 章的主题。服务器配置工具这些工具处理服务器本身的细节,包括软件包、用户账号以及各种类型的配置。这组特定的工具包括 CFEngine、Puppet、Chef 和 Ansible。它们也是人们在讨论基础设施自动化和基础设施即代码时会首先想到的。这些工具将在第 4 章中讨论。基础设施服务帮助管理基础设施和应用程序服务的工具和服务,如监控、分布式进程管理及软件部署等。这是第 5 章的主题。
第2章 动态基础设施平台
2.1 什么是动态基础设施平台
本章介绍各种类型的动态基础设施平台,这类平台为置备和管理核心基础设施资源提供了基础。我们的目标是理解为了有效地支持基础设施即代码,平台需要提供哪些典型能力、服务模型以及功能。
动态基础设施平台是提供了计算资源(具体包括服务器、存储和网络),并且支持程序化分配和管理这些资源的系统。
想法:2023-11-15 14:26:29
动态基础设施平台即提供了云服务的软件,或者是能自动化置备管理裸机硬件的软件
不同类型的动态基础设施平台及示例
想法:2023-11-15 14:24:33
公有IaaS云:AWS、Azure、Digital Ocean、GCE和Rackspace Cloud; 社区laaS云:政府部门之间共享的云服务; 私有IaaS云:CloudStack、OpenStack 和VMware vCloud; 裸机云:Cobbler、FAI和 Foreman
动态基础设施平台是云、虚拟机还是裸机都不重要,重要的是可以用脚本和工具自动地创建和销毁基础设施中的元素,报告它们的状态并管理元数据。
2.2 对动态基础设施平台的要求
2.2.1 可编程
尽管像 AWS 这样的公有基础设施云是动态基础设施平台最知名的范例,但许多组织实现了自己的私有基础设施云。本书侧重于介绍在已有的平台上构造基础设施,因此不会讨论如何构建你自己的基础设施平台。
对动态基础设施平台的要求基础设施即代码的意思是如何把基础设施当作软件系统,这就意味着动态基础设施平台需要具备某些特征。这个平台需要具备如下特征:• 可编程;• 按需获取;• 自服务。
想法:2023-11-15 14:31:22
美国国家标准和技术协会(NIST)发布了关于云计算的精彩定义。它列出了云的5个基本特征: ·按需自服务(置备); ·广泛的网络接入(可以通过“标准的机制”从网络上接入); ·资源池(多租户); ·快速的弹性伸缩(可以快速甚至自动添加和删除元素); ·可度量的服务(可以对资源的使用计费)。
动态基础设施平台的定义要比云宽泛一些。资源池不是基础设施即代码的要求,也就意味着计费不是必需的。
可编程动态基础设施平台必须是可编程的。用户界面是很方便,而且大部分虚拟化产品和云服务商都会提供。但是脚本、软件和工具必须能够与平台交互,这就需要可编程 API。
大部分基础设施平台通过网络 API 暴露其管理功能,其中 REST API 因其易用性和灵活性而最为流行
2.2.2 按需获取
2.2.3 自服务
2.3 平台提供的基础设施资源
按需获取对于基础设施即代码来说,动态基础设施平台支持资源的即时创建和销毁非常关键。
想法:2023-11-15 14:40:15
支持按需、累计的收费,而非长期计费承若
想法:2023-11-15 14:36:25
即时性很重要,而非层层申请
自服务自服务在按需获取之上对基础设施平台额外增加了一些要求。基础设施用户不仅应该能够快速获得资源,还应该能够依照自己的需求调整和定制这些资源。
基础设施即代码假设并要求团队使用脚本和工具自动化地指定、置备并调整资源。这让使用基础设施的团队能够围绕他们的需求进行调整和演进。
基础设施用户拥有能够轻松、常态化地修改其基础设施的能力,意味着他们能够快速地修正错误。此外,使用本书中针对变更的自动化测试和预发布,可以降低中断其他服务的风险。
平台提供的基础设施资源基础设施管理拥有许多活动部件。动态基础设施平台提供了 3 种主要的基本组件:计算、存储和网络
2.3.1 计算资源
2.3.2 存储资源
大部分平台提供的服务列表远远超出这 3 种,但其他服务几乎都只是这些服务的各种变化(例如不同类型的存储)或者在它们之上的服务组合。例如服务器镜像管理(支持计算的存储)、负载均衡(网络,可能基于计算实例)、消息(网络和计算)和认证(在计算实例上运行的应用程序)。甚至像 Kinesis 这样无服务器的计算服务,也是通过在常规的计算资源上运行任务来实现的。
计算资源计算资源就是服务器实例。任何动态基础设施平台都能创建和销毁虚拟机,还有一些服务和功能让服务器管理更容易、更强大。
存储资源虚拟化基础设施消耗了数量惊人的存储——动态创建服务器吞噬磁盘空间的速度非常惊人。基础设施平台需要为服务器、快照、模板等分配磁盘空间,同时还要使运行在这些服务器上的应用程序和服务有存储可用。
虚拟化平台可能不会透明地提供存储,所以置备服务器的脚本可能需要查找空间足够的存储池,然后将其分配给新的实例。
基础设施团队管理好磁盘空间的使用非常重要。至少需要将用量和费用信息通过仪表盘清晰地展示出来(5.3.1 节有关于用好信息辐射器的讨论),这样人们就知道什么时候应该检查并剔除不需要的资源。清理旧模板和快照的自动脚本会很有用。
除了计算资源所需的存储,动态基础设施平台还需要为运行于其上的服务和应用程序提供存储。大部分云平台提供两种类别的存储服务:块存储和对象存储。
块存储块存储卷可以像本地磁盘一样挂载在服务器实例上。云平台提供的块存储服务的例子包括 AWS 的 EBS、OpenStack 的 Cinder 和 CGE 的持久磁盘。
它们的存在可以比某个特定服务器的生命周期还长,这对于管理持久化数据和连续性策略特别有用
对象存储许多云平台提供对象存储服务,其中的文件可以在基础设施的不同地方存储和访问,甚至可以公开使用。亚马逊的 S3、谷歌的 Cloud Storage、Rackspace 的 Cloud Files 以及OpenStack 的 Swift 都是此类存储。
对象存储通常是作为长期存储设计的,比块存储的可靠性更高、成本更低,但是时延会更高。它适用于存储需要从多个服务器上访问的制品,块存储与之不同,只能从挂载它的服务器上访问。
网络文件系统基础设施团队经常需要在多个服务器实例之间更直接地共享存储。一种方式是使用像 NFS或者 SMB/CIFS 之类的文件共享网络协议。服务器实例可以挂载本地或块存储,并让其他服务器挂载和使用。
诸如 GlusterFS、HDFS 或 Ceph 的分布式和(或)集群式文件服务工具的设计使之更适合在动态基础设施中使用。它们确保了文件在多个服务器节点间都是可用的,也能更平稳地应对服务器节点的添加或移除。但是也不要假设这能完美解决问题,你不仅一定要对性能和延迟进行测试,而且还要针对集群变更的影响以及失败场景进行测试。在决定使用何种特定的技术和工具之前,想清楚使用场景。我看到过至少一个团队实现了复杂却脆弱的 GlusterFS 集群,仅仅是为了实现容错,也就是当第一台服务器出故障的时候,另外一台灾备服务器能够确保数据继续可访问。直接使用平台内建的服务,如块存储复制,通常更加简单、可靠。
2.3.3 网络资源
网络资源动态基础设施平台需要管理内部元素之间以及与外部网络的网络互通。在基础设施中添加和删除服务器,需要更新网络路由、负载均衡池和防火墙规则。大部分虚拟化或者云化的基础设施平台都提供动态、虚拟化的网络来处理网络互通。然而这些平台通常都安装和运行在拥有自己网络基础设施的更大资产之上。为了让动态基础设施平台中的元素和其他部分无缝地在一起工作,需要对接周边的网络。
自动化配置周边网络也是可能的,这样就能够容易地处理动态基础设施的变更。这给网络资产带来了基础设施即代码的所有好处:可重复性、持续测试以及一致性。
2.4 动态基础设施平台的类型
2.4.1 公有IaaS云
2.4.2 社区IaaS云
2.4.3 私有IaaS云
动态基础设施平台的类型
公有IaaS云公有云是由供应商构建和运行的标准云服务。计算资源会在供应商的客户之间共享,你只需要为自己使用的部分付费。例子有亚马逊的AWS、微软的 Azure、Digital Ocean、谷歌的 GCE 和 Rackspace Cloud。
社区IaaS云社区云是为有限的客户群体构建和运行的云服务(例如为政府部门服务的云)。云服务可能会为了满足这个群体的特定需求做一些调整,例如遵循某个安全标准。它也有可能对访问进行限制,比如确保不能在与社区外部客户共享的系统和硬件上存储或传输客户数据。
私有IaaS云私有云是为单个组织的多个客户(例如公司内不同的部门或团队)构建和运行的云服务。可能会有供应商为该组织构建、运行甚至托管私有云,但是其资源不会和其他组织共享。即使并不是所有的资源都会被占用,公司也一般为整个可用的容量付费。根据各部门的需要和预算,公司可能会有内部的收费或者容量限制。
私有 IaaS 云服务产品包括 CloudStack、OpenStack 和 VMware 的 vCloud。
云服务的类型:IaaS、PaaS 和 SaaS
从允许多个用户共享计算资源这点来讲,它们每个都是云,但是其用户却截然不同。
软件即服务(SaaS)在最终用户之间共享的应用程序,可能是面向最终用户的,比如网页版的电子邮件软件。但是实际上有一些 SaaS 产品是面向基础设施团队的,包括监控甚至配置管理服务器。
2.4.4 反模式:手摇云
2.4.5 混合云服务
2.4.6 裸机云
平台即软件(PaaS)让开发者构建、测试并托管软件的共享平台。它抽象了底层的基础设施,这样开发者就不需要操心应用程序或者数据库集群应该分配多少台服务器,因为平台都已经搞定了。许多 IaaS 云提供商提供的服务本质上是 PaaS 的服务元素(例如亚马逊的管理数据库服务 RDS)。
基础设施即服务(IaaS)共享的硬件基础设施,系统管理员可以用其为各种服务构建虚拟的基础设施。
想法:2023-11-15 14:51:52
强调硬件设施
反模式:手摇云手摇式虚拟化基础设施是指使用虚拟化工具来管理硬件资源,但是这些资源没有以自服务或者动态的方式提供给用户。
混合云服务简单地说,混合云就是指一部分基础设施运行在私有云上,另一部分运行在公有云上。有一种严格来说不算混合云但也很常见的做法,就是把一些服务运行在云化的基础设施上,再集成一些以传统方式管理的基础设施上的服务。
这种混合基础设施的出现有下面这些原因。• 因为监管或者安全需求,一些数据需要保存在更为受限的环境之中。• 一些服务有可变的容量需求,托管在公有云上充满吸引力;另外一些服务则相当固定,没有必要运行在公有云上。• 将已有服务从传统的基础设施上迁移出来的投入也许没那么合理。如果组织仍处于采用公有云的早期阶段,那就更是如此了。但是在很多情况下,可能有一定数目的服务永远不适合迁移到公有云上。
裸机云有了虚拟化基础设施,多台虚拟服务器可以在单台物理服务器上运行,而且可以根据需要在物理服务器之间切换。这有助于最大化利用可用的硬件。但是在很多情形下,操作系统仍然需要直接运行在硬件而不是虚拟机上面。幸运的是,即使在这些情形下,依旧可以应用基础设施即代码。对于给定的应用程序或服务,有很多原因可以解释为何在硬件上直接运行也许是最好的选择。虚拟化增加了性能开销,因为它在应用程序和所使用的硬件资源之间增加了额外一层抽象。
2.5 如何选择动态基础设施平台
2.5.1 公有还是私有
团队需要能在硬件层运行的自动化动态基础设施平台。它需要拥有本章前面提到的能力,包括能够置备和分配计算资源、存储和网络。它应该是可编程的、动态的,而且要支持自服务模型,只有这样才能用脚本完成这些活动。
有些工具可以用来在裸机上实现动态基础设施平台,包括 Cobbler、FAI、Foreman 和 Crowbar。这些工具可以利用 PXE(preboot execution environment)规范启动一个从网络上下载的基础操作系统镜像,这个镜像接着会运行一个安装程序去下载并启动操作系统安装镜像。这个操作系统安装镜像会运行一个脚本,使用类似 Kickstart 的工具配置操作系统,接着可能运行 Chef 或者 Puppet 之类的配置管理工具。通常,触发服务器来使用 PXE 启动一个网络镜像,需要在这个服务器启动的时候按一个功能键。这对于无人值守安装可能有点棘手,但是许多硬件供应商都有无人值守管理功能(lights-out management,LOM),可以远程甚至自动地完成安装。
想法:2023-11-15 14:56:17
裸机云的例子
如何选择动态基础设施平台
公有还是私有建议把组织的 IT 基础设施迁移到公有云上时,需要关注下面这些问题。
安全和数据保护
不管使用公有云、外部供应商还是内部 IT,从来没有什么可以取代好的安全策略和实施。你的团队需要针对自己的服务全面考虑安全风险和威胁模型,然后将这些理解应用到不同的托管选项中,制定出最佳的方式。在许多情况下,混合基础设施可能适合用来隔离某些类型的数据和操作。
对托管位置的法律约束一些组织限制了数据和系统托管的位置。来自政府的合同可能会要求系统托管在本国,或者禁止托管在其他某些国家。一些地方的隐私法不允许将用户数据传输到对数据使用保护没那么严格的国家。
对于可变容量的需求你需要清楚组织的容量需求,并且理解独占的基础设施与供应商的共享资源池分别对容量需求的影响。使用公有云服务的一个重要好处是可以很快地调整你的容量,而且只为你需要使用的容量付费。
2.5.2 云的可移植性
自己构建云服务的总体成本
商业产品还是差异化
基础设施的置备已经变得像商业产品一样,到了具备编程接口,可以按照标准化、可互换、自动化的方式提供服务的程度。
当计划迁移到基于云的基础设施上时,一个常常出现的需求是避免锁定在单个云供应商。有些工具集和产品可以使云平台之间的迁移更容易。然而需要特别小心,避免花费了大量的时间和精力之后,发现迁移到另外一个云供应商仍然复杂、昂贵且充满风险。
对可移植性能够达成的目标保持现实,这点很重要。这个需求背后的主要驱动力来自管理未来替换云供应商的风险,并且通过降低潜在迁移的成本和风险,保留迁移可行性的选项。在这种情况下,没有必要保证迁移是零代价的。
确保可以无痛地离开某个云供应商的方法只有一个,那就是从一开始就构建一个跨供应商的基础设施
在多个云上运行消除了迁移和锁定的风险,但是显著增加了实施和运行基础设施前期与过程中的成本和时间。
想法:2023-11-15 15:04:25
在成本和迁移之间抉择
可移植性技术
如果系统运行在单个云平台上,有一些技术可以使未来的迁移更容易。一个技术是避免使用厂商特有的功能。这有一个缺点:你可能错失一些或许能够在构建和运行系统时节省时间与成本的功能和服务。记录下基础设施使用的厂商特有服务也许就足够了,然后在迁移的时候找一个提供相似服务的厂商,或者做一些定制实现来替代这些服务。
构建能够响应不断变化的需求(包括改变部分基础设施的供应商)来改变基础设施的能力,比尝试构建一个在未来不会发生变化的基础设施(即使涌现出了未知的需求)要更为现实和强大。
容器化可能对降低云供应商锁定有帮助。应用程序打包从底层的服务器中抽出和应用相关的配置和文件,这样它们就能更容易地在新的托管环境中运行。但是重度容器化的基础设施需要工具和服务来管理和编排容器,所以走这条路的团队需要考虑如何在云平台之间移植这些工具和服务
最后一个避免锁定的潜在策略就是,使用在非私有平台上运行服务的厂商。换句话说,如果云平台是使用标准的虚拟化软件构建的,而其他竞争厂商也使用了这个软件,那它的迁移就可能比从私有平台上迁移要容易一些。
想法:2023-11-15 15:07:59
使用别人踩过坑的,即大多数人都用了的
2.6 与云和虚拟化的“机械通感”
于 IT 从业人员来说,越是深入、全面地理解系统技术栈底层的硬件如何工作,越能熟练地发挥其最大性能。
软件的历史就是在抽象之上再逐层抽象。操作系统、编程语言和虚拟化都曾通过简化计算机系统与人的交互而帮助人们变得更有效率。你不需要担心某个特定的变量保存在哪个 CPU 寄存器里,不需要考虑如何分配堆载以避免不同的对象互相覆盖,也不需要操心某个虚拟机运行在哪个硬件服务器上。
硬件仍然潜伏在抽象之下,理解 API 和虚拟 CPU 单元外表之下发生的事情很有用(见图 2-3)。它有助于你构建的系统优雅地处理硬件错误,避免隐藏的性能瓶颈,并且打通潜在的“通感”——使软件能够匹配底层的系统,从而工作得比那些草草写就的软件更可靠、更有效。
理解平台中的硬件服务器所使用的典型内存和 CPU 容量可以帮助你设计虚拟机的大小,从而获得虚拟机的最大性能。一些团队尽管不需要所有的容量,还是会通过选择 AWS 实
2.7 结语
例的大小来使他们独占整个硬件服务器的概率最大化。
理解存储选项和网络连接有助于确保磁盘读写不会成为瓶颈。这不是选择最快的可用存储这么简单的问题。选择性能最高的 SSD 本地磁盘对于可移植性、成本甚至资源的可用性都有影响。
软件和基础设施的架构、设计和实现需要基于对硬件、网络、存储以及动态基础设施平台实际架构的理解。
基础设施团队应该寻找并通读所有与其所使用平台有关的白皮书、文章、会议演讲和博客。从供应商那里引入专家来评审你们的系统——从高层的架构设计到具体的实现细节。一定要问你们的设计和实现如何在他们的硬件基础设施上工作。如果使用自己组织管理的虚拟化基础设施,更没有理由不协作。确保从全盘的角度来设计你的软件和基础架构,并且持续测量和修改,从而尽可能获得最好的性能和可靠性。
有了动态基础设施平台,下一步就是选择和实现一些工具,用来定义和管理平台提供的资源
第3章 基础设施定义工具
3.1 选择基础设施即代码的工具
上一章介绍了虚拟化和云平台,它们提供包括计算、网络和存储在内的动态基础设施资源。本章讨论团队可以用哪些工具按照基础设施即代码的原则管理这些资源。
像 CloudFormation、Terraform 或者 OpenStack Heat 之类的基础设施定义工具允许指定需要分配哪些基础设施资源以及如何配置它们。之后,这些工具就可以使用动态基础设施平台来实施不同的资源规格。当然,我们也可以简单地使用平台的用户界面来创建和管理资源。也有一些第三方工具提供了图形化的用户界面(GUI)互动地管理虚拟化和云基础设施。但要从基础设施即代码获益,就必须用可重复、可测试、可重用并且自文档化的方式管理基础设施。
前半部分指导如何选择和使用支持这种工作方式的工具
后半部分专门针对基础设施定义文件和工具,给出了定义基础设施资源的各种类型和方法的例子,并且关注如何使用配置注册表进行基础设施配置。
基础设施即代码将第 1 章描述的挑战、原则和实践融会贯通,实现了自动化
3.1.1 需求:脚本接口
3.1.2 需求:无人值守的命令行工具
下面的几个小节讨论了对基础设施即代码支持很好的工具有哪几点需求。这些需求对于所有的基础设施管理工具都适用,从基础设施自动化平台到本章描述的基础设施定义工具,以及本章后面描述的服务器配置工具和服务。
需求:脚本接口对于把 GUI 和基于网页的 UI 作为最重要交互方式的工具而言,把 API 和命令行工具当作首要接口的工具更容易写脚本。
有了命令行工具、可编程的 API 和开放源代码,团队就可以打开基础设施的引擎盖。这不仅对于改进、修理是必需的,对于集成不同的工具和服务亦是。
需求:无人值守的命令行工具命令行接口(CLI)工具应该很容易写脚本。这意味着工具的设计应该支持其在无人值守的 shell 或者批量脚本中运行。
• 它应该可以从其他工具或者脚本语言中接受输入,如标准输入、环境变量、命令行参数。• 输出的结果容易被其他工具和脚本语言使用。结构化输出而不是嵌在文本中的结果会很有帮助,因为这是可以解析的。• 手动在控制台窗口中输入命令(甚至密码)不是必需的。接受许可、提供证书应该可以用脚本的方式完成,要不然就对工具本身授权。
让人停下来去接受许可条款、提醒手动输入密码等交互式输入的工具都不是为自动化而设计的。工具应该接受调用参数或者配置项参数,这样不需要等待输入就能运行。
3.1.3 需求:支持无人值守的执行
需求:支持无人值守的执行
需要这种人工参与的脚本不能解放团队去关注其他事情。1 那些不需要人工介入就能可靠运行的任务是真正自动化基础设施的构建单元。能够被其他脚本和工具触发和运行的脚本就可以毫不费劲地进行自动化测试。它们也可以用作自动化伸缩和恢复例行程序的一部分。
支持可靠的无人值守的脚本和任务有一些特征。幂等的应该可以重复执行同一个脚本和任务且没有负面效应。事先检查应该验证任务的开始条件是否正确;如果不是,就要退出并给出可见、有用的错误信息,从而使事情处于可用的状态。事后检查应该检查任务是否已经成功应用了变更。这不只是检查命令的返回值,还要证实最终的结果。例如,检查虚拟主机已经添加了一个 Web 服务器可能涉及向这个 Web 服务器发起一个 HTTP 请求。
3.1.4 需求:外部化配置
看得见的错误当任务没有能够正确运行时,团队应该可以看到。这可能涉及信息辐射器和(或)集成到监控服务(详见 5.3.1 节)。参数化任务应该可以对相似类型的多次操作适用。例如,单个脚本应该可以用来配置多个虚拟服务器,即使有不同的特征也可以。脚本需要有办法发现特定虚拟主机的参数,以及为特定情况做配置的带条件的判断逻辑或模板。
实现这些需要基础设施团队的自律。要不遗余力地发现可以自动化的手动任务;要使用好的编程实践确保脚本是稳健的;要把难以自动化的任务剔除,即使这意味着用更支持无人值守自动化的部件替换基础设施的主要部分。
幂等一个工具要能够重复地无值守运行,它就必须是幂等的。这意味着不管运行多少次,其运行结果都应该是一样的。幂等的脚本和工具可以设为连续运行(例如有固定的时间间隔),这有助于防止配置漂移并提高对自动化的信心。
需求:外部化配置一些基础设施管理工具被设计成以“黑盒”的风格将配置数据保存在内部。访问和编辑配置的唯一方式是通过工具的界面。还有一种方式是将配置保存到外部文件中,可以通过常见的文本编辑工具来读取和编辑。黑盒配置模式的本意是为了简化管理。这类工具为用户提供了有用的界面,只展示有效的选项。但外部化配置模式更灵活,特别是在用作相似基础设施工具生态的一部分时。
服务器、环境、网络规则或者其他任何基础设施元素的外部化配置简化了重复工作。比如,它让这些事变得简单:• 一致地置备某类元素的许多实例;• 创建某个元素的正确测试实例;• 快速重建某个元素的遗失或损坏的实例。
对于工具内部管理的配置,团队使用它的能力受制于工具所支持的交互。另一方面,如果把配置外部化为文本文件,任何现成的工具都可以访问和操控它。你可以用任何喜欢的文本编辑工具编辑它们,可以用常见的命令行工具操控它们,也可以写自己的脚本管理它们。团队有能力使用对文本文件友好的工具的庞大生态之后,相比使用私有的工具,对基础设施配置有了更多的控制。
使用标准的版本控制系统外部化配置可以使用的最重要的现成工具就是版本控制系统(VCS)。它支持 1.5.3 节提到的好处:对变更的可追溯性,出问题时回滚的能力,基础设施不同部分变更的相关度,对团队中所有人的可见性,以及触发自动化测试和流水线的可执行性。
3.2 配置定义文件
VCS 扮演着基础设施即代码的中心角色。任何可以针对基础设施的操作都记录在脚本、配置文件和定义文件中并签入了版本控制系统。当有人需要做变更时,就可以从VCS 中签出文件,编辑文件以做变更,并提交新版本的文件到 VCS 中。
配置定义文件“配置定义文件”是个通用术语,表示特定自动化配置工具的文件,用来驱动基础设施自动化工具。大部分工具似乎都有自己的名字:playbook、cookbook、manifest、template,等等。配置定义可以是其中的任何一个,甚至是配置文件或脚本。
Bash、Perl、PowerShell、Ruby 和 Python 之类的通用目的脚本语言仍然是基础设施团队工具箱的重要组成部分。
可重用的配置定义
3.3 使用基础设施定义工具
可重用的配置定义在元素和环境间重用配置定义的能力是基础设施一致和流程可重复的关键。QA、预发布和生产环境所有者应该使用同一个定义文件,而不是使用不同的定义文件。任何合理的基础设施配置 DSL 都应有办法使用参数。
参数应该以一致、可重复的方式设置,而不是从命令行手动输入。当使用变更管理流水线时,流水线编排工具(比如 Jenkins 或者GoCD 这样的 CI 或 CD 服务器)可以用来为流水线的每个阶段设置参数。此外,参数也可以在配置注册服务中管理。
使用基础设施定义工具
这些工具用来定义、实施和更新 IT 基础设施架构,有时也被当作基础设施编排工具。基础设置的规格在配置定义文件。工具用这些定义去置备、修改或者移除基础设施的元素以匹配规格中的描述。它是通过集成动态基础设施平台的 API(如前续章节中描述的)来完成的。
3.3.1 用过程化脚本置备基础设施
具 有 相 同 原 理 的 基 础 设 施 定 义 工 具 包 括 AWS CloudFormation、HashiCorp Terraform、2。OpenStack Heat 和 Chef Provisioning许多团队使用过程化脚本来置备基础设施,特别是那些在更标准的工具出现之前就已经开始这么做的团队。这些工具可以是调用 CLI 工具的 shell 或者批量脚本,比如通过 AWS CLI 和 AWS 基础设施交互;也可以是使用通用语言编写的,其中使用了基础设施平台 API 的库;还可以是使用 Fog 库的 Ruby 脚本,使用 Boto 的 Python 脚本,或者使用 Go 的 AWS SDK 或 Google Cloud 库的 Golang 脚本。
“置备”的定义“置备”这个术语可以用来表示不同的事情。本书中提到的置备表示使服务器、网络设备之类的基础设施元素可用。根据置备对象的不同,可能涉及:• 为元素指派资源;• 实例化元素;• 在元素上安装软件;• 配置元素;• 将元素注册到基础设施服务中。在置备流程的最后,这个元素就完全可用了。置备有时指这个流程中更小的一部分。例如,Terraform 和 Vagrant 都将之定义为对 Chef 和 Puppet 等服务器配置工具的调用,以便在服务器创建之后进行配置。
用过程化脚本置备基础设施在一个团队中,我们可以用 Ruby 实现的命令行工具把 Rackspace Cloud 上的服务器置备过程标准化。我们把这个工具称为 spin,取自“启动(spin up)一个服务器”。这个脚本会接受几个命令行调用参数,这样就能在不同的环境中创建不同类型的服务器了
3.3.2 声明式定义基础设施
最后,我们将关于服务器类型和环境的信息移到配置文件中,分别叫作 servers.yml 和environments.yml。这意味着我们不需要经常修改脚本文件本身,只要确认它安装在需要运行它的工作站和服务器上即可。我们的关注点成了将正确的东西纳入配置文件,然后将它们当作制品进行跟踪、测试和推进。有趣的是,通过修改脚本以使用像 servers.yml 和 environment.yml 这样的配置文件,我们走向了声明式定义。
声明式定义基础设施将定义分开放到单独的文件中促使我们不再按照程式化的方式看待系统创建,例如“先做 X,然后做 Y”。反之,定义文件可以是声明式的,例如“应该是 Z”。对于需要理解某事应该如何完成的任务,程式化语言很有用。但是在更需要理解需要什么的时候,声明式定义非常有用。如何做的逻辑就变成了读取并应用定义文件的工具要肩负的责任。
声明式定义非常适用于基础设施配置。你可以指定希望事情是怎样的,例如应该安装的软件包,应该定义的用户账号,应该存在的文件。工具会让系统匹配你指定的规格。你不需要担心系统在工具运行之前的状态。文件可能不存在;也可能存在,但是属主或权限不同。工具包括了所有的逻辑,可以弄明白需要做哪些变更、不需要做哪些变更。
3.3.3 使用基础设施定义工具
3.3.4 配置服务器
使用基础设施定义工具大部分基础设施定义工具用命令行工具来使配置定义生效。
虽然基础设施团队成员可以从本地工作站或者笔记本上运行工具,但是最好以无人值守的方式运行
配置服务器基础设施定义工具会创建服务器,但不对服务器上有什么负责。因此,定义服务工具声明有两个 Web 服务器,但是并没有在上面安装Web 服务器软件或者配置文件。
创建服务器时,基础设施定义工具通常需要向一个服务器配置工具传递配置参数。例如,它可能指定了服务器的角色,这样配置工具就会安装相关的软件和配置。它可能传递如DNS 服务器地址这样的网络配置细节。
3.4 配置注册表
3.4.1 轻量级配置注册表
配置注册表配置注册表是基础设施元素中信息的目录。对于需要管理和集成基础设施的脚本、工具、应用服务来说,它提供了一种发现这些信息的方式。这对于动态基础设施来说特别有用,因为随着元素的添加和删除,这些信息持续地变化着。
实现配置注册表的方式有很多种。对于简单些的基础设施,定义工具使用的配置定义文件也许就足够了。当工具运行时,它所需的所有信息都在配置定义中。然而,这种方式不能很好地扩展。随着定义文件中管理的对象数目增多,一次性应用所有这些可能会成为变更的瓶颈。
有很多配置注册表产品,例如 Zookeeper、Consul 和 etcd。许多服务器配置工具供应商提供自己的配置注册表,例如 Chef Server、PuppetDB 和 Ansible Tower。这些服务器被设计成更容易和配置工具集成,其中还包括仪表盘之类的其他元素。为了能在动态基础设施上工作,配置注册表服务必须支持从注册表中以编程的方式添加、更新和删除条目。
轻量级配置注册表和使用一个配置注册表服务器不同,许多团队使用文件实现轻量级的配置注册表,这些文件存储在集中、共享的位置,如 AWS S3Bucket 或者 VCS 之类的对象存储中。使用开箱即用的静态网络托管工具就可以访问这些文件。
一种替代方法就是把这些配置打包到系统包中,比如 .deb 或 .rpm 文件,然后再将它们推送到内置的 APT 或者 YUM 仓库中。这样就可以使用普通的打包管理工具来将这些设置拉取到本地服务器中。这些实现配置注册表的轻量级方式利用了成熟、开箱即用的工具,比如 Web 服务器和打包管理仓库
陷阱:和配置注册表的紧耦合重度使用的注册表可能变成紧耦合或者脆弱性的来源。脚本和服务依赖注册表中的条目可能不清楚。改变条目的格式或者删除一个看起来不再需要的条目可能会导致不可预期的灾难。这就导致大家不愿意改变注册表,直到它变成了脆弱、过度复杂的“一团乱麻”。
3.4.2 配置注册表是CMDB吗
配置注册表是CMDB吗配置管理数据库(CMDB)是在自动、动态基础设施之前就存在的概念。CMDB 是 IT 资产及其之间关系的数据库,这些资产被称作配置项(configuration item,CI)。CMDB 和配置注册表很有多相似的地方:都是罗列基础设施中对象的数据库。
但是 CMDB 和配置注册表是用来解决两个不同核心问题的
配置注册表设计为允许自动化工具共享有关基础设施中对象的数据,这样它们就可以基于不同对象的状态动态修改其配置。它需要有可编程的 API,这样基础设施团队应该使用 API 来确保注册表总是准确地代表了基础设施的状态。
建立 CMDB 最初是为了跟踪 IT 资产。你拥有的硬件、设备和软件许可证有哪些?它们用在哪里?它们用来做什么?很久以前,我用电子表格构建了一个 CMDB,后来移到了微软的 Access 数据库。我们手动管理其中的数据。这对于石器时代来说还不错,那时什么东西都是用手构建的,事物变化也不是很快。
这就是配置注册表和 CMDB 起源的两个不同方向:一个是为支持自动化而共享数据,另一个是记录资产信息。
3.4.3 CMDB的审计与修复反模式
3.4.4 CMDB的基础设施即代码方式
3.5 结语
下面是一些在管理基础设施即代码时处理 CMDB 问题的指南。• 确保一切的构建都是自动化的,这样就能正确和准确地记录它们。• 如果需要跟踪资产,考虑使用一个单独的数据库,让自动化过程更新它。应该使其保持简单。• 自动化过程应该在配置注册表中准确地记录和报告所使用的商用软件许可证。流程应该报告许可证使用情况。如果有不合规的使用或者太多未使用的许可证,这个流程应该告警。• 扫描发现并报告哪些不是通过自动化过程创建和配置的对象。如果不属于该基础设施就将其移除,否则将其加到自动化过程中然后重新正确地构建一遍。
第4章 服务器配置工具
4.1 自动化服务器管理的目标
使用脚本自动化地创建、置备以及更新服务器并不新鲜,但过去 10 年间已经出现了新一代的工具。CFEngine、Puppet、Chef、Ansible 等是这类工具的代表。虚拟化和云推动了这些工具的流行,因为使用这些工具可以更容易创建大量新的服务器并随后配置和更新这些服务器。Docker 这样的容器化工具最近也出现了,用于打包、分发以及运行应用程序和进程。容器将操作系统元素和应用程序绑定在一起,影响了置备和更新服务器的方式。
本章讲述如何设计服务器自动化工具以遵从实现基础设施即代码的准则,其中包括工具可以采用的不同方式,以及团队针对自身的基础设施可以使用的不同方式。
4.2 具有不同的服务器管理功能的工具
4.2.1 创建服务器的工具
• 能够完全按需置备 1 一台新服务器,等待时间不超过数分钟。• 置备新服务器时完全不用人工参与,比如不需要人工响应事件。• 当定义了服务器配置变更之后,向服务器应用该变更的过程不需要人工参与。• 每个变更都应该被应用到所有相关的服务器,而且在该变更之后置备的新服务器都应该包含该变更。• 置备以及变更服务器的过程具有可重复性、一致性、自文档和透明化等特性。• 修改置备服务器以及变更配置的流程既容易又安全。• 每次修改服务器配置定义以及修改置备服务器和更改服务器的流程都会触发运行自动化测试。• 配置的变更和处理基础设施任务的流程变更都应版本化,并且要应用到不同的环境中,以便支持对照性测试和阶段性发布策略。
本节会探索该生命周期中使用到的相关工具。这些工具有多个功能,其中一些会应用到多个生命周期阶段。本节讨论的功能有创建服务器、配置服务器、打包模板以及在服务器上运行命令。
创建服务器的工具前一章已经描述过,新服务器是使用基础设施定义工具通过动态基础设施平台创建出来的。服务器的创建基于一个服务器模板,而该模板是某种基础镜像。该镜像格式可以是基础设施平台特有的 VM 镜像格式(比如 AWS AMI 镜像或者 VMware VM 模板),也可以是供应商提供的操作系统安装盘镜像(比如 Red Hat 安装 DVD 的 ISO 镜像)。大多数基础设施平台支持通过用户界面交互式创建服务器,如图 4-2 所示。但是所有重要的服务器都应该能被自动化地创建。
4.2.2 配置服务器的工具
创建新服务器的使用案例有很多。• 基础设施团队的成员需要构建一个标准类型的新服务器,例如向集群中加入一台新的文件服务器。他们修改基础设施定义文件来指定该新服务器。• 一个用户想要启动某标准应用程序的新实例,例如缺陷追踪应用程序。用户可以使用自服务门户,该门户会创建一台应用程序服务器,并安装缺陷追踪软件。• 由于硬件问题导致某 Web 服务器 VM 崩溃。监控服务检测到这一事件并触发创建一台新的VM 来替代它。• 用户业务的增长超过了现有应用程序服务器集群的承受能力,所以基础设施平台的弹性伸缩功能会创建新的应用程序服务器并加入到集群中来满足需要。• 开发人员提交了对应用软件的一个修改。CI 软件(比如 Jenkins 或 GoCD)自动在测试环境置备一台应用程序服务器,并且安装最新构建出来的软件,然后自动化测试集可以针对该环境运行自动化测试。
配置服务器的工具Ansible、CFEngine、Chef、Puppet 和 SaltStack 都是专门设计用来通过基础设施即代码的方式配置服务器的工具。它们使用外置的配置定义文件,在其中使用设计好的 DSL 来配置服务器。这些工具从文件中读取定义并将相应的配置应用到服务器上。
多服务器配置工具需要在每台服务器上安装代理软件。该代理软件周期性运行,从中央仓库拉取最新的定义并应用到该服务器。这是设计 Chef 和 Puppet 时的默认使用方式。2其他工具使用推送模式,即中央服务器触发对被管理的服务器进行更新。Ansible 默认使用该模式,它使用 SSH 密钥连接到服务器并运行命令。3 这种方式的好处是不需要被管理的
4.2.3 打包服务器模板的工具
服务器安装和配置代理软件,但缺点是牺牲了安全性
自动化服务器配置模型的安全权衡中央系统用于控制服务器的配置,这会给一些不法分子带来可乘之机。基于推送的配置模型会要求在服务器上开放端口,而攻击者则极可能会连接该端口。攻击者可能会扮演配置管理者并向目标服务器推送配置定义,而该配置定义将导致服务器被恶意使用。这甚至会允许攻击者执行任意命令。密钥通常可用于阻止攻击,但是需要稳健的密钥管理手段。拉取模式简化了安全问题,但仍有机会遭受攻击。这种情况下的攻击点是客户拉取配置定义的中央仓库。如果攻击者可以危害存放配置定义的仓库,那么他们会获取被管理的服务器的完全控制权。
按理说,选择一个供应商提供工具的一体化生态系统可以简化基础设施团队的工作。然而,如果生态系统中的元素可以被不同的工具替换,那么团队就可以选择最好的工具来满足他们的要求。
打包服务器模板的工具大多数情况下,可以使用现成的服务器模板镜像来构建新服务器。比如 IaaS 云之类的基础设施平台经常提供通用操作系统的模板镜像。很多平台也提供由供应商和第三方构建的模板库。这些模板是为特殊目的而预安装和配置的镜像,比如应用程序服务器。但很多基础设施团队发现构建自己的服务器模板更有用。他们可以使用团队喜欢的工具、软件和配置来预配置服务器模板。
一个关键的权衡点是,如果越来越多的元素被打包到了服务器模板中,那么需要经常更新模板。这要求更加复杂的流程和工具来构建和管理模板。
4.2.4 在服务器上运行命令的工具
在服务器上运行命令的工具能横跨多个机器远程运行命令的工具可以帮助团队管理多台服务器。诸如 MCollective、Fabric 和 Capistrano 等远程命令执行工具可以用于临时任务(比如调查和修复问题),也可以用于编写脚本执行日常任务
一些人称这种工具为 SSH-in-a-loop(循环使用 SSH)。因为它们大部分都使用 SSH 连接到目标机器,所以这种说法并不完全错误。但这些工具也拥有更加先进的功能,可以更容易地编写脚本,更容易地定义一组服务器并在上面运行命令,或更容易地与其他工具集成。尽管跨服务器运行一些临时命令很有用,但应该只在特殊情况下这样做。手动运行远程命令工具来更新服务器是不可重复的,所以对于基础设施即代码来说不是个好实践。
如果经常使用交互式工具执行日常任务,就应该考虑将这些任务自动化。理想情况是将其放入配置定义中。对于仍需要人工参与的任务,可以使用团队喜欢的远程命令工具提供的语言来脚本化。
使用工具提供的脚本语言存在危险:这些脚本会随着时间发展越来越复杂。这些工具的脚本语言只适合小型脚本,缺乏以整洁的方式管理较大代码库所需的功能,比如创建可重用、可共享的模块。服务器配置工具专门被设计为支持大型的代码库,所以更加适用。
4.2.5 从中央注册中心获取配置
无须多说,团队开发的所有脚本、工具、实用程序和库都应该由版本控制系统来管理。
从中央注册中心获取配置第 3 章描述了使用配置注册表来管理基础设施中不同元素的信息。服务器配置定义能够从配置注册表中读取值,从而设置参数(详见3.2 节)。
4.3 服务器变更管理模型
4.3.1 临时变更管理
4.3.2 配置同步
4.3.3 不可变的基础设施
4.3 服务器变更管理模型动态基础设施和容器化引导人们实验不同的方式来实现服务器变更管理。有数种模型可以管理对服务器的变更,一些比较传统,一些很新甚至颇有争议
临时变更管理临时变更管理指的是当仅有特定的更新需要执行时才对服务器发起变更。在自动化服务器配置工具成为主流之前,临时变更管理是管理服务器的传统方式。它的弱点在于会导致配置漂移、雪花配置,以及第 1 章描述的所有缺点。
配置同步配置同步指的是重复地将配置定义应用到服务器。例如,每小时运行一次 Puppet 或者 Chef 代理软件。这保证通过定义使系统任何部分的变更都保持一致。配置同步是基础设施即代码的主流方式,大多数服务器配置工具都采用了这样的设计思路。这种方式的主要限制在于服务器的很多部分都处于未管理状态,极易遭遇配置漂移问题。
不可变的基础设施不可变的基础设施指的是通过完全替换服务器的方式来实现配置变更。通过构建新的服务器模板来应用变更,然后使用该服务器模板重新构建相关的服务器。这增加了可预测性,因为产品环境和测试环境中的服务器只有细微差别。这对服务器模板管理具有很高的要求。
4.3.4 容器化服务
4.4 容器
容器化服务容器化服务指的是将应用程序和服务打包到轻量级的容器中(Docker 普及了这项服务)。这降低了服务器配置和运行在服务器上的应用之间的耦合。所以主机服务器会非常简单,变化频率很低。虽然这些主机仍然需要某种变更管理模型,但该模型更加易于实现、易于维护。
理整个虚拟机和服务器简单得多。
4.4 容器诸如 Docker、Rocket、Warden 以及 Windows 容器等容器化系统已经成为在服务器上安装和运行应用程序的可选方式。容器系统用于定义和打包进程的运行时环境到容器镜像中。然后可以分发、创建和运行该镜像的实例。容器使用操作系统的特性来隔离容器的进程、网络以及文件系统,所以成为了一个自主、齐全的服务器环境。
容器化系统的价值在于,它为容器镜像和工具提供了一种标准格式来构建、分发和运行这些镜像。
容器化的好处如下:• 将具体应用程序的运行时需求与容器运行的主机服务器解耦;• 通过容器镜像可以重复创建一致的运行时环境,而该容器镜像可以被分发和运行在任何支持该运行时的主机服务器上;• 将容器定义为可以被 VCS 管理的代码(比如在 Dockerfile 中),从而用来触发自动化测试,并通常拥有基础设施即代码的所有特性。
至 2016 年初还存在其他的一些容器实现,包括:• CoreOS rkt;• Pivotal 创建的 CloudFoundry Warden;• Odin 创建的 Virtuozzo OpenVZ;• 谷歌的 lmctfy,其开发已经终止,目前合入 libcontainer,成为了 Docker 的组件 6;• VMware 的 Bonneville。
从主机系统解耦运行时需求对于基础设施管理来说好处特别大。它清晰地实现了基础设施和应用程序之间的关注点分离
4.4.1 以容器方式和非容器方式管理Ruby应用程序
4.4.2 容器是虚拟机吗
容器是虚拟机吗容器有时被描述为一种虚拟机。它们有共同点,都是在单个主机服务器上运行多个进程,而这些进程都认为自己运行于自己独立的服务器上。不过容器和虚拟机有显著的技术不同点。容器的使用场景和虚拟机有很大区别。
虚拟机和容器之间的不同点
主机服务器使用 hypervisor(虚拟机管理程序,比如 VMware ESX 或 Xen,后者是亚马逊 EC2 服务的基础)来运行虚拟机。hypervisor 往往作为操作系统安装在硬件主机服务器的裸机上。然而,一些虚拟化包可以安装在另一个操作系统之上,特别是 VMware Workstation 和 VirtualBox,都能作为桌面应用程序来运行。
从这个意义上来说,容器不是虚拟机。容器没有模拟硬件,与主机服务器使用同一个操作系统,而且实际运行在同一个内核上。容器系统使用操作系统特性来隔离进程、文件系统和网络,运行在容器中的进程就像运行在独立的系统中。这靠的是严格限定该进程的访问权,而不是模拟硬件资源。
4.4.3 使用容器而不是虚拟机
使用容器的一个幼稚方式是采用和构建虚拟机镜像相同的方式来构建容器。将多个进程、服务和代理软件打包到单个容器中,然后采用和运行虚拟机一样的方式来运行该容器。这样做完全没有利用容器的优势。使用容器的最佳方式是将它作为一种打包服务、应用程序或者任务的方法。它是一种快速建造的方式,将应用程序加入它的依赖当中,并提供一种标准方式让其主机系统管理自身的运行时环境。与其单个容器运行多个进程,不如同时运行多个容器,而每个容器只运行一个进程。这些进程会变成独立、松耦合的实体。这使得容器非常适合微服务应用程序架构
使用这种方式建立的容器在启动时会非常快。这对于长期运行的服务进程很有用,因为能更加容易地周期性部署、重新部署、迁移和升级这些服务。不过快速启动也让容器更适合将进程作为任务来运行
4.4.4 运行容器
4.4.5 安全和容器
高效管理基础设施资源的下一代革命就是容器化。虚拟化是革命的前奏,可以通过添加或移除虚拟机在数分钟内改变负载能力。容器则更进一步,可以在数秒内改变负载能力。9
运行容器将单个应用程序打包和运行在容器中非常简单。使用容器作为常规手段跨多个主机服务器来运行应用程序、服务和任务则稍微复杂一些。容器编排系统能够跨主机系统自动化地分发和运行容器
容器完全有潜力在基础设施层以及运行在基础设施之上的服务和应用程序间建立清晰的隔离。运行容器的主机服务器可以保持非常简单,使用容器化不需要为具体的应用程序需求做定制,也不需要对应用程序施加约束,并且可以提供日志和监控等支撑服务。运行容器的基础设施由通用的容器主机组成。可以将主机拆得非常小,仅包含运行容器的最小化工具集合,以及一些用于监控和管理任务的代理软件。这会简化主机的管理工作,因为它们不经常变化,而且包含的东西很难破坏,很少需要更新。这也减小了安全暴露面。
4.5 结语
第5章 基础服务概述
5.1 基础设施服务和工具的考虑
前面的章节介绍了一些工具,用于提供、置备以及配置核心基础设施资源:计算、网络和存储。这些工具为基础设施即服务提供了基本的构建单元(building block)。但是,大多数基础设施需要各种其他的辅助性服务和工具。
有一些服务和工具,例如 DNS 和监控,对于基础设施的正常运行是必需的。其他的服务和工具,例如消息队列和数据库,可能只对一部分应用程序是必需的。
本章的目标不在于列举或者解释这些服务和工具,而是介绍在通过代码对动态基础设施进行管理的上下文里面,这些服务和工具应该如何工作。这是本章第一节的主题。接下来,本章会使用 4 个核心服务来说明这些考虑因素,因为这些服务对于动态基础设施尤为重要。这 4 个服务和工具分别是监控、服务发现、分布式进程管理和软件部署。
5.1 基础设施服务和工具的考虑对于基础设施管理所涉及的任何服务和系统而言,其目标与前面章节介绍的基础设施平台、定义工具以及服务器配置工具的目标是一致的。
对于这些服务,基础设施即代码的原则可以概括为:• 服务可以很容易地重新构建或复制;• 服务的元素是用完可扔的;• 服务所管理的基础设施元素是用完可扔的;• 服务所管理的基础设施元素经常会发生变更;• 服务实例的配置是一致的;
5.1.1 支持外部配置的工具优先
• 管理和使用服务的流程是可重复的;• 服务可以迅速且轻松地满足常规需求,最好是自服务或者自动完成;• 服务可以轻松且安全地进行复杂的变更。
一些具体的实践包括:• 使用外部定义文件;• 自文档化的系统和流程;• 一切版本化;• 持续测试系统和流程;• 小的变更,而不是批量变更;• 让服务持续可用。
遗留基础设施管理软件产品的问题包括:• 无法自动处理新增或删除的基础设施元素;• 假定产品会被安装在静态服务器上;• 需要手动配置,通常需要通过 UI 操作;• 在产品的不同实例之间,很难对配置进行复制和变更;• 很难对配置做自动化测试。
接下来是选择基础设施服务产品的标准。它们与之前章节介绍的标准是一脉相承的。
支持外部配置的工具优先
5.1.2 假定基础设施是动态的工具优先
5.1.3 具有云兼容许可的产品优先
假定基础设施是动态的工具优先
想法:2023-11-15 16:23:24
动态,与静态、不能动相反
下面是一些对动态基础设施工具进行评估的有效标准:• 能够优雅地处理新增或删除的基础设施元素,包括整体环境;• 支持跨设备聚合和查看历史数据,包括已经被不同设备删除或替换的数据;• 能够自动基于事件进行变更,不需要人工介入;• 自动展示当前状态和配置的信息。
具有云兼容许可的产品优先
5.1.4 支持松耦合的产品优先
5.2 团队之间共享服务
支持松耦合的产品优先
重要的是确保可以对基础设施的任何部分进行变更,而不需要对其他部分进行广泛的变更。系统各部分之间的耦合增加了变更的范围和风险,从而导致变更的频率降低,更让人恐惧。产品自身的耦合度可能与组织如何设计和实现他们的基础设施与管理服务相关。遵循强大的设计原则,避免产品的实现使基础设施团队互相干扰。在不影响其他团队的情况下,团队应该可以对自己的基础设施进行变更。保持高度的警惕性和良好的设计,防止紧耦合成为一个问题。
5.2 团队之间共享服务
服务实例模板
5.3 监控:告警、指标和日志
服务实例模板对于无法在团队之间清晰隔离的服务,每个团队最好都拥有一个专门的实例。然后,团队可以根据自己的需求调整实例的配置,而不影响其他团队。数据、凭证以及访问控制都可以更有效地隔离。
但是,运行相同服务的多个实例会给某些需要保持一致性的东西带来配置漂移的风险
在决定是否共享服务实例或者支持多实例的时候,要考虑以下问题。• 团队需要的定制化是否会影响使用该服务实例的其他团队?如果是,多服务实例可能是最佳选择。• 团队对服务的使用是否会影响其他团队的绩效?如果是,多服务实例可以避免此类问题。• 服务是否需要运行每个团队提供的代码?服务是否有效地隔离了代码的运行环境?(请牢记,容器甚至虚拟机都无法提供进程之间 100% 的隔离!)• 服务是否会保留一些不应该对所有用户都可见的数据或凭证?保护这些数据的控制机制有多强?• 团队之间是否存在共享数据或内容的强烈需要?如果是,共享实例可能是一个更好的选择。
5.3 监控:告警、指标和日志
监控的目标在于在需要的时间让需要的人看到正确的信息。这些信息可能来自于系统的各个部分,从核心基础设施、服务、应用程序到业务的指标。
5.3.1 告警:出现问题时告诉我
监控信息有两种类型:状态和事件。状态与当前的情况相关,而事件记录了操作或变更
5.3.1 告警:出现问题时告诉我
反脆弱、自修复基础设施的秘诀在于人。告警让人们知道何时需要注意,以阻止故障的发生,或从故障中恢复。最终用户服务才是真正重要的,所以必须从用户的角度检查所有环节是否正确。主动式检查可以登录到服务,并运行关键的事务或用户旅程(user journey)。这些证明了端到端的系统都在正常工作,并给用户返回了正确的结果。
团队应该思考系统之中不同类型的状态和事件,并且针对每一个状态和事件确定所需的措施。
什么是信息辐射器信息辐射器(information radiator)又称公共仪表盘(communal dashboard),是一种高度可视化的信息展示方式。它被置于团队公共空间,所有人都能很容易地看到关键状态信息。敏捷软件开发团队使用这些工具展示持续集成和持续交付流水线的构建状态。运维团队使用它展示服务的状态。跨职能产品团队则展示两者以及关键业务指标。
只有以简洁的方式展示可以指导行动的信息时,信息辐射器才不会被忽略。一个有效的经验法则是,辐射器应该让人们可以立即明白该采取如下行动中的哪个:(a) 继续手头的工作;(b) 高声呐喊,停止手头的工作并且采取行动。展示内存使用量和 CPU 利用率的细线图并不能引起任何人的注意。仪表盘在数据库将要耗尽内存的时候显示巨大的红色色块,可以很有效地吸引注意。与告警一样,长期显示红色的信息辐射器也毫无价值。如果辐射器上显示的指标没有重要到需要立刻修复,那就把它删掉。
想法:2023-11-15 16:36:20
所以说,很多东西不能乱用,不然造成信息干扰,得不偿失
5.3.2 指标:收集和分析数据
5.3.3 日志聚合和分析
5.3.2 指标:收集和分析数据
监控的另一个方面是收集数据库中的数据。这些数据可以交互式地进行分析,并且自动包含在仪表盘、定时报表和信息辐射器中。
5.3.3 日志聚合和分析
当服务器出现故障或者被自动销毁时,保存在虚拟机文件系统中的日志文件就会丢失。对于这一问题,集中式日志聚合是一种流行的解决方案。把服务器和设备配置成将日志发送到向中央存储服务(例如 syslog 服务器或者Logstash)。可以添加类似于 Elasticsearch 和Kibana 的工具,使人们更易于搜索聚合的日志,基于日志中的活动构建仪表盘,以及在出现问题时发送告警。
5.4 发现服务
5.4 发现服务
5.4.1 服务器端的服务发现模式
5.4.2 客户端的服务发现模式
5.5 分布式进程管理
5.5.1 使用服务器角色编排进程
5.5.2 使用容器编排进程
服务器端的服务发现模式让每个服务都拥有一个负载均衡器(或者负载均衡虚拟 IP),它将客户端的请求定向一组运行着相关服务的服务器池。在服务器被置备、销毁或者失败的时候,负载均衡器将自动更新。
客户端的服务发现模式 3 是指,提供服务的服务器列表保存在服务注册表中。客户端先从服务注册表查找这些服务器地址,然后决定向哪台服务器发送请求。
5.5 分布式进程管理
使用服务器角色编排进程管理进程的方法之一是服务器角色(server role)。例如,角色为 web server 的服务器上运行了 Web 服务器进程。当你需要水平扩展容量的时候,可以启动多台该角色的服务器。当需求下降的时候,可以通过销毁该角色的服务器来缩减。将 Web 服务器运行在多个数据中心里可以提供业务连续性。这种服务器进程的编排方法直截了当,而且天然适合于动态基础设施平台。然而,这种方法可能有点重。启动一台完整的服务器,即便是虚拟机,也可能花费很长的时间来让服务就绪,虽然这些服务可能只是需要快速执行或者满足短暂的需求爆发。
使用容器编排进程容器化为管理服务器进程提供了一个截然不同的模型。进程被打包,可以运行在不是专门为此构建的服务器上面。一个通用容器宿主机池可以用来运行大量迥异的容器化进程或任务。将容器化的进程部署在宿主机上是非常灵活和快速的。容器宿主机的数量可以基于不同类型服务的整体需求自动调整。然而,这种方式依赖于调度器来启动和管理容器实例。
5.5.3 调度短期任务
5.5.4 容器编排工具
5.6 软件部署
5.6.1 部署流水线软件
调度短期任务很多服务和基础设施管理工作都涉及按需或是定期地运行短期任务。有些服务自己拥有管理这些任务的能力。例如,持续集成服务器可以把任务分发给一组运行代理进程的服务器。其他服务则依赖于类似 Cron 的操作系统调度程序。然而,Cron 并不是为分布式任务设计的。有些容器编排工具恰恰提供了这一项特性。
器编排工具随着类似于 Docker 的容器化系统流行起来,容器编排工具也走到了台前。大部分容器编排工具都需要在容器宿主机池上运行代理,能够自动选择宿主机来运行新的容器实例、替换失败的实例以及伸缩容器实例的数量。有些工具还可以处理服务发现、网络路由、存储、调度任务等。
5.6 软件部署
在最坏的情况下,这些软件部署流程太过复杂,以至于无法自动化。以下是该问题的一些原因。• 软件从一开始就是手动部署的。随着时间的推移,系统变得庞大,却一直没有使用自动化。在系统没有进行显著的重构甚至架构改造之前,重新引入自动化是极其困难的。• 软件不同版本的安装过程涉及不同的事情,可以称之为“雪花发布”。要求面面俱到的发布文档是“雪花发布”的症状之一。• 发布的频率不高。这鼓励了人们将每次发布视为特殊的偶发性活动,而非常规性事件。• 环境不一致,所以将软件部署到每个节点都需要定制的工作。部署到环境需要专门了解如何调整软件、软件配置以及环境的配置,使所有的东西完全匹配。这是“雪花发布”的一种变体。
5.6.1 部署流水线软件
5.6.2 打包软件
持续交付(CD)软件对于软件和基础设施配置制品在这一系列环境之中的流转过程进行编排。针对给定制品的一系列流转过程被称为流水线(pipeline),流水线的每个阶段被称为步骤(stage)。对于每个步骤,CD 工具会触发软件的部署,或者推送配置信息到指定的环境中使之生效。然后,它可能会触发自动化测试,如果测试失败就将整个流水线标记为失败
5.6.2 打包软件
将内部软件部署到服务器上的最理想方式是使用与安装其他软件相同的流程和工具。将软件打包成服务器原生的包格式(.rpm 文件、.deb 文件、Nuget 包等),从而简化软件的部署。这些格式支持安装前(pre-installation)与安装后(post-installation)的自动化脚本和版本管理,而且可以使用类似于 APT 和 YUM 的仓库系统进行分发。
5.7 结语
部署微服务微服务架构 4 在更大、更复杂的环境中特别适合于安全、简单和可靠的软件部署。微服务的思想是将应用程序的功能分解为独立可部署的服务,这些服务通过网络互相进行通信。如果功能能够清晰地隔离开,接口也能清晰地定义出来,这能有效地改善复用度和共享度。单个微服务应该很小、易于部署。如果它们的实现是松耦合的,那么可以在不影响依赖于它的其他服务的情况下对单个微服务的变更进行部署。然而,微服务应用程序架构需要精细的基础设施管理 5。使用微服务的组织会衍生出非常多的可部署服务 6,这些服务都会被频繁地构建和部署。亚马逊电子商务网站的实现包括超过 200 个微服务。它们通常每天都会部署数十次或数百次到生产环境。即便是规模在 10 个左右微服务的中小型组织,也很难在静态、雪花型的基础设施之上进行维护和部署。微服务架构不仅仅需要具有严格一致配置的动态环境,还需要能够轻松安全地对服务器进行变更和改进。
第二部分 模式
第6章 置备服务器的模式
基础设施不仅仅是服务器,还包括创建、配置和修改服务器,这些通常会占用大多数的时间和精力。因此,第二部分主要关注置备和更新服务器。然而这里介绍的很多服务器相关模式和方法对于其他的基础设施元素,如网络设备和存储,同样有效,而且经常可以简化。
有效的基于基础设施即代码的置备过程具有下列特征:• 可以按照需要,毫不费力地重建任何已经存在的基础设施元素;• 新元素可以只定义一次,然后发布、复制到多个实例和环境中;• 任何元素的定义和置备过程都是透明且易于修改的。
6.1 服务器置备
6.1.1 服务器的生命周期
典型的服务器置备任务包含了分配硬件、创建服务器实例、磁盘分区、加载操作系统、安装软件、配置服务器组件、设置网络以及为服务器注册使其完全可用的必备服务(如 DNS)
服务器置备可以在服务器生命周期的不同时间点来完成
置备不仅仅针对新的服务器。有时候已经存在的服务器需要重新置备,从而切换角色。有时候一个大的服务器可能用于多个角色,偶尔需要添加一个新的角色。
6.1.1 服务器的生命周期
- 打包服务器模板
这个服务器镜像已经置备了常见的元素,可以用来创建多个服务器。一些基础设施管理平台直接支持模板,比如亚马逊的 AMI以及 VMware 的模板。如 Rackspace Cloud 的其他平台并没有显式的服务器模板,但创建快照(snapshot)做备份的功能也可以很容易地用作模板。
- 创建新服务器
创建一个新的服务器包括分配资源,如 CPU、内存以及磁盘空间,然后实例化虚拟机或硬件服务器。这个阶段通常涉及配置网络,包括分配一个 IP 地址,并把该服务器放在网络体系结构中,例如将它添加到一个子网。服务器也可以添加到基础设施编排服务中,比如DNS、配置注册中心或者监控
- 更新服务器
好的服务器创建过程会确保新服务器在创建时是一致的,但是这种一致性并不长久。服务器生命周期中的修改会导致分化。服务器模板的内容以及在服务器创建时发生的活动往往被基础设施团队不断更新和改进,这意味着不同时期创建的服务器很可能是不同的。
- 更换服务器
有些修改可能需要完全替换服务器,而不是简单地更新现存的服务器。
无缝地更换服务器是连续性战略的一个关键,它确保基础设施的重大修改无须中断服务或丢失数据。零停机更换部署确保现存的服务器仍然在运行时,就完整地构建和测试一个新服务器,这样一旦准备好就可以进行服务的热交换。
- 删除服务器
销毁一个服务器看似简单,但是基础设施服务需要更新以对应地移除它。数据可能也需要保留。确保服务器删除的相关信息在删除后仍然能保留是有用的。对于调试问题和跟踪趋势而言,留住被删除服务器的历史指标和日志数据非常重要。
- 服务器生命周期的其他事件
从失败中恢复
调整服务器池大小
6.1.2 服务器都承载了什么
6.1.3 服务器上东西的类型
重新配置硬件资源很多虚拟化和云平台都能修改运行服务器实例的硬件资源。
6.1.4 服务器角色
.1.4 服务器角色
在服务器角色的很多模型中,一个特定的服务器可以有不同的角色。
一种模式是定义细粒度的角色,并将它们组合在一起形成特定的服务器。
另一种模式是角色的继承层次。基础角色包含了所有服务器通用的软件和配置,比如监控代理、通用用户账户以及通用配置,如 DNS 和 NTP 服务器设置。其他角色可能在不同的继承层次上添加更多的东西。
6.2 创建服务器的模式
6.2.1 反模式:手动制作服务器
启动一个新服务器实例的来源可能有:• 克隆现有的服务器;• 实例化运行中的服务器先前保存的快照;• 从诸如 EC2 AMI 这样特意准备好的服务器模板进行构建;• 从 OS 提供商的 OS 安装镜像(如 ISO 文件)直接引导。
6.2.2 实践:将服务器创建参数放在脚本中
手动构建服务器几乎会立即导致配置漂移和雪花服务器。服务器的创建过程不可跟踪,没有版本管理,无法测试,也肯定不是自文档化的。
脚本是记录新服务器创建流程的简单方法,可以轻松地重复。把脚本引入版本管理系统中,使之透明、可审计、可逆,并进一步向可测试迈进。
避免每次都需要编辑的脚本我不止一次看到经验丰富的系统管理员编写创建服务器的脚本,但是他们不熟悉基础设施即代码,所以这些脚本每次运行时都需要设置参数。这可能有助于简化一部分手动过程,但并没有真正自动化服务器的创建过程。
我们的目标应该是,即便使用脚本的人需要知道自己想要的东西,也不应该需要记住如何做到的细节。这些细节以及如何组合各种选项的逻辑(用来给用户想要的东西)都应当放在脚本中。
6.2.3 反模式:热克隆服务器
6.2.4 模式:服务器模板
6.2.5 反模式:雪花工厂
6.3 引导新服务器的模式
6.3.1 推送引导
要在创建服务器时运行配置工具,需要引导程序能够运行该工具。有两种主要的实现策略:推送引导和拉取引导。
6.3.2 拉取引导
6.3.3 实践:对每个新服务器实例进行冒烟测试
6.4 结语
在每个新服务器创建时做完整性检查是明智的。服务器自动冒烟测试脚本可以检查你对所有服务器的基本要求,与服务器角色相关的特定信息以及常规的合规性。下面是一些例子。• 服务器是否在运行并且可以访问?• 监控代理是否在运行?• 服务器是否在 DNS、监控和其他网络服务中出现?• 所有必要的服务(Web 服务器、应用服务器、数据库服务器等)是否都在运行?• 是否存在必要的用户账户?• 是否开放了任何不该打开的端口?• 是否启用了任何不该启用的账户?冒烟测试应当自动触发。如果依赖人去手动运行脚本,它就可能被忽视,并且随着时间的推移变得没什么用。我们可以求助于 Jenkins 或 GoCD 这样的 CI 或者 CD 服务器,因为它们每次都可以自动运行这些类型的测试。
第7章 管理服务器模板的模式
7.1 供应模板:不能让别人来做吗
本章建立在前面关于创建和置备服务器的章节基础之上,讨论管理服务器模板的方法。
使用服务器模板有助于可重复地创建新服务器并保持一致性,然而这要求用良好的流程来管理模板。需要借助补丁和改进来构建模板并保持更新。实现该目标的流程和工具需要遵守基础设施即代码的原则。模板本身应通过可重复、透明、自文档和自测试的流程来构建。
7.2 使用模板置备服务器
7.2.1 创建时置备服务器
使用模板置备服务器一个自然的问题是,在服务器模板中应该置备哪些配置元素和软件包,以及在创建新服务器时应该添加哪些配置元素和软件包。
创建时置备服务器一个极端做法是最小化模板里的内容,并在创建新服务器时执行大部分配置工作。新服务器始终能获取最新的变更,包括系统补丁、软件包版本和配置选项。这种方法简化了模板管理。模板的数量会非常少
创建期间进行置备的问题每次创建新服务器时进行大部分置备工作的主要缺点是创建新服务器需要更长时间。对每个新服务器都重复相同的活动可能是浪费。每次创建新服务器时下载大量包和文件会浪费带宽。对于有些基础设施而言,自动化创建新服务器是其灾难恢复、自动化伸缩以及(或者)部署的关键部分,重量级的服务器创建过程意味着这些事情需要更多的时间。较大规模的灾难恢复方案可能尤其令人痛苦,因为置备新服务器需要先等待重新创建仓库服务器和配置服务器等基础设施服务。
7.2.2 在模板中置备
7.2.3 平衡模板和创建之间的置备工作
在模板中置备置备服务器的另一个极端做法是将几乎一切都放在服务器模板中。创建新服务器则变得非常快速和简单,只需要选择模板和应用实例特定的配置(比如主机名)。这对于需要快速启动新实例的基础设施非常有用,比如用来支持自动化扩容。
平衡模板和创建之间的置备工作尽管可以选一个极端,或在模板构建阶段完成所有配置,或在新服务器创建阶段完成所有配置,但大多数团队会选择将置备任务同时分配到两个阶段。在决定如何平衡置备工作时,需要考虑几个因素。
一个考虑因素是在新建服务器中应用变更的周期时间
需要频繁变更的部分最好放在服务器创建时完成,不经常变更的则放在模板中。
7.3 构建服务器模板的流程
为多个平台创建模板
构建模板包括以下流程:• 选择一个原始镜像;• 定制化原始镜像;• 将该镜像打包到服务器模板镜像中。
7.4 原始镜像
7.4.1 反模式:热复制服务器模板
服务器模板通常是通过给正在运行的服务器创建镜像来构建的。这涉及从某种原始镜像启动服务器,对该服务器进行自定义,然后对该服务器做快照生成新的模板镜像。原始镜像有几种选项。
反模式:热复制服务器模板如前所述,不应通过热复制一个正在运行的服务器来创建新服务器(见 6.2.3 节)。创建服务器模板也是如此。如果希望服务器具有可复制性,则要求模板也是可复制的。因此启动、定制和快照服务器以创建模板的整个过程,应该是完全受控且可复制的。
7.4.2 基于操作系统安装镜像烘焙模板
7.4.3 基于供应镜像烘焙模板
应该从一个从未应用于其他目的的干净服务器来创建模板。这样,新服务器的唯一历史记录及运行时数据就只会来自于设置模板的过程,而不会来自任何生产用途。
基于操作系统安装镜像烘焙模板操作系统安装镜像(例如,操作系统供应商的 ISO 文件)为构建服务器模板提供了一个干净、一致的起点。模板构建过程起始于从操作系统镜像引导服务器实例和运行自动安装过程(例如,Red Hat 提供的 Kickstart)。然后,对服务器实例进行定制化,最后保存镜像作为模板。这往往是虚拟化平台的一个选择,但大多数 IaaS 云平台并不提供直接从 ISO 引导服务器的简单方法。在这些情况下,最可行的选择是基于供应镜像进行构建。
基于供应镜像烘焙模板
可以直接用供应镜像创建服务器。但通常推荐只将其作为创建自定义模板的起点。这样可以添加团队自己的基础设施所需的包和配置。供应商的供应镜像通常有多种用途,所以剔除不需要的包是个好主意
7.4.4 基于Unikernel构建模板
7.4.5 在不启动服务器的情况下自定义服务器模板
7.5 更新服务器模板
7.5.1 重新烘烤模板
7.5.2 烘焙新模板
7.5.3 版本控制服务器模板
7.6 构建基于角色的模板
7.6.1 模式:分层模板
7.6.2 共享模板的基础脚本
7.7 自动化服务器模板管理
7.7.1 在烘焙前自定义服务器
7.7.2 实践:自动测试服务器模板
7.8 结语
7.8 结语
想法:2023-11-16 10:22:50
本章节简要看了一下
第8章 服务器更新与变更模式
动态基础设施使得创建新服务器变得非常容易,但在创建之后一直保持最新的状态就难多了。这两种情况相结合常常会导致麻烦,譬如状态不一致的服务器蔓延开来。正如我们在前面的章节看到的,状态不一致的服务器很难实现自动化,所以配置漂移导致了无法管理的“意大利面式”基础设施。
因此管理服务器变更的流程对于管理良好的基础设施来说是至关重要的。
在自动化流程之外,不应该允许对服务器进行变更。
如果经常绕过自动化流程发起变更,那就表明需要改进这些流程,确保新流程成为团队成员最简单和最自然的工作方式。
更新服务器的流程应该是毫不费力的,这样它就可以随着服务器数量的增长而扩大规模。对服务器进行变更应该是完全无人值守的流程。
高效的服务器变更流程有以下特点:• 自动化流程是团队成员应用变更的最简单和最自然的方式;• 变更会被发布到所有相关的现有服务器上面;
8.1 服务器变更管理模型
8.1.1 临时性变更管理
8.1.2 持续配置同步
8.1.3 不可变服务器
• 服务器的配置应该接近,不允许产生不一致的漂移;• 变更应用的过程应该是无人值守的;• 无论影响到多少台服务器,一项变更所涉及的努力应该是相同的;• 错误的变更会快速可见。
本章将深入讲解第 4 章介绍的主要的服务器变更管理模型(详见 4.3 节),然后描述实现它们的模式与实践
服务器配置变更的 4 种模型分别是:临时性、配置同步、不可变服务器和容器化服务器。
临时性变更管理
这往往会导致服务器配置不一致,并导致难以可靠、全面地实现自动化。为了能够跨多台服务器运行自动化的流程,这些服务器的状态需要始终保持一致。
持续配置同步
确保了在运行时所做的任何变更都会及时同步生效,从而防止了配置漂移。
持续同步有助于维护良好自动化的基础设施的规范。无论给这些工具什么配置,它们都会运行,所以团队必须保持正确的配置定义。配置同步执行的时间间隔越短,就会越快发现配置定义的问题。越快发现问题,团队就能越快修复它们。
任何不是通过配置定义来显式管理的部分都可能会在工具之外发生变更,这给它们留下了配置漂移的隐患。
不可变服务器
所谓的“不可变服务器”方法是指,当变更发生时,不直接对现有的服务器进行修改,而是通过构建一台全新的服务器来进行配置变更。1 这确保了任何变更在发布到生产环境之前都会进行测试,因为对运行中的基础设施进行变更可能会导致预料之外的后果。
8.1.4 容器化服务器
8.2 通用模式和实践
不可变服务器仍然有配置漂移的风险,因为人们仍然可以在服务器置备出来以后修改其配置。然而,这项实践一般会与保持服务器较短的生命周期相结合,就像对凤凰(Phoenix)服务器所做的一样
把“不可变”一词理解为针对服务器的配置而非整个服务器可能更加恰当。这样,在配置和数据之间有了一条清晰的界限。它强制团队明确定义服务器的哪些元素将会被作为配置项进行管理,哪些元素会被视为数据。
容器化服务器
容器对于变更频繁的应用程序(例如内部开发的软件)很有用。
8.2 通用模式和实践
8.2.1 实践:最小化服务器模板
8.2.2 实践:当服务器模板变更时更换服务器
8.2.3 模式:凤凰服务器
实践:最小化服务器模板
服务器开始的配置越少,未来要管理的配置就越少。这对于安全、性能、稳定性和故障排查也同样是个好主意。
实践:当服务器模板变更时更换服务器
只要构建服务器的模板进行了升级,更换运行中的服务器就是一个好的实践,如图 8-1 所示。更换应该是渐进式的,而非颠覆式。例如,新的模板可以先应用在测试环境中,然后推进到更敏感的环境里。请参阅第 12 章以了解更多相关内容。此外,服务器集群的成员可以被有序地更换,以避免中断服务。
模式:凤凰服务器
有些组织发现,即使服务器模板没有发生变更,定期更换服务器也是一种解决配置漂移的好方法。实际上,这实现了服务器 100% 全自动管理的目标。只要不是通过持续同步的配置定义进行管理,任何对服务器的修改都会在使用模板重新创建服务器的时候重置。这是通过设置所有服务器的最长生命周期,并且定期重建超过此时限的服务器来实现的。此流程应确保服务不会中断,例如使用零停机更换模式
8.3 持续部署的模式与实践
8.3.1 模式:无主服务器的配置管理
8.3 持续部署的模式与实践
持续同步需要定期运行一个进程,将当前的配置定义应用到给定的服务器上面。这个过程有两种不同的工作方式。一是推送模型,指由一个中央进程控制调度,连接到各个服务器来发送和应用配置定义。二是拉取模型,指目标服务器本身运行一个进程,下载和应用最新的配置定义。
想法:2023-11-16 10:31:04
前面的两章节也是类似的拉取和推送
8.3.2 实践:应用Cron
8.3.3 持续同步流
8.3.4 未配置领域
持续同步流持续同步会将配置定义应用并且重复应用到服务器上。图 8-3 展示了整个流程。在把配置定义应用到服务器上之后,假如配置定义没有变化,那么配置工具的重复运行不会导致任何变化。如果配置定义发生变更并且生效,那么配置工具在下次运行的时候就会将这个变更应用到服务器上。
8.4 不可变服务器的模式与实践
8.4.1 服务器镜像作为制品
8.4.2 使用不可变服务器简化确认管理工具
8.4.3 不可变服务器流程
8.4.4 使用不可变服务器引导配置
8.4.5 事务性服务器更新
8.5 管理配置定义的实践
8.5.1 实践:保持配置定义最小化
8.5 管理配置定义的实践
实践:保持配置定义最小化
包括配置定义在内的代码都是有开销的。随着代码量的增加,团队花在编写、维护、测试、更新、调试和修复代码上的时间也越来越多。
尽力减小代码库的大小。
8.5.2 组织定义
8.5.3 实践:使用测试驱动开发来驱动良好的设计
8.6 结语
8.5.2 组织定义
一旦基础设施团队掌握了编写与使用服务器配置工具的基础知识,就应该投入时间来学习如何使用工具的特性去实现模块化与重用。目标是确保单独的模块或定义文件都很小、简单、易于理解。
8.5.3 实践:使用测试驱动开发来驱动良好的设计
它的主要价值在于驱动整洁、可维护的代码设计。
第9章 定义基础设施的模式
本章将探讨怎样置备和配置更大的基础设施元素组。随着基础设施的规模、复杂度和用户数不断增长,基础设施即代码的收益越来越难实现:• 特定变更的影响范围越来越大,从而很难实现频繁、快速和安全的变更;• 人们在例行维护和救火上花费更多时间,在为服务带来有价值的提升上花的时间越来越少;• 允许用户置备和管理自己的资源可能会对其他用户和服务造成破坏。
除了集中控制,另一个选项是设计基础设施以最小化特定变更的影响范围。即使基础设施的规模变得更大,一种定义、置备和管理基础设施的有效方式也将支持频繁和充满信心的变更。这就允许将应用和服务基础设施安全地委托出去。
9.1 环境
9.1.1 反模式:手动制作的基础设施
9.1.2 定义基础设施栈即代码
本章将关注于如何将基础设施组织成栈,以支持更简单、更安全的变更管理。将基础设施划分成栈的方式有哪些?对于栈而言,合适的大小是多大?有什么定义和实现栈的好方法?
9.1 环境
术语“环境”经常在有多个栈时使用,而这些栈实际上是同一个或同一组服务的不同实例。环境最常见的用途是测试。应用程序或服务可能有“开发”“测试”“预生产”和“生产”环境。这些环境的基础设施通常是一样的,但可能因为规模不同而有些变化。
9.1.1 反模式:手动制作的基础设施
想法:2023-11-16 10:43:41
本书中的反模式,即不推荐的做法(比如手工),与推荐的模式相反的意思
9.1.3 反模式:每个环境单独的定义文件
9.1.4 模式:可重用的定义文件
9.1.4 模式:可重用的定义文件更有效的方式是,在所有代表相同应用程序或服务的环境中使用单个定义文件。可以用参数化的方式在这个文件中设定每个环境的特定选项。这使得构建和运行一个基础设施栈的不同实例变得很容易。
9.1.5 实践:测试并推进栈定义
9.1.6 自服务的环境
9.2 组织基础设施
9.2.1 反模式:单体栈
9.1.6 自服务的环境
参数化的环境定义还有另一个好处,那就是很容易创建新的实例。
9.2 组织基础设施基础设施通常是由多种互相关联的栈组成的。一些栈共享诸如网络设备之类的基础设施,还有一些则依赖于互相之间的网络连接。通常需要把一些持续的变更流应用到部分或全部的栈,这可能会导致问题。本节会讨论一些组织基础设施的办法,可以解决这些问题
9.2.2 迁移基础设施时避免“直接迁移”
9.2.3 将应用程序环境分到不同的栈中
迁移基础设施时避免“直接迁移”
跳出已有的、经过考验的基础设施实施来思考有难度,但是值得投入精力。
将应用程序环境分到不同的栈中多层的应用程序可以被分成多个栈,从而使每个层级都可以独立地修改。
9.2.4 管理栈之间的配置参数
9.2.5 共享基础设施元素
9.2.6 实践:应用程序代码和基础设施代码一起管理
为每个应用程序分配专用的基础设施,升级就可以按更易于管理的任务块执行,管理开销也更小。乍一看,给每个应用程序升级数据库可能比一次性升级一个单独的共享实例更低效。但是前者的风险要小得多。自动化可以减少升级时间并提升可靠性。可以通过先在测试环境中自动应用和测试升级来使其更加可靠。
9.2.7 共享定义的方法
9.2.7 共享定义的方法
对于许多开发团队来说,共享基础设施代码通常是有好处的。要在共享好的代码和保持团队敏捷之间取得平衡却并不简单。
有些团队用以下方法来解决这个问题。共享模块版本化团队在发布时可以选择是否更新模块版本,这样就可以在时间允许的情况下采用更新的版本。
9.2.8 实践:基础设施设计要与变更范围匹配
复制而不是共享团队维护应用程序和基础设施代码的模板,当需要创建新的应用程序时复制这些模板文件,当有改进时就放进模板中。有选择地共享团队使用一个共享的模块,但是可以根据需求选择编写另外的模块。可重写的模块把模块设计成易定制的,应用程序团队在需要时可以改写其中的行为。
9.2.9 示例:微服务的基础设施设计
9.3 运行定义工具
9.4 结语
第三部分 实践
第10章 基础设施的软件工程实践
基础设施即代码的涵义是,运行软件的系统和设备本身就可以当作软件来对待。这样才能够在基础设施领域采用那些在软件开发领域中被证明有效的实践和工具。本章将探讨一些特定的软件工程实践,这些实践对于开发和维护基础设施非常有效。
章所涉及软件工程实践的主旨是内建系统质量。质量并不是与开发毫无联系的实践,也不是系统构建完成之后的测试活动。质量必须是开发人员(包括基础设施开发人员)计划、设计、实施和交付系统工作中不可缺少的一部分。
在软件和基础设施开发中保障质量的一些原则 1 如下:• 及早开始交付可工作、有用的代码;• 持续进行小而有用的增量交付;• 只做当下必要的构建;• 每一次增量构建都尽可能简单;• 确保每一个变更都是精心设计和实现的;• 尽早收集每一个变更的反馈;• 随着你和用户对系统的学习,改变需求是意料之中的事情;• 假设交付的一切都将随着系统的演化而变更。
本章将介绍如何借助持续集成(CI)和持续交付(CD)的实践来支撑以上原则。本章也研究了使用版本控制系统(VCS)的实践,这些实践是实现 CI 和 CD 的前提条件。
10.1 系统质量
10.1.1 低质量的系统很难变更
10.1.2 高质量的系统能更容易、更安全地变更
10.1 系统质量良好的软件工程实践产生高质量的代码和系统。通常情况下,质量仅仅被视为关乎功能正确性。实际上,高质量才能保证变更顺利。衡量系统和代码质量的真实度量指标是,它们可以多快、多安全地进行变更。
10.1.2 高质量的系统能更容易、更安全地变更
类似这样的系统只需要很少的技术文档。通常情况下,绝大多数团队成员可以很快地画出和某个讨论相关的系统架构组件。拥有相关技术知识的新人通过沟通交流、阅读代码以及在系统上工作即可迅速熟悉情况。
10.1.3 基于代码的基础设施质量
10.1.4 快速反馈
10.2 基础设施管理的版本控制系统
版本控制系统管理什么
10.1.3 基于代码的基础设施质量
基础设施即代码将质量的焦点转移到了定义文件和工具系统上。自动化的结构和管理至关重要,这样才能获得高质量代码,从而让设施易于理解、变更简单并快速地从问题中得到反馈。如果用以构建和变更基础设施的定义和工具质量高,那么基础设施自身的质量、可靠性和稳定性也应该很高。
0.1.4 快速反馈高质量系统优势就在于可以快速反馈变更。如果我更改配置定义时犯了一个错误,我希望尽快发现这个错误。
10.2 基础设施管理的版本控制系统
版本控制系统管理什么将构建和重建基础设施所需要的一切都放入版本控制系统。理想情况下,如果你的整个基础设施全都丢失了,只要版本控制的内容还在,就能够从版本控制系统中检出所有的内容,然后运行几个命令就可以重建一切,当然可能还会根据需要拉取一些备份的数据文件。
版本控制系统中管理的一些内容包括:• 配置定义(cookbook、manifest、playbook 等);• 配置文件和模板;• 测试代码;• CI 和 CD 的任务定义;• 工具脚本;
10.3 持续集成
10.3.1 持续测试分支不是持续集成
编译完成的工具和应用程序的源代码;• 文档。
不需要放在版本控制系统的内容包括下面这些 2。• 软件制品应存放在仓库中(如储存 Java 制品的 Maven 仓库、APT 或 YUM 仓库等)。这些仓库应该经过备份或者有脚本(在 VCS 里面)可以重建它们。• 如果能够可靠地从版本控制系统里的源文件重新构建,那么构建出的软件和其他制品就不需要放入版本控制系统。• 由应用程序管理的数据、日志文件等类似的内容也不需要放入版本控制系统。应当将它们作为相关内容存储、归档或者备份。第 14 章详细介绍了这一点。• 密码和其他安全机密永远不应该存储在版本控制系统中,而应该使用那些自动化基础设施中管理加密密钥和机密的工具。
10.3 持续集成
持续集成这项实践并不只是关于使用 CI 工具,而是频繁集成和测试所有的变更。团队的所有开发人员都将他们的修改提交到代码库的主干。每次提交后,CI 工具都会构建代码库,并运行自动化测试套件。当代码的变更导致构建失败或测试失败时,它会快速地提供反馈。因为测试是基于每一次提交运行的,所以人们马上就可以清楚地知道是哪些修改引起了问题。开发人员提交得越频繁,修改集的规模就越小。修改集越小,发现和修复问题就会越快、越容易。
10.3.1 持续测试分支不是持续集成
有了持续集成,每个人可以将变更提交到同一个主干,并针对完全集成的代码库进行测试。当代码提交后,冲突就会很快被发现,这可以节省大量的工作。
10.3.2 谁破坏了构建
常见的分支策略
想法:2023-11-16 11:09:05
特性分支:当一个开发人员或小组开始在一个代码库上进行变更时,可以创建一个分支,从而使得他们的工作相对隔离。这种方式可以保证他们的工作不会破坏生产环境中的内容。当变更完成后,这个团队可以将他们的改动合并回主干; 发布分支:当一个新版本部署到产品环境后,可以创建一个分支来反映当前生产环境下的版本。缺陷修复可以在这个分支上进行,并合并进主干。下一个版本的工作在主干上进行; 持续集成:所有工作都在主干上完成和提交。持续集成可以用来保证每一个提交都被全面测试。持续交付流水线可以用来确保变更被全面验证后才应用到生产环境;
越频繁地将变更提交到共享的主干,而且提交越小,那么冲突就会越小,测试就会越容易,要修复的问题也就越少。
为了使持续集成有效,CI 系统上的每次构建或测试失败都必须立即解决。当忽略或者没有注意到构建失败时,错误就会堆积起来,在以后变得扑朔迷离、难以理清。
在错误修复之前,团队的其他人都不能提交任何更改,以使问题更容易解决。
提交导致失败的人应该优先修复问题。如果变更没有被迅速修复,那么它应该在版本控制系统中回滚,使得 CI 任务可以重新运行,并有望回到绿色的状态。
10.3.3 忽略失败的测试
10.3.4 针对基础设施的持续集成
10.4 持续交付
10.4.1 集成阶段的问题
10.3.3 忽略失败的测试
一个相关的坏习惯是为了继续构建而“暂时”禁用或注释那些失败的测试。修复失败的测试应该是你的当务之急。发布某个特定的变更或许很重要,但是测试套件才能给予你快速发布的能力。如果你允许测试降级,那么就是在损坏你的交付能力。
CD 背后的思想是确保能够持续地验证所有的可部署组件、系统和基础设施,并确保它们都准备好部署到产品环境了。CD 用来解决“集成阶段”的问题。
10.4.2 部署流水线和变更流水线
执行频繁的测试部署可以确保部署流程得到了充分的验证。如果应用程序的任何变更会影响到生产环境的部署,它们会首先破坏测试环境的部署。这也意味着问题能够被快速修复。严格遵循这一实践会使部署到生产环境成为一件很容易的事。
10.4.3 持续交付不是持续部署
实施变更和部署软件的过程会涉及各种环境、工具以及流程,在流水线的所有阶段中使其保持一致至关重要,因为这样可以确保尽早发现在生产环境中可能出现的问题。
测试环境应该如生产环境一样固定。在测试环境中添加生产环境中没有的权限只会导致生产环境部署失败。如果生产环境的约束使其不能像测试环境那样易于变更,那就要么找到在这些约束下轻松工作的部署方案,要么找到更好地满足这些约束目标的方法。
10.4.3 持续交付不是持续部署
CD 的要点不是将每一个变更立即应用到生产环境,而是确保每个变更都可以部署到生产环境。
这仍然需要决定什么时候真正地将特定的变更或者发布版本推送到生产环境。这可以由人来决定,但是由工具自动执行。实现决策流程的授权和审核甚至也会成为可能。
10.5 代码质量
10.5.1 整洁代码
10.5.2 实践:管理技术债务
10.5 代码质量
10.5.1 整洁代码
10.5.2 实践:管理技术债务
软件工艺主要是关于如何避免技术债务。在发现问题和缺陷的时候立刻修复它们是一个非常好的习惯。如果能在制造它们的时候发现和修复就更好了,而不是养成“认为现在已经足够好”的坏习惯。
10.6 管理重大的基础设施变更
特性开关
10.6 管理重大的基础设施变更
本书推荐的工程实践都是基于每次只做小变更的策略(详见 1.5.5 节)。当需要交付大的、可能是颠覆性的变更时,这种方式可能面临较大的挑战。
敏捷交付复杂工作的关键是将复杂任务分解成小的变更。每一个变更都应该有潜在的价值,至少足以让他人尝试并看到效果,即便它并没有准备好用于生产环境。
有一些方法有助于把重要的变更增量式地构建到生产系统中,其中之一是进行不那么颠覆性的小变更。慢慢地、一点点地替换旧的功能
另一种方法是将变更隐藏为对用户不可见。在更换用户目录服务的例子中,你可以开始构建一个新的服务,并部署到生产环境,同时保持旧的服务仍然运行。这样就可以对依赖于它的那些服务进行选择性的测试。
10.7 结语
第11章 测试基础设施变更
前一章描述了如何将诸如 CI 和 CD 这样的软件工程实践应用到基础设施即代码中,主旨是质量管理。本章将深入介绍测试的细节,特别是自动化测试。自动化测试是能够持续测试系统变更的关键,但很多团队发现难以持续构建和维护自动化测试套件。本章介绍成功建立并保持自动化测试体系的团队所采用的方法。
测试的目的是帮助快速地完成工作。遗憾的是,许多组织认为测试会减慢工作进程。人们对于质量和交付的关系有一个常见的误解,即认为质量和交付速度是对立的,必须对两者做出折中。这种思维方式导致了这样的想法:自动化通过让系统测试变得更快,进而加速交付流程。
自动化测试的目标是通过尽早识别和修复错误来帮助团队保持系统的高质量。在持续测试和问题修复方面具有严格纪律的团队,能够快速且自信地做出变更。
一个强大、平衡的自动化测试体系会带来如下好处:• 减少在生产环境中发现的错误;• 加快错误发现后的修复速度;• 能够频繁地变更和改进。
11.1 敏捷测试方法
11.1.1 自动化测试提供快速反馈
11.1 敏捷测试方法
敏捷过程提倡团队将测试与实现合并,从而缩短反馈循环(见图 11-1)。测试可以随着变更持续进行。测试人员和开发人员紧密合作,并与自动化测试结合,就可以获得这样的效果。
自动化测试的最有效目标不是缩短项目测试阶段的时间,而是将测试和修复活动一起纳入到核心工作流中。当对系统进行修改时,不管它是针对应用程序代码的修改,还是针对基础设施定义的修改,人们都会持续地进行测试
测试的目的是能够在做出变更的时候立即修复每一个问题。此时他们对这些变更仍记忆犹新。由于变更的范围也非常小,问题可以很快被发现并修复。
11.1.1 自动化测试提供快速反馈
测试自动化成功的关键在于整个团队能够参与其计划、设计和实现,而不是将它作为一个孤立小组的责任。
11.1.2 有机地构建一个测试套件
11.2 构建测试套件:测试金字塔
11.1.2 有机地构建一个测试套件
要启动一个能够产生良好测试习惯的计划,采用的方式并不是试图构建一个完整的测试用例套件来覆盖现有的功能,而是当每一个新的变更出现的时候,都为它编写测试。当发现一个 bug 时,针对那个 bug 编写测试,然后修复它。当需要一个新的特性或者功能时,可以在开发的同时实现测试,甚至可以使用测试驱动开发
将测试套件作为常规变更的一部分有机地进行构建,会迫使每个人去学习可持续的持续测试习惯和技能。再次强调,自动化测试的目标不是一个“完整”的测试套件,而是对每一个变更进行测试的日常例程。测试套件几乎是作为一个副产品从这种方式中产生。有趣的是,这样的测试套件会更关注于那些最需要测试的系统领域,即变化最多或者破坏最严重的地方。
11.2 构建测试套件:测试金字塔管理测试套件非常有挑战性。测试应该快速运行,易于维护,并帮助人们快速地找到解决故障的原因。测试金字塔是一个用以思考如何平衡不同的测试类型,从而实现这些目标的概念
11.2.1 避免失衡的测试套件
在金字塔中,测试的范围越向上越广,越向下越窄。较低层级的测试验证小范围、单独的内容,例如定义文件和脚本。中间层级把一些较低级别的元素放在一起测试,例如创建一个正在运行的服务器。最高层级则测试整体集成的系统,例如一个拥有多个服务器和周边基础设施的服务。
自动化测试套件的一个常见问题是出现失衡,如同甜筒冰淇淋或者倒金字塔的形状,如图 11-3 所示。这种情况的发生大多是因为相对于较低层级的测试,高层级的测试过多。
11.2.2 实践:尽可能在最低层级进行测试
11.2.2 实践:尽可能在最低层级进行测试
UI 和其他高层级的测试应该保持在尽量少的数量,且只应该在较低层级的测试运行之后才运行。有效的测试套件只运行少量的端到端测试,覆盖系统的主要组件,并证明集成部分工作正常。具体的特性和功能应该在组件级别的测试或者单元测试中进行。
11.2.3 实践:仅实现需要的层级
11.2.4 实践:经常删减测试套件
11.2.5 实践:持续评审测试的有效性
11.2.3 实践:仅实现需要的层级
测试金字塔表明,每个组件都有多个集成层级的测试。要实现哪一层级的测试取决于特定的系统及其需求。避免过度复杂的测试套件是很重要的
11.2.4 实践:经常删减测试套件
当编写新的测试成为一种习惯,团队也需要相应地形成删减测试的习惯来以保持套件的可管理性。当然,避免在一开始就实现无用的测试也是很有帮助的。
11.2.5 实践:持续评审测试的有效性
最有效的自动化测试体系需要不断地评审和改进测试套件。你需要不时地对测试进行纵览和调整,删除测试层级或者一组测试,增加新的层级或者新的测试类型,增加、删除或者替换工具,改善管理测试的方式,等等。
11.3 实现均衡的测试套件
基础设施单元测试的代码覆盖率要尽量避免为基础设施单元测试的代码覆盖率设置目标。因为基础设施的配置定义往往相对简单,所以基础设施代码库可能不会有软件代码库那样多的单元测试。设置单元测试覆盖率的目标在软件开发世界中是一个滥用的实践,可能会导致团队编写和维护无用的测试代码,使得维护良好的自动化测试更加困难。
11.3 实现均衡的测试套件
在金字塔的不同层级上,不同类型的测试可能需要不同的工具。避免执着于工具是很重要的。要避免选择一个工具,再围绕这个工具来构建测试策略。相反,要分析系统和组件,从而决定如何进行测试,然后选择工具来实现。与基础设施的任何部分一样,你也会随着时间的推移改变一部分测试工具。
11.3.1 低层级测试
11.3.1 低层级测试
11.3.2 中间层级测试
语法检查
静态代码分析
单元测试
11.3.2 中间层级测试
创建测试基础设施
本地测试基础设施的虚拟化
管理测试基础设施的工具
11.3.3 高层级测试
11.3.3 高层级测试
11.3.4 测试运维质量
11.3.4 测试运维质量
自动化测试是保障运维需求必不可少的方法。每当系统或基础设施变更时,证明它没有引起运维问题是很重要的。团队应该有相关的目标和阈值,能够基于其编写测试来保证每次变更的正确性。
11.4 管理测试代码
11.4.1 实践:将测试代码与所测代码放在一起
11.4.2 反模式:反射测试
监控即测试监控和自动化测试之间密不可分,两者都是检测系统问题的方式。测试主要针对系统变更,目的是在将变更应用到生产系统之前发现它可能引入的问题。监控旨在检测运行中系统的问题
11.4 管理测试代码
应该可以用一种可重复、可复制、透明的方式来配置测试代理或软件,该方式还应具备基础设施即代码所期望的所有其他质量属性。
11.4.1 实践:将测试代码与所测代码放在一起
测试代码应该和其所测的代码一起管理。这意味着把它们都放到你的版本控制系统中,并一起提交到流水线中,直到它们到达运行阶段。这避免了测试代码与所测代码的不匹配。
11.4.3 隔离组件进行测试的技巧
11.4.3 隔离组件进行测试的技巧
为了能够有效地测试一个组件,测试时必须将这个组件从它的依赖中隔离出来。
11.4.4 重构组件以便隔离
11.4.5 管理外部依赖
611.4.4 重构组件以便隔离
通常情况下,一个特定的组件很难被简单地隔离。对其他组件的依赖可能是硬编码的,也可能太乱以至于很难分开。相对于随后写测试,在设计和构建系统时写测试的好处之一是它会强迫你改进设计。如果一个组件很难被单独测试,这通常表示设计有问题。设计良好的系统应该由很多松耦合的组件组成。因此,在那些很难隔离的组件上运行测试时,应该先修复设计
11.4.5 管理外部依赖
依赖于其他团队管理的服务是很正常的。一些诸如 DNS、认证服务或邮件服务器的基础设施元素可以由一个单独的团队或外部供应商提供。这可能会成为自动化测试的挑战,因为:• 他们可能无法处理持续测试带来的压力,更不用说性能测试了;• 他们可能有一些可用性问题会影响到你的测试,这在由供应商或团队提供服务的测试实例时尤为常见;• 可能成本很高或者请求受限,这使得在持续测试中使用它们变得非常不切实际。
11.4.6 测试设置
自动化测试的一般原则是每个测试应该是独立的,并应确保其所需的开始状态。它应该能够以任何顺序运行测试,可以自己运行任何测试,并总能得到相同的结果。
下面是关于测试数据的一些规则:• 每个测试应该创建它需要的数据;• 每个测试要么在运行后清理数据,要么在每次运行时创建唯一的数据;• 测试在开始时不应该假设有什么数据或没有什么数据
11.5 测试的角色和工作流
11.5.1 原则:人们应该为所构建的东西编写测试
11.5 测试的角色和工作流
敏捷软件开发带来的一个重大好处是打破了开发人员和测试人员之间的孤岛。不是将质量作为一个单独团队的职责,而是由开发人员和测试人员共同负责。敏捷团队不是在系统即将完成时分配大块的时间专门测试,而是在编码的时候就开始测试。
这里有一些关于如何在团队里管理测试的指导原则。
11.5.1 原则:人们应该为所构建的东西编写测试
11.5.2 编写测试的习惯
11.5.3 原则:每个人都应该能够使用测试工具
11.5.4 质量分析师的价值
11.5.2 编写测试的习惯
11.5.3 原则:每个人都应该能够使用测试工具
11.5.4 质量分析师的价值对于质量保障工作拥有深厚专业知识和热情的工程师在哪个工程团队都有巨大价值。他们经常充当测试实践的拥护者,帮助人们思考正在计划或讨论的工作。
11.5.5 测试驱动开发
11.5.5 测试驱动开发测试驱动开发(TDD)是极限编程 11 的一项核心实践。它的思想是,因为写测试可以改善所构建系统的设计,所以应该在写相关代码之前写测试。经典的工作节奏是“红 - 绿 - 重构
红为下一个变更编写测试,运行测试,然后看到它失败变红。绿实现并测试定义,直到测试通过。重构改进老定义和新定义,使其结构良好。
11.6 结语
第12章 基础设施的变更管理流水线
本章会解释如何通过构建变更管理流水线去实现基础设施的持续交付。
CD 和软件部署流水线的重点在于允许变更以一种持续的流而不是大批量的方式交付。变更能够验证得更加彻底,不仅因为是通过自动化过程去应用,而且因为是一提交就测试,变更还不大。如果做得好,结果是可以更频繁、更快速、更可靠地应用变更。
持续变更管理基础设施的持续交付可以被视为持续的变更管理或者持续的置备(详见文章“Continuous Provisioning - The Final Frontier”)。重点在于创建一个经过优化的过程,可以快速、严格地验证小变化的持续流。
12.1 变更管理流水线的好处
12.2 设计流水线的准则
基础设施变更管理流水线和软件部署流水线没有什么不同。很多人将应用基础设施变更的流水线叫作“部署流水线”。我喜欢用“变更管理流水线”这个词是为了强调它和基础设施的相关性。软件部署流水线已被认为是软件发布过程的自动体现。3 变更管理流水线可以被描述为基础设施变更管理流程的自动化体现。
变更管理流水线像下面这样工作。• 迅速并全面地测试每一个变更,以证明它是否可以部署到生产环境。• 渐进地测试受变更影响的系统元素。这和前一章讨论过的测试金字塔一致。• 在适当情况下,启用手动验证活动,如探索性测试、用户验收测试(UAT)和审批。• 以低风险、低影响的方式将变更轻松、快速地应用到生产系统。做到这一点的前提是确保应用变更的过程是全自动的,并且在所有环境中都相同。
以流水线的方式管理基础设施变更的团队会发现以下好处。• 可以随时把基础设施管理工具和代码部署到产品环境。产品上线从来不需要额外的工作(例如,合并、回归测试以及“增强”)。• 交付变更毫不费力。一旦有变更通过流水线的技术验证阶段,除非有问题,否则不需要特别注意就可以进入生产环境。不再需要决定如何应用变更到产品环境的技术决策,因为已经在先前阶段就制定、实现和测试过这些决策了。• 没有什么方式比通过流水线进行变更更加简单。除了启动已经停机的系统之外,手动处理比直接通过流水线进行变更需要更多的工作,而且更可怕。• 合规与治理更容易。引发变更的脚本、工具和配置对于评审者是透明的。可以审计日志来证明谁在什么时间做出了何种变更。使用自动化变更管理流水线,团队可以证明任一变更所遵从的过程。这强于听某人声称遵从了文档中手动过程的一面之词。• 变更管理过程可以更加轻量化。人们可以把需求构建到自动化工具和测试中,而无须讨论和检查每个变更。他们可以周期性地查看流水线的实施和日志,按需做出改进。这样能把时间和注意力放在过程和工具上,而不是逐一调查每个变更。
12.2 设计流水线的准则
12.2.1 确保每个阶段的一致性
12.2.2 对于每个变更都立即得到反馈
12.2.1 确保每个阶段的一致性环境、工具和过程在各个阶段应当是一致的。
一致的环境并不意味着完全相同反对让测试环境和生产环境一致的一个理由是成本。对于有着成千上万台服务器或者昂贵硬件的组织,在流水线中的每个阶段或者任何阶段都复制环境并不现实。
下面是一些指导原则。
• 确保基本的特性一样。操作系统和版本应当始终相同。如果生产环境使用了更贵的操作系统发行版(比如“企业版”),你要么咬紧牙关,至少在一个前期环境中使用它,要么确保对于你使用的操作系统,组织能付得起全面使用的费用。• 复制足够多的生产环境特性,这样就可以捕获潜在的问题。不需要在测试环境的负载均衡池运行 50 台服务器。但至少得保证在相似的负载均衡器后运行 2 台服务器,并且充分运行以发现状态管理的潜在问题。• 在前面的阶段,至少有一个环境应该复制生产环境的复杂性。但是没有必要每个环境都这样做。例如,前面介绍的简单流水线的自动化部署测试环境可能有一个服务器的负载均衡池,在生产环境里将应用程序部署到不同的服务器上。但是即使在像 QA 和 UAT这样的后期阶段,在单台服务器上也能运行所有应用程序。生产环境的架构需要仔细考虑,以确保暴露了所有潜在的风险。
12.2.2 对于每个变更都立即得到反馈
确保流水线快速运行,从而可以在提交变更时立刻得到反馈。流水线应当是快速解决生产环境问题的最简单方法。如果需要绕过流水线去应用变更,就标志着该改进流水线了。
12.2.3 在手动阶段之前运行自动阶段
12.2.4 尽早获得类生产环境
12.2.3 在手动阶段之前运行自动阶段
一旦可以在无人值守的情况下自动化地将变更应用到系统,运行自动化测试就会比经验丰富者测试的成本更低而且速度更快。因此,在将系统交给人之前,首先运行所有的自动化测试是有意义的。
12.2.4 尽早获得类生产环境
对于一个理想的流水线,刚提交的变更会被自动应用到最准确的测试环境中。这时的测试可以确保,在交付给人类来决定是否准备好了之前,该变更已被证明在技术上对于生产环境就绪了。
12.3 基本流水线设计
12.3.1 本地开发阶段
12.3.2 构建阶段
12.3 基本流水线设计
12.3.1 本地开发阶段
12.3.2 构建阶段
12.3.3 发布配置制品
构建阶段可能会包含下面的一些动作。• 语法检查和静态分析(详见 11.3.1 节)。• 编译相关的代码。• 单元测试。• 本地执行测试。对于软件组件和服务,即使不在完全的部署环境中,运行和测试它也是合适的。通常会使用测试替身(详见 11.4.3 节),而不是与其他系统或者基础设施元素集成,来保证这个阶段是自包含的。在某些场景下,容器化(比如 Docker)可以帮到我们。• 生成和发布报告,比如代码变更报告、测试结果、生成的文档以及代码覆盖率报告。• 将代码打包为可发布和部署的格式。
12.3.3 发布配置制品
每一个成功的构建阶段结束后,都会打包和发布配置制品。这意味着为流水线后续阶段的使用准备相关的材料。取决于基础设施元素的性质,其中涉及:• 针对系统或者语言构建一个安装包文件(如 RPM、.deb、.gem 等),并且上传到仓库;• 将定义文件集(如 Puppet module、Ansible playbook、Chef cookbook 等)上传到配置仓库;• 在基础设施平台上创建一个模板服务器镜像(VM 模板、AMI 等)。
制品是:原子的(atomic)将一组给定的材料作为一个单元进行组装、测试和应用;可移植的(portable)可以通过流水线来推进,并且不同的版本可以应用到不同的环境或者实例;版本化的(versioned)可以可靠、可重复地应用到任何环境,这样任何给定的环境都会有一个明确的组件版本;
12.3.4 自动化测试阶段
完整的(complete)给定的制品应当包括部署或者配置相关组件所需要的一切,不应该假定组件制品的早先版本之前已经应用;一致的(consistent)将制品应用到任何两个组件实例,结果应该相同。
在使用主服务器(例如,Chef Server、Puppet Master 或者 Ansible Tower)配置管理模型时,制品就是定义文件(例如,cookbook、module 或者 playbook
在无主服务器的配置管理模型中(详见 8.3.1 节),配置定义存储在一个通用的文件管理系统中,而不是一个特殊的配置服务器中。这可能是文件服务器、静态 Web 服务器、对象存储(如 AWS S3)、系统包仓库(如 APT 或者 YUM),甚至VCS。
对于不可变服务器(详见 8.4 节),制品就是服务器模板镜像。
12.3.4 自动化测试阶段
12.3.5 手动验证阶段
12.3.5 手动验证阶段
12.3.6 上线
12.3.7 流水线的节奏
保持流水线的流动性不要让共享的环境或阶段成为工作的瓶颈。团队经常会尝试将单一测试环境用于 QA和对利益相关者的演示。这通常会导致QA 的工作在精心准备环境的时候停止,然后在演示之前冻结。新的变更不能部署在测试环境,每次可能都得等几天,以防在演示前有什么破坏系统。在这些情况下,切分环境会更好。取决于多少测试人员同时工作,QA 工作至少得有一个环境。演示也应该有自己独立的环境。使用基础设施即代码来动态置备一致环境的能力有极大的好处。在很多场景下,可以根据演示或者测试练习的需要置备环境,然后销毁。
12.3.6 上线
零停机应用变更和部署系统的能力对于保证顺利应用并且快速、定期地发布变更必不可少。混乱的变更流程鼓励批量处理和低频率发布。这反过来增加了发布的大小、复杂度以及风险。确保零停机变更流程 9,比如蓝绿部署、凤凰部署以及金丝雀发布,在至少一个上游流水线阶段经过使用和测试很有用处,最好是在自动化测试阶段
12.4 使用流水线的实践
12.4.1 实践:证明每个变更都对生产准备就绪
12.4 使用流水线的实践
12.4.1 实践:证明每个变更都对生产准备就绪
12.4.2 实践:每个变更都始于流水线起点
12.4.3 实践:出现错误时停止流水线
12.5 扩展流水线到更复杂的系统
12.4.2 实践:每个变更都始于流水线起点
12.4.3 实践:出现错误时停止流水线
12.5 扩展流水线到更复杂的系统
12.5.1 模式:扇入型流水线
12.5.2 实践:保持较短的流水线
12.5.3 实践:解耦流水线
12.5.2 实践:保持较短的流水线
12.5.4 集成模型
12.6 处理组件之间依赖的技巧
12.6.1 模式:库依赖
12.6 处理组件之间依赖的技巧
12.6.1 模式:库依赖
12.6.2 模式:自置备的服务实例
12.6.3 提供预发布的库构建
12.6.2 模式:自置备的服务实例
12.6.4 为消费者提供服务的测试实例
12.6.5 将服务的测试实例用作消费者
12.7 管理组件间接口的实践
12.7.1 实践:保证接口的向后兼容性
12.7.2 实践:从发布解耦部署
12.7.3 实践:使用版本相容
12.7.4 实践:提供测试替身
12.7.5 实践:用契约测试来测试提供者
12.7.6 实践:用参考消费者来测试
12.7.7 实践:提供者接口的冒烟测试
12.7.8 实践:运行消费者驱动契约测试
12.8 结语
第13章 基础设施团队的工作流
13.1 任何可以自动化的都要自动化
最大的转变是不再直接操作服务器和基础设施,而是间接操作。基础设施工程师再也不能简单地登录到一个服务器上做变更,而是要对工具和定义做变更,然后让变更管理流水线将变更应用到服务器上。
想法:2023-11-16 14:14:28
自动,自动,自动
13.1 任何可以自动化的都要自动化
13.1.1 手动变更
13.1.2 临时的自动化
想要避免一次次查找突然出现的用户请求、问题或任务,有各种级别的技术可供使用,可以优先从这些开始:(1) 重新设计或者配置,不再需要做这个任务;(2) 实现自动化,透明地处理任务,不需要任何人关注;(3) 实现一个自服务工具快速地完成任务,执行的人不需要知道具体的细节——最好连要完成它的人也是如此;(4) 编写文档,使用户可以轻松地自行完成任务。
13.1.3 自主的自动化
13.1.4 自主的自动化工作流
13.2 使用本地沙箱
13.2.1 使用本地虚拟化做沙箱
13.2 使用本地沙箱
沙箱就是一个团队成员可以在将变更提交到流水线之前测试变更的环境。它可能运行在使用虚拟化的本地工作站上,也可能运行在虚拟化平台上
让沙箱环境工作的关键原则之一是一致性。沙箱需要代表真实的基础设施,让每个人都确信在一个地方正常工作的变更在另外一个地方也可以正常工作。实现这一目标的最可靠方法是尽可能地在沙箱和实际基础设施上使用相同的工具和配置。操作系统版本,服务器配置工具和定义,甚至相关的网络配置都应该是一样的。
理想情况下,用于在真实基础设施中启动服务器的服务器模板同样应该可以启动本地 VM。
13.2.2 具有本地测试的工作流示例
13.2.3 使用虚拟化平台做沙箱
13.3 代码库组织模式
保持短的变更 / 提交周期需要建立起组织变更的好习惯,使得即使在没有完成整个任务时生产环境也不会被破坏
13.2.3 使用虚拟化平台做沙箱
13.3.1 反模式:基于分支的代码库
系统架构、团队结构和变更管理流水线的设计之间有直接的关系。当这三个元素保持一致时,可以在工作流中找到证据:人们和团队基本不用协调就可以轻松地完成工作。如果它们没有保持一致,也会在工作流中体现出来。
有三种组织大型代码库的主要模式:分支,每个组件一个主干,单主干。
13.3.1 反模式:基于分支的代码库
13.3.2 模式:每个组件一个主干
13.3.3 模式:单一主干
13.4 工作流的效率
13.4.1 加快变更
13.3.2 模式:每个组件一个主干将每个组件或服务的代码放在自己的 VCS 项目库中,可以说是使用微服务架构的团队最常用的方式。这允许人们将组件检出到本地并在上面工作,不需要关心在其他组件上已经完成的工作。当一个变更涉及修改多个组件的部分时,这个模式会面临一个挑战。检出涉及的所有组件,并在本地修改和测试它们并不难。但是当你提交这些变更时,这些组件在流水线中并不一定能“齐头并进”。如果一个更改的组件在其他组件之前到达下游阶段,就会因为它和其他组件的旧版本集成导致测试失败。
13.3.3 模式:单一主干每个组件建立自己 VCS 项目的一个替代方案是把所有的源代码保存在单个项目中。这强制整个代码库对于给定的提交来说是一致的。这也简化了保持不同组件协同工作的问题。开发者要确保他们所做的所有修改是可行的而且通过了测试,否则就不能提交修改。这种方法的挑战在于,需要采用不同的方法来实现构建和 CI 的工具,特别是针对大规模。它应该能容易地只运行与已变更代码相关的测试,而不是强制运行所有组件的全部测试套件。类似地,在变更提交后,只有已修改组件的流水线阶段是需要运行的。
13.4 工作流的效率
13.4.1 加快变更
13.4.2 代码评审
13.4.3 将治理融入工作流
13.4.2 代码评审
3.4.3 将治理融入工作流
“治理”是指确保根据相关政策进行工作的流程,从而保证效率和遵循法律。
13.5 结语
第14章 动态基础设施的连续性
本章主要关心的是生产环境中基础设施的运维质量。
我用“连续性”这个术语包罗运维质量的方方面面,其目标就是让服务不中断,持续地供用户使用。服务应该快速、正确地执行。数据应该总是可用且正确的。有恶意的人应该没办法破坏服务。如果出了问题,应该能快速检测出来并恢复,对用户的影响很小或者没有影响。
14.1 服务连续性
14.1.1 真实可用性
本章讨论的连续性包括以下方面。服务连续性在出现问题或变更时,确保最终用户能够使用服务。数据连续性在基础设施无法保证一致和可用的前提下,保证数据的可用性和一致性。灾难恢复优雅地处理最坏的情况。安全让坏人无处作恶。
14.1 服务连续性
系统组件会出故障。软件会崩溃。资源会耗尽。即使没有这些意外的问题,也会有人做变更。他们会升级系统和软件。他们会添加、删除或者重新分配资源。他们会部署新的应用并和已有的应用集成。他们会部署更新,会优化配置。服务连续性的目标是确保最终用户不会注意到这些,只有发现新功能和更快速响应的喜悦。
14.1.1 真实可用性
14.1.2 用动态服务器池做恢复
14.1.2 用动态服务器池做恢复
14.1.3 为动态基础设施设计软件
14.1.3 为动态基础设施设计软件
14.1.4 为连续性划分系统
14.2 零停机变更
14.1.4 为连续性划分系统
14.2 零停机变更
14.2.1 模式:蓝绿替换
14.2.2 模式:凤凰替换
零停机部署的基本思路就是在不中断服务的情况下变更基础设施元素。这里描述的所有模式都涉及在部署一个元素的新版本时,之前的版本仍在使用中。在真正使用新元素之前会对变更进行测试。在测试并认为它已经准备好了后,就切换到新元素上使用。之前的元素会保持运行一段时间,从而能够在新元素出现问题后快速地回滚。
14.2.1 模式:蓝绿替换
14.2.2 模式:凤凰替换
14.2.3 实践:缩小替换的范围
14.2.3 实践:缩小替换的范围
14.2.4 模式:金丝雀替换
14.2.4 模式:金丝雀替换
14.2.5 为零停机替换路由流量
14.2.5 为零停机替换路由流量
14.2.6 有数据的零停机变更
14.2.6 有数据的零停机变更
14.3 数据连续性
14.3.1 冗余地复制数据
14.3 数据连续性
如果基础设施的每一个元素都是用完可扔的,如何在这样的环境中支持这一点?有很多技巧可以解决这个问题,比如:• 冗余地复制数据;• 重新生成数据;• 委托数据持久化;• 备份到持久存储。
保留数据的一个常见的做法是确保它在多个实例之间复制,并且带冗余
14.3.2 重新生成数据
14.3.3 委托数据持久化
14.3.4 备份到持久存储
14.4 灾难恢复
14.4 灾难恢复
14.4.1 持续的灾难恢复
14.4.2 灾备计划:为灾难做计划
14.4.3 实践:优先重建而不是冷备份
拥有能够从头重建整个基础设施和服务的配置定义和脚本至关重要。然而,如果保存这些东西的地方消失了会怎样?如果失去了 VCS 怎么办?如果使用了供应商提供的 VCS,而他们关门大吉或者被入侵了怎么办?应该经常备份你的 VCS,并存储到完全不同的地方,这样就能在紧急情况下提取并建起一个新的 VCS。
14.4.3 实践:优先重建而不是冷备份
14.4.4 通过流水线持续监控
14.4.4 通过流水线持续监控
14.5 安全
14.5.1 自动掩盖危害
14.5.2 以可靠的更新作为防护
14.5.3 包的来源
14.5.4 自动加固
14.5.5 流水线中安全验证的自动化
14.5.6 变更流水线的漏洞
14.5.7 管理云账号的安全风险
14.6 结语
第15章 基础设施即代码的组织要求
15.1 演进式架构
基础设施即代码的前提是,云和动态基础设施在处理基础设施时,创造了使用全新实践和技术的机会。旧的工作方式(例如手动配置服务器)会浪费新技术的好处。同样,以旧的 IT 服务运维模型来使用云实践,也浪费了新技术和工作实践的好处。
结合云服务,基础设施即代码可以帮助组织通过可靠、高质量的服务轻松应对不断变化的需求。实现这一目标的组织原则包括:• 持续设计、实现和改进服务的方法;• 授权团队不断交付和改进服务;• 在快速持续交付的同时确保高质量和合规性。
15.1 演进式架构
演进式设计和实现的基础是能够持续、容易、安全且廉价地进行变更。拥抱这种方式的团队知道,他们不会实现完美的“最终”设计。不论如何,正确的设计是不断变化的。因此他们接受持续变更,而且能够熟练地持续变更。
15.1.1 在实战中学习
15.1.2 从先驱者流水线开始
15.2 度量有效性
15.2.1 首先对期望的结果达成一致
15.2 度量有效性
15.2.1 首先对期望的结果达成一致
15.2.2 选择有助于团队的度量指标
15.2.3 跟踪和改善周期时间
15.2.2 选择有助于团队的度量指标
下面是基础设施团队使用的一些常用指标。周期时间(cycle time)从识别一个需求到完成它的时间。该指标用来度量变更管理的效率和速度。本章后面会更详细地讨论周期时间。平均恢复时间(MTTR)从识别一个可用性问题(包括性能严重下降或者功能不可用)到解决它(可以是一个替代解决方案)所花费的时间。该指标用于度量解决问题的效率和速度。平均故障间隔时间(MTBF)发生关键可用性问题之间的时间。该指标用于衡量系统的稳定性和变更管理过程的质量。虽然这是个有价值的指标,但 MTBF 的过度优化是导致其他指标不佳的常见原因。可用性系统可用时间的百分比,通常不包括系统因计划中的维护而离线的时间。这是系统稳定性的另一种度量方式。通常在服务合同中用作 SLA。真实可用性系统可用时间的百分比,没有将计划中的维护排除在外。5
15.2.3 跟踪和改善周期时间