随着云计算的逐渐流行,创建和管理诸如虚拟服务器、网络、存储、负载均衡等基础设施的方式已然发生转变。传统的手动或者脚本管理方式虽然能够应付数台服务器这种少量使用场景,但是对于多则成百上千的大规模服务器数量来说,显然不再适用和高效。为此,我们需要一种能够自动化的、可重复的以及可靠的创建和管理云基础设施的方法。来自 Google(谷歌)、Amazon(亚马逊)、Netflix(网飞)等互联网公司的做法表明,基础设施即代码正是用来解决此类问题的最佳实践。那么,究竟什么是基础设施即代码呢?

什么是基础设施即代码

基础设施即代码,其对应的英文为 Infrastructure as code,意指通过编写并执行代码来定义、部署以及更新基础设施。采用基础设施即代码,需要我们转变过去的思维,将云主机、网络(包括路由、防火墙)、存储等所有基础设施都当作软件来对待,从而能够有效利用软件开发的良好实践。使用源代码来表示基础设施,不仅可对其进行编程处理,而且能版本化、共享、重用、调试,甚至在出现错误时还可能还原。对于在软件开发生命周期中进行的代码评审、自动化测试、CI(Continuous integration,持续集成)和 CD(Continuous delivery,持续交付)等活动,也可以同样应用到基础设施上。因此,我们就能创建更加容易追溯、监视和调试的服务运行环境。

基础设施即代码的价值

所有的云计算平台都无一例外的提供了 Web 操作界面。对于大部分人而言,通过 Web 操作界面只需要点点鼠标即可创建基础设施。显然,它看起来非常容易使用。那么,我们为什么不推荐这种手动管理基础设施的方式呢?这是因为手动管理方法一般具有下列弊端:

  • 十分容易出错。仔细回想一下,你上次手动创建基础设施犯错是什么时候?是不是才没过几天?
  • 很难创建多个相同且一致的环境。每一个环境都很特殊。它们的配置各不相同。久而久之便成了雪花服务器。这些服务器脆弱不堪,一触即崩。“标准”二字在他们的字典里根本就没有存在过。
  • 非常耗时。虽然这是手动操作所需付出的代价之一,但是我们实在没有必要为此浪费大把的时间,毕竟我们还有更好的选择。
  • 想要保持环境最新真的是难。给老掉牙的系统打补丁?拜托别碰,你可能会陷入“依赖地狱”。
  • 最重要的是你的基础设施无法像收银小票一样长期保留下来。它只散见于几篇过时的文档或某一时刻的大脑中。

而使用基础设施即代码这种实践将带来多方面的好处,我们认为它最重要的价值在于:

  • 版本控制

    我们可以将用来定义基础设施的代码存储在版本控制系统(如 Git)中。一方面,从提交的版本记录我们可追溯基础设施从创建到更新的整个历史过程;另一方面,假如基础设施遇到故障,那么我们便能根据已有的历史记录进行排查。此外,利用版本控制系统,我们甚至还能回滚具有问题的基础设施,从而将其还原到正常状态的版本。

  • 自动化

    执行定义的基础设施代码通常是自动化完成。显然,它比在 Web 界面中通过手动点击按钮来创建基础设施的过程要快。同时,它也更安全,手动操作一般容易导致人为错误;而自动化过程则更加一致且可重复。

  • 重用

    通过把定义基础设施的代码打包成模块,我们从而能够将其变成可以重复使用的组件。对于开发、测试及生产环境中的同类型基础设施,我们无需从头开始构建,只需加以重复利用。因此,重用不仅可以节省我们创建基础设施的时间,而且经过测试的模块也将使基础设施更加可靠。

  • 可执行的文档

    从传统上讲,创建基础设施的过程要么被记录到文档中,要么存在于某个运维专职人员的大脑里。使用文档的问题是,它总是容易过时,而且维护它需要耗费大量的时间。而将特定技术锁定在专职人员身上有时则让情况更加严重,假如该名人员不在工作岗位上,那么将没有别的人知道如何创建基础设施。如果我们将基础设施通过代码的形式定义,那么团队中的每一个人不但都可以查看或评审这些代码,而且还能直接予以执行。

周而复始的手动管理基础设施,时间长了难免不变得枯燥和乏味。如此工作既无创意,也无挑战。通过基础设施即代码的方法在改进我们工作的同时,让我们专注于从事更有价值的事情。

基础设施即代码的工具

我们已经看到了采用基础设施即代码具有巨大的优势。然而,我们如何才能实现它呢?根据 Yevgeniy Brikman(叶夫根尼•布里克曼)的说法[1],如果你想要实现基础设施即代码,那么至少包括以下几类工具可以选择使用:

  • 脚本

    通过编写脚本来自动化管理基础设施,这是最直接,同时也是历史最悠久的方式。在早期,用来编写脚本的语言通常以 Shell 为主(如 GNU Bash),但后来更加通用的编程语言(如 PerlPythonRuby 等)也加入了进来。使用脚本的好处是简单且上手相对更快,一般可以利用熟悉的编程语言来编写。然而,其缺点也非常明显,除了要编写大量的定制化代码之外,后期的维护更是颇成问题。

  • 配置管理工具

    当下主流的配置管理工具包括 AnsibleSaltStackChefPuppetCFEngine 等等,这些工具用来在现有的服务器上自动安装并配置软件。与脚本相比,一方面,使用这类工具通常采用描述或声明式的 DSL(特定领域语言)来编写。由于不再需要学习专门的编程语言,所以在使用难度上大为降低。

    另一方面,使用脚本来实现幂等通常较为困难,而通过配置管理工具却能轻易实现。所谓幂等,就是说不管代码执行多少次,其最终行为都将是正确的。例如,假设我们想要为 /etc/hosts 追加一行条目,如果使用脚本,那么每次执行可能都将添加相同的内容,最终导致这些内容重复存在于文件中。经验和教训告诉我们,编写仅仅工作的脚本很容易,但要编写好好工作的脚本却十分困难。相反,使用配置管理工具则不会存在这样的问题。这是因为它们会根据描述或声明的状态进行判断,若该文件没有这行条目则添加,反之则什么也不做。

    此外,脚本一般在单机上执行,而且临时脚本通常用完即弃。配置管理工具则往往针对分布式执行而设计,能够同时管理大量的远程服务器。

  • 服务器模板工具

    代替在现有的服务器上安装和配置软件,我们也可以直接将预装好的环境打包成服务器模板。这种模式被称为不变基础设施模式,该模式现在已经得到了越来越多的采用。

    一般用来制作服务器模板的技术包括容器化技术和虚拟化技术,而相应的工具则有 DockerPodmanPackerVagrant 等等。通过这些工具打包好的服务器模板称为镜像,将镜像进行部署后最终成为运行的实例。

    不变基础设施模式的惯用做法是,从来不对实例做任何变更。但是,当不得不进行变更时,则从服务器模板创建新的镜像。另外,如果运行的实例出现故障,那么也不用对它进行修复,而是将它抛弃,并根据镜像重新部署新的实例。

  • 服务器准备工具

    无论是配置管理工具,还是服务器模板工具,它们定义的代码都针对现有的服务器运行。与它们不同的是,服务器准备工具则用来创建服务器本身。这类工具包括 TerraformAWS CloudFormationOpenStack Heat 等等。

本书将专注于介绍 Terraform,根据我们长期观察,Terraform 是目前用来编写基础设施即代码的最佳开源工具之一。我们喜爱 Terraform,不仅因为它支持 Amazon Web Services(AWS)Google CloudMicrosoft AzureDigitalOceanLinodeVultr阿里云腾讯云等市场上广泛的云供应商,而且也在于它的生态越来越成熟。


  1. https://blog.gruntwork.io/a-comprehensive-guide-to-terraform-b3d32832baca ↩︎