多年来,基础设施即代码(Infrastructure as Code,IaC)一直是一种趋势。它通过定义相关标准,以及推出各种新的方法与工具,来尽可能地自动化我们的各项日常任务。例如,Ansible、Pulumi、Terraform等,都是我们耳熟能详的该领域自动化工具。由于每种工具都各有着各自的优缺点,因此,我们选择起来并不容易,而且往往需要团队通过协作,来识别、测试和定义正确的工具。毕竟此类协作的成功关键就在于,能够确保各个团队成员参与到IaC项目中,进而实现适当的自动化流程。
除了由工具选择所带来的挑战,定义项目的架构也并非易事。单存储库与多存储库各有利弊,它们能够在不同应用场景中,简化IaC项目架构的参与与协作。下面,我将和您深入讨论如何在不同的环境中,使用不同的自动化工具,来开启IaC项目。
什么是IaC项目?
基础设施即代码表示在描述性模型中,管理包括:云架构、网络、虚拟或物理服务器、以及负载平衡器在内的任何基础设施组件。由于属于基于DevOps软件开发的重要实践,因此它强调的是那些用于置备和更改系统配置的一致性、可重复的例行过程。类似于相同的源代码能够生成相同的二进制文件,IaC模型也会在每次应用时,生成相同的环境。可见,IaC是一种通过机器可读的定义文件,来提供、配置和管理IT基础设施的方法。据此,我们可以轻松地对整个基础设施的状态,进行版本控制。
总的说来,IaC项目具有如下主要优势:
- 提高速度:通过快速设置完整的基础设施,让软件开发的生命周期更加高效。
- 提高一致性:具有可重复性、一致性的自动化流程,可以避免各种手动错误。
- 降低成本:IaC通过良好的云计算能力和自动化策略,降低了项目在硬件、操作人员、物理资源等方面的花费,进而大幅降低了基础设施管理与维护的成本。
当然,IaC及其配套的工具与项目架构,并非DevOps团队独享,它也能够为公司内的其他工程师赋能,提高协作水平,这也是IaC成功的关键。
如何启动IaC项目?
作为一个灵活可选的架构,IaC需要根据不同的“上下文”,通过不断迭代,来提高项目的效率。也就是说,IaC项目不一定在首次就能被正确定义,它需要通过持续迭代,才能适应本公司的工作方法。下图展示了一个典型的项目目录结构。
以下是针对上述目录架构的简单解释:
- Root是项目的入口,它包含了诸如:README、CONTRIBUTION等项目主要文档,以及跟踪每次更新的CHANGELOG文件。
- Dist是一个由自动化脚本自动创建的可选文件夹,可用于配置本地环境,以便加入项目中的任何角色。例如,它可以将符号链接集中式地存储到“extra-tools”文件夹中,以及那些由IaC项目使用的二进制文件。
- Docs存放了更多文档,以便将带有代码源的文档集中起来,以进行版本控制并保持同步。
- Extra-playbooks是一个可以自动下载外部playbook的文件夹。它有效地分离了内、外部资源,以便区别哪些代码可被更新,哪些不可以。
- Extra-tools是一个文件夹,其中包含了用于管理IaC架构的每个工具的二进制文件。如果它被设置为本地,则可以方便任何角色按需使用它来运行各种操作。
- Inventory是自动化工具共享全局信息的位置,可为不同环境中的每一种资源进行编录。
- Playbooks是项目团队开发的内部playbook的位置。
- Plugins是由自动化脚本创建的可选文件夹,可用于配置本地自动化工具,以便扩展其功能。
- Provision是用于提供基础设施的自动化代码的位置。它可以是云端、或是诸如Terraform、Pulumi等本地资源、以及Vagrant、Docker、Kubernetes等本地测试环境(下文会提到)。该文件夹按照不同的工具可分为多个子文件夹,以便项目团队轻松地识别并管理置备的工具。
- Roles是playbook用来配置提供资源的不同角色的具体位置。
因此,这样的目录架构可用来在逻辑上,将置备(provisioning)代码与配置(configuration)代码分开,以便在同一个项目内,轻松地实现完全的自动化,且无需管理多个存储库。例如,团队可以使用Terraform去置备某个虚拟机,并使用Ansible等本地置备程序自动配置它。
如何进行团队合作
常言道:“一个人可以走得更快,但一群人才能走得更远。”可见,协作是成功的关键。以团队形式开发IaC项目,可以避免出现其他人无法理解的架构,或是选择了错误的自动化工具。值得注意的是,工程团队中的任何人都应该使用IaC项目,来自动化其流程。毕竟,DevOps方法论的主要目标,就是要缩小运维与开发人员之间的差距。而IaC项目可以通过每个人的参与,来协助实现这一点。
显然,由不同团队开发的IaC,需要项目管理人员将其划分为不同的路线图、任务、子任务,并随着时间的推移,持续跟踪进度。因此,相比掌握如何管理项目,团队更应该了解如何轻松地实现协作。
版本代码
与其他软件项目类似,IaC项目也离不开版本控制。从概念上说,版本控制是随着时间的推移,跟踪和管理源代码的更改,以防止关联性任务发生冲突的一种实践。同时,它也能够通过发布管理,按需快速回滚到过往的版本。
其中,版本规则(convention)必须事先定义和自动管理一个持续的管道,以实现对存储库、状态文件、以及bucket进行自动标记。下图展示了一个IaC项目的简单版本规则:
- MAJOR的版本变化发生在引入重大更改时。例如,自动化工具的某次升级,可能会更改API的行为,或需要重写代码。
- MINOR的版本变化发生在需要以向后兼容的方式添加功能时。例如,添加新的角色、引入新的工具等。
- PATCH的版本变化发生在需要针对向后兼容的错误,进行修复、或格式设置时。
使用带有显式名称的分支
在开发方面,IaC项目应该遵循的另一个的实践是分支的使用。在源代码控制软件中,人们可以使用分支,将代码从生产环境版本中分离出来,用以修复错误、或添加功能。因此,分支方便了用户对开发代码执行更改,而不会对生产环境或其他成员的工作,产生影响。
值得注意的是,我们需要在创建分支时,就使用明确的名称,以确保其他成员可以顺利地引用,并快速了解到该分支是否仍在开发中。通常的做法是,使用当前任务的单号来命名分支,以便快速地参考项目管理器的标识符。
此外,我们还需要维护生产环境代码的主分支和每个子环境的专用分支。为此,我们可以定义一个工作流,让其首先在开发环境(分支)中部署每个更改,然后在缓存环境(分支)中部署更改,最后在生产环境(主分支)中发布更改。
写入显式提交消息
运营团队应该通过管控好提交消息的格式,来确保大家能够更好地理解发生的更改。为了能够从每次更新中提取到实用的信息,我们需要定义显式的提交消息规则。下图的规则示例是由可用于分析项目、并快速了解成熟度的信息所组成。它包括:类型(Type)、范围(Scope)和摘要(Summary)三个组成部分。其中,类型定义了提交的全局目的,范围定义了项目的哪个子组件会受到影响,而摘要则限定80个字符来快速描述更新。
- 文档(Docs):属于更新类文档,类似README文件。
- 功能(Feat):向项目添加新的功能。
- 修复(Fix):修复错误的代码更新。
- 重构(Refactor):对不引入新功能的代码予以更新。
- 格式(Format):代码的纠错(linting)。
- 测试(Test):单元测试中的代码更改。
- 持续集成(Ci):持续集成过程中的代码更改。
在规则上,我们需要使用较小的提交方式,以便轻松地找到待使用的提交类型。如果您无法确定待使用的模式,则需拆分成多个提交。您可以参考一个名为git-semantic-commits的Github项目。它展示了在命令行中自动创建提交消息的格式。
为了确保每个贡献者都能够遵循该格式,我们可以将预提交(pre-commit)规则运用到任何源控制器的软件上。毕竟,提交消息对于多人协作的项目是非常重要的。如果使用得当,它可以在许多方面提供帮助,特别是在错误修复和回滚过程中。
查看代码
在团队协作过程中,代码审查也是一个重要的环节。为了保证软件质量,团队会通过查看和阅读IaC的部分代码,来发现潜在的错误,进而决定是继续还是中断实施。一个基本的流程应当至少经过一次批准,才能在主分支(又名生产环境)中进行代码的合并。
促进项目的启动(On-Boarding)
贡献者们只有在理解了项目的基本概念、各项优秀实践、以及如何提交首次更新的基础上,才能通过协作参与,来启动项目。而影响IaC项目启动的先决条件还包括:文档的质量、代码的质量、本地环境的设置、以及开发更新所需的时间。毕竟,设置新的环境是需要时间的,它涉及到安装、更新和配置工具,下载依赖项,以及配置文件等。为了便于IaC项目的贡献者更容易地实施,我们可以利用自动化工具,来完成各种所需的“基本(base)”配置,以便每个成员都能共享到相同的本地环境配置(如:工具版本、依赖项等)。
当然,我们无需临时为设置环境而花时间研究如何使用正确的版本或命令,只需运行一个playbook,即可准备开启IaC项目。例如,我们可以将架构交由Ansible管理,以确保能同时安装Python、Terraform、Kubectl、Helm、以及Mitogen等,进而轻松地配置Linux和MacOS等多个环境。
可用工具速览
下面,我们一起来简单谈论一下,那些在启动IaC项目时,值得特别关注的工具。
使用Terraform进行配置
Terraform是由HashiCorp开发的开源工具。它允许DevOps工程师以编程的方式,提供运行应用程序所需的资源。由于是基于HashiCorp语言(又称HCL),因此它允许任何人通过横跨多个的云服务、或本地数据中心,以配置和重配的方式,来轻松地维护整个基础架构的状态。面对不同的配置器和模块,Terraform能够管理应用程序所需的几乎所有资源。
Terraform虽然旨在为项目保持最新的状态,并同时共享多个状态,但如果未能正确地遵循DevOps流程的话,团队合作可能会随着时间的推移,而变得繁琐且复杂。对此,我们可以借用外部工具Atlanti,在Terraform项目中针对任何更新,来轻松地管理代码审查和自动合并。当然,它也可以被用在将代码投入生产环境之前,捕获各种错误与缺陷。
正如测试是DevOps方法的重要组成部分那样,它对于IaC项目的重要性也不言而喻。我们可以采用一个名为Terratest的工具,对自动化的Terraform资源开展测试。这是一个由Gruntwork开发的Go库,可以为带有Terraform的IaC,由Amazon、Google等IaaS平台提供的Packer(下文将提到),以及Kubernetes集群,创建和自动化各种测试,并且能够添加自动化的管道。
使用Ansible进行配置
Ansible是一种为跨平台主机,提供强大的自动化支持工具。任何IT专业人员都可以使用它,来管理应用程序的部署、工作站和服务器上的更新、云服务的分配、配置管理、以及系统管理员的日常事务。凭借其幂等性、以及灵活的组件配置能力,Ansible显著地提高了IT环境的可扩展性、一致性和可靠性。
Ansible能够通过与Terraform的耦合,实现对任何应用所需的物理资源的轻松管理。与其他编程语言类似,Ansible能够定义各类文件在投入生产之前,必须经历的测试和审查。目前,我们可以使用Molecule和Ansible Test,两种不同的工具来实现自动化。它们都具有很好的易用性,可以在Ansible的各种playbook上运行单元测试,以实现在审查代码之前,验证其行为。
为了提高Ansible的性能,我们可以在Ansible中集成一个名为Mitogen的Python库,以大幅降低Ansible在运行各种playbook时产生的压缩和流量。它非常适合那些基于Ansible的IaC项目。
此外,专注于编程语言方法(programmatic language approach)的IaC工具--Pulumi,可以为IaC项目提供更好的灵活性,并让开发者能够按需轻松地更改各种方法、架构或工具。因此,如果您熟悉Python、Go等编程语言的话,可以试用该工具。
在虚拟环境中以本地的方式运行代码
如前所述,IaC项目可以被视为应用开发项目中的一种,应当遵循定义开发文件、以及测试等步骤。通常,我们首先应在本地测试更新,然后在开发或测试环境中进行测试。对此,DevOps工程师可以使用Vagrant、Docker、Podman、Buildah、Minikube、Kind、以及MicroK8s等工具,来模拟特定的环境,以测试IaC项目的各个部分。例如,作为开源工具,Vagrant可以创建一个虚拟环境(例如基于Virtualbox),来测试软件在某个特定系统上的部署状况。Docker、Podman和Buildah可以被用于在容器环境中,执行相同的操作。而Minikube、Kind、MicroK8s也可被用于在本地的Kubernetes集群中,执行相同的操作。通过这些不同的方法与用例,我们可以轻松地在IaC项目中开展测试,并以主动的方式解决潜在问题,而非被动地采取反应。
使用Packer构建自己的镜像(可选)
IaC项目通常是由与计算资源有关的“基本(base)”配置文件所组成。基本配置文件、或称通用配置文件,是自动化工具需要应用于计算资源之上,以确保跨资源一致性的角色列表。例如,基本配置文件可以包含:root密码、NTP服务器、SMTP服务器、以及监控工具的部署等的配置信息。
不过,在IaC项目中,基本配置文件有时也会拖慢新的主机的启动时间。为此,我们可以使用一个名为Packer的开源工具,以编程的方式,通过创建操作系统的自定义基本镜像,来减少基本配置。Packer是一个由HashiCorp开发的开源工具,可用于从单个配置源,为多个平台创建相同的主机镜像。我们可以上传已创建的镜像,以供云端、或本地的虚拟化编排平台(orchestrator platform)使用。
前文提到的Vagrant,可以在本地使用Packer,并根据定制的镜像定义,去生成虚拟机,进而在本地测试IaC项目的指定部分。这对于改进自定义资源的部署十分有益。当然,是否确实需要这样做,则完全取决于基础设施的实际要求。
在本地模拟云服务
在生产环境中开展代码测试之前,我们可以使用一些工具,在本地模拟云服务。这比为了测试某段代码而生成整个环境,要更加节省IaC的项目成本。
AWS用户可以使用一个名为LocalStack的强大工具。它可以被轻松地部署在本地虚拟环境(如:虚拟机或容器)中,模拟多个AWS端点,进而在本地测试Terraform或Ansible代码。
而对于GCP用户而言,则可以使用gcloud命令、及其各种实验性的功能,临时模拟出有限的端点。
小结
综上所述,我们从IaC项目的基本目录结构,团队合作,代码的版本管理,名称规则,提交消息的格式,如何查看代码,启动项目,以及各种实用工具等方面,向您全面地介绍了开启一个基础设施即代码项目。如果您想深入了解IaC的相关知识,请参阅如下链接:
原文标题:How to Start an Infrastructure as Code Project,作者:Nicolas Giron