自动化的应用案例
在运维行业中,自动化这个术语一般用来指代通过编写代码来解决各种各样的问题。尽管写这些代码的动机以及最终产生的解决方案本身往往区别很大。更广泛地说,在这一观点中,自动化是“元软件”,也就是操作其他软件的软件。
正如我们之前暗示的,自动化有许多用例。下面是一个非详尽的例子列表:
● 创建用户账户。
● 某个服务在某个集群中的上线和下线过程。
● 软件或硬件安装的准备和退役过程。
● 新软件版本的发布。
● 运行时配置的更改。
● 一种特殊情况的运行时配置更改:依赖关系的更改。
这个列表基本上可以无限扩展。
Google SRE的自动化使用案例
在Google内部,上述所有使用案例都有,甚至更多。
然而,在Google SRE内部,我们主要负责运维基础设施,而不是管理那些穿过基础设施的数据的质量。这条分界线并不是完全清晰的——例如,我们会非常关注某个数据集在推送之后消失一半的情况,因此我们会针对这种粗粒度的差异报警。但对于SRE而言,具体修改系统中一些账户的某个子集的属性是相当罕见的。因此,自动化的情境通常是自动化管理系统的生命周期,而非系统内部的数据:例如,部署新的群集服务。
即使如此,SRE的自动化努力也与其他组织所做的差距并不大。SRE使用不同的工具来管理自动化,同时关注的重点不同(我们接下来将会对此进行讨论)。
广泛使用的工具有Puppet、Chef、cfengine,甚至 Perl都提供了自动化完成特定任务的方法,主要区别在于对帮助进行自动化的组件的抽象层次不同。Perl这种完整的语言提供了POSIX级别的接口,理论上在系统API层面上提供了一个基本上是无限的扩展范围。[17]而Chef和Puppet则提供了一些“开箱即用”的抽象层,通过对这些抽象层的操作可以直接操作服务或者其他高级对象。这里的妥协十分经典:高层次的抽象更容易管理和进行逻辑推理,但当你遇到一个“有漏洞的抽象”时,就会系统地、重复地甚至不一致地出现故障。例如,我们经常假设,将一个新的二进制文件发布到集群中是原子性的;该集群最终会全部变成新版本,或者全部维持旧版本。然而,现实中的行为很复杂:集群网络中途可能会发生故障;物理机可能发生故障;与集群管理层的通信可能会失败,使系统进入不一致的状态;视具体情况不同,新的二进制文件可能安装了,但没有推送,或者推送了但是没有启动,或者启动了但是无法验证。没有几个抽象模型能够成功地模拟这些结果,大部分模型都会中止并要求人工干预。而那些真正糟糕的自动化系统甚至都不会这样做。
SRE在自动化领域有一系列设计哲学和产品,它们中的一些类似于一种不会特别详细地对高层次实体建模的通用部署工具,另外一些则类似于在非常抽象的层次上描述服务部署的语言。后者往往比前者更加通用,更符合通用平台。然而,我们生产环境的复杂性有时意味着前者是更容易采用的选择。
自动化分类的层次结构
虽然所有这些自动化步骤都是有价值的,同时自动化平台本身也是很有价值的。在一个理想的世界里,我们不需要任何平台之外的自动化进程。事实上,构建一个完全不需要胶合逻辑的系统要比有一个依赖外部的胶合逻辑的系统更好,不仅仅是因为内部化效率更高(尽管这样的效率提升很有价值),而是因为设计中将胶合逻辑排除在外了。这样做需要将胶合逻辑的具体用例—一般来说是对系统的直接操作,例如添加账户或执行系统集群上线—用某种方法在应用程序中直接处理。
这里提供了一个更详细的例子,Google的集群上线系统自动化经常出现问题,因为这些最终是在核心系统之外维护的,因此经常受到“代码腐烂”(bit rot)的影响。也就是说,当基本系统变化的时候,上线自动化系统没有随之改变。尝试将两者(集群上线自动化系统和核心系统)更紧密地连接起来的努力常常会由于两个团队不一致的优先级定义而失败。产品的研发人员会—不能说不合理的—抵制对每一次改动都进行一次测试部署的要求。其次,关键性的,但是不经常执行的,以至于很难测试的自动化系统尤其脆弱,因为反馈的周期很长。集群故障转移自动化是一个经典例子:故障转移可能每隔几个月甚至更长时间才发生一次,导致每次执行都不一致。自动化的演进遵循以下路径:
1)没有自动化
手动将数据库主进程在多个位置之间转移。
2)外部维护的系统特定的自动化系统
SRE在他或她的主目录中保存了一份故障转移脚本。
3)外部维护的通用的自动化系统
SRE将数据库支持添加到了每个人都在使用的“通用故障转移”脚本中。
4)内部维护的系统特定的自动化
数据库自己发布故障转移脚本。
5)不需要任何自动化的系统
数据库注意到问题发生,在无须人工干预的情况下进行故障转移。
SRE讨厌手动操作,所以我们尽力创造不需要他们的系统。然而,有时手动操作是不可避免的。
同时,相对于在特定系统相关配置上变更的自动化,另外一种自动化是面向整个生产领域的变更。在Google这种高度集中的专有生产环境下,有大量的跨特定服务范围的变更存在—比如,对上游的Chubby服务器的变更,使访问更可靠的一个Bigtable客户端库的功能开关的变更等—这些变更也需要安全地管理,在必要的情况下进行回退。当变更数量超过一定量之后,这种全生产范围内的变更就不可能手动完成了,即使在这之前,对一个变更很小或者通过基本的重启+检查就可以完成的流程进行人工监督是毫无意义的。
下面让我们使用内部案例研究来详细描述上文提到的这些要点。第一个案例研究的是如何利用有远见的工作来成功地实现了SRE自我标榜的涅槃:通过自动化将SRE从整个流程中消除。