一文搞懂基础设施即代码 (IaC)_软件工程

基础设施即代码(Infrastructure-as-Code,IaC)意味着使用代码来定义和管理基础设施,而不是使用手动流程。更重要的是,IaC是将软件工程原则和方法引入云基础设施。本文将探讨IaC的基础知识以及如何设置相关环境。

PART 01  

IaC简介

在IaC之前,基础设施是(某些情况下现在仍然是)通过简单操作用户界面、批处理脚本和配置管理工具等方法提供的,这些方法并不适用于当今的云计算。

同样,当下很多所谓的IaC其实很大程度上更接近于“基础设施即文本”。作为以结构化文本编写的基础设施,它是可重复并且可以进行版本控制的。但是,在实施需要与应用程序代码一起使用的软件工程时,它就无法胜任了。例如,无法支持标准开发工具、测试框架或包管理。

真正意义上的IaC方案需要使用专为云上基础设施设计的平台,从而使标准软件工程实施方案和工具都能够得以应用。

IaC为什么非常重要?

IaC之所以重要,主要有三个原因:

一是当下企业向云的全面迁移。越来越多的工作负载正在从本地数据中心迁移到云端,并且这种趋势会一直持续下去。然而,云计算本身并不是能够保证和维持基础设施可靠而又可扩展的灵丹妙药。与物理数据中心一样,云基础设施的脚本集也可能存在不一致、文档记录不充分等情况。由于IaC是强制执行经过验证的工程实施步骤,从而能够将混乱的状况整理得秩序井然。 

二是公众使用云的方式更加复杂。商业用户尝试改变设施、模式和工作方式,以改善收益。IaC不只是简单的资本支出与运营支出,而是关乎如何整合构成工程生命周期的所有因素,例如版本控制和测试,以释放云可以提供的所有价值。它能够使用工程实践来充分挖掘云计算的潜力,从而更好更快地推动创新进而推动公司业务。 

三是管理云上基础设施的负荷不断在增加。可用的云服务种类每年都在增长,越来越多的公司正在采用现代云设施(比如容器或无服务器设施)。这些设施往往包含许多松散耦合和相互依赖的组件,从而导致工程师必须管理的云资源数量以惊人的速度增长。这当然是一件好事,因为这意味着商业用户正在从云上获得更多收益,推动了公司业务发展,但结果是云资源的复杂性和规模不断增加。  

例如,从云上获取收益的方法之一是充分利用云供应商提供的越来越多的服务。这些服务可以推动创新并加快业务进展。但同时,每一项新服务都会带来新的API,这会增加基础设施的复杂性。

随着云资源规模和复杂性的增加,现代的IaC方法就是亟需的了。它可以帮助工程师构建、部署和管理基础设施。如果工程师管理的资源介于1到10个之间,那么简单的点击就可能能正常工作;当管理10到100个资源时,“基础设施即文本”或旧版IaC工具可能仍然能胜任。

但是一旦资源数目到了成百上千或成千上万时会发生什么?这在今天并不罕见!最重要的是,这成千上万的资源不是每月更新一次,而是每天更新多次。管理好这一切的最佳途径是将用于应用程序代码的相同软件工程实施方案和工具落实到位。

思考下列问题:

(1)如何确保我的基础设施能够快速扩展、更改和发展,以支持业务并创造竞争优势?

(2)如何保持云基础设施以及对其任何更改的可见性?

(3)如何制定策略和数据护栏来确保安全性和可靠性?

(4)如何通过更好的协作和流程,最科学地授权我的团队构建、部署和管理基础设施?

要解决以上问题需要一种现代的IaC方法。现代的IaC方法是充分挖掘云计算潜力的方式。

PART 02  

使用IaC的重要注意事项 

IaC平台的选择至关重要。如果使用者意欲使用已有的标准软件工程工具和操作,那么在选择时就要注重以下特点: 

1.标准语言

对标准语言的良好支持,意味着开发人员可以方便地使用相同的应用程序代码语言来定义和配置基础设施,例如TypeScript、Go、Python和C#等常用语言。很多旧版的IaC工具使用自己的域特定语言 (DSL),这可能会导致一些问题,比如开发人员经常发现缺少常见的编程设施。

在所选择的平台上,工程师应该能够轻松创建强类型化、设施化的配置,并使用他们一直所依赖的功能,例如循环、常量和函数。并且,使用标准语言的另一个优势是开发人员对此早已熟悉,他们可以立即开始编码。若是需要再去学习DSL的特性和局限性,大概是一件既耗费时间又令人沮丧的事情。

2.标准开发工具

使用标准编程语言意味着开发人员还可以使用标准开发工具,例如IDE。一个优点依然是熟悉程度,开发人员可以在他们习惯的环境中工作;另一个则是开发人员得以在一个能轻松编写、调试、测试和部署代码的环境中大显身手。

3.测试框架

与应用程序一样,对基础设施进行彻底的测试非常重要。合格的IaC 平台应当支持标准测试框架,还应该能够帮助团队扩展其执行的测试类型。

标准运维测试侧重于验收测试。这意味着运维团队在云中启动基础设施,然后测试它们以查看是否完整无误。毫无疑问,如果它没有正确启动,运维团队需要将其销毁并重新部署。但这并不是一个最佳方法,因为可能不应该发生的事情已经发生了,这取决于团队的反应速度。合格的IaC平台应当通过部署前和部署期间的频繁测试来帮助团队“转移风险”。如果上述步骤还没有执行,那么团队应能使用IaC平台执行以下类型的测试:

(1)单元测试

单元测试单独评估基础设施的行为。外部依赖项(例如数据库)被替换为模拟,以检查资源配置和响应。之所以使用模拟是因为来自云服务供应商的响应是众所周知的并经过测试的。测试者已经知道给定一些参数后供应商将如何响应。

单元测试在内存中运行,没有任何进程外调用,这使得它们非常快。在开发过程中可以使用它们进行快速反馈循环。单元测试确实可以帮助开发人员在基础设施生命周期的早期解决问题。

(2)集成测试

集成测试(也称为黑盒测试)单元测试之后进行,它采用不同的方法。集成测试部署云资源并验证它们的实际行为——当然是在一个临时环境中。临时环境是模拟生产环境的短期环境。它通常很简单,且只包括正在测试的代码的第一级依赖项。集成测试完成后,可以销毁临时基础设施。

(3)安全测试

很多时候,安全测试被留到最后一刻,或者当做是“完成”的代码扔给安全团队,他们被排除在整个开发过程之外实际上,这种思路可以说是“自寻死路”。

现代IaC平台应该加密敏感的配置数据,并使遵循标准的安全实施(例如密钥轮换)能够顺利执行。还要检查平台是否加密了状态元数据,并确保机密值永远不会以纯文本形式公开。该平台还应与云提供商提供的安全服务能够轻松无障碍集成。

此外,与其他类型的测试一样,IaC平台应该帮助开发人员将自己编写的安全测试添加到工作流程中。正如尽早对代码实施单元测试一样,你也应该尽早测试以发现安全问题。这些测试属于 CI/CD 管道,因此基础设施在发布之前会进行彻底的漏洞测试。

4.创建可重用组件

可重用组件意味着开发人员可以从单个组件中构建更高级别的资源。有了它们,工程师就能够创建可以在其他地方重用的有用抽象。这些组件可以使用公司内部的最佳实践方案来编写,并在内部和社区内共享。使用可重用组件有助于创建可重复、可靠的基础设施。所以,要认真研究你正在考虑的平台能否轻松创建这些组件。

5.标准包管理器

如若创建可重用的组件,则需要一种方法来打包它们,以便可以轻松实现共享。除了使用标准工具外,还需要对标准包管理器的支持。例如,开发人员可能希望将组件放入 GitHub存储库并通过NPM发布。那么IaC平台应该能够轻而易举做到这一点。

6.创建行为可见

为便于明确责任和相互协作,所有基础设施资源的集中可见,更迭变化的历史视图可见,这些都很重要。开发人员选择的平台应该具备日志审核以及云资源更改时差异可见的能力(类似于团队使用Git等协作工具的方式),从而为开发人员提供整个基础设施的可见性。此外,该平台还应该可以设置细粒度的控制,以便控制哪些用户可以访问和更改基础设施。

7.支持多个云供应商

并非每家公司都希望使用多个云供应商,但这是应该考虑到的事情。如果开发人员想要保留多个选项,那就选择不会局限于单个云供应商的IaC平台。

8.策略即代码

另一个经常被忽视的IaC方面是策略即代码。现代IaC平台应该允许开发人员将软件工程原则和方法应用于自己的策略,就像它对基础设施所做那样。策略即代码的好处与基础设施即代码的好处大致相同。策略会在安全性、合规性以及成本控制方面持续实施组织的云治理。策略是明确的,可以使用标准语言和工具编写,可以进行版本控制、测试并最终集成到 CI/CD 管道中,从而使所有基础设施都遵循公司的最佳实施方案。

PART 03  

基础设施即代码工具 

许多开源IaC工具可用于自动执行资源分配、部署和管理。使用的关键在于正确选择适合自己的基础设施自动化工具。以下是常见的IaC类别和工具:

一文搞懂基础设施即代码 (IaC)_基础设施_02

PART 04  

使用Terraform实施基础设施即代码 

Terraform是一个不受平台所限平台的开源工具,它允许开发人员将基础设施编写成为声明性配置文件。Terraform支持众多的云供应商,使得开发人员能够在AWS、Google Cloud、Azure和Oracle等主流云平台中配置资源。


一文搞懂基础设施即代码 (IaC)_开发人员_03


借助Terraform,工程师可以快速扩展基础设施资源的配置。自动化的部署过程能够提高组织中开发团队的工作效率,从而使他们可以更改部署基础设施。并且Terraform有助于减少对于集中式基础设施团队的依赖,使开发团队能够更快地行动,缩短业务功能耗费的周期时间。 

使用 Terraform 配置资源,请使用以下命令:

一文搞懂基础设施即代码 (IaC)_开发人员_04

使用Terraform模块创建可重用的基础设施

Terraform模块的概念很简单——开发人员可以在模块内编写代码,并在整个代码库的多个位置重用它。使用Terraform模块,只需几行代码就可以快速构建基础设施。随着基础设施的不断繁衍,开发人员需要在不同的环境(如开发和过渡期)中部署相似的资源,谁也不希望反复多次地复制粘贴相同的代码。

Terraform模块更易于阅读。它们强制执行最佳实施方案,开发人员不会在Terraform文件中进行硬编码。为使模块可以被不同的团队重用并适应各种实例,需要使其可配置。并且能够将附加参数传递给环境的多个资源。由于是经过严格测试和完全记录的集中式模块,因此Terraform非常可靠。

对于最佳实施方案来说,应当开始将基础设施视为可重用的模块。Terraform模块能够促进代码的重用,避免重复,并有助于在组织内部共享模块。使开发人员可以有更多时间精力来提高集中式可重用模块的质量。

示例代码:

下面是使用Terraform模块在各种环境中创建AWS S3存储桶所需的步骤。首先,我们使用AWS与所需资源进行交互。以下代码配置AWS提供者:

1 terraform { 
2 required_providers {
3 aws = {
4 source = "hashicorp/aws"
5 version = "~> 4.9"
6 }
7 }
8 }
9
10 provider "aws" {
11 region = "us-east-1"
12 }

现在创建一个用于配置S3存储桶资源的Terraform模块:

1 resource "aws_s3_bucket" "s3-bucket" { 
2 bucket = var.bucket
3 policy = var.policy != null ? var.policy : null
4 tags = merge(var.tags, { Name = "${var.bucket}-bucket" })
5
6 server_side_encryption_configuration {
7 rule {
8 apply_server_side_encryption_by_default {
9 sse_algorithm = "AES256"
10 }
11 }
12 }
13

14 dynamic "lifecycle_rule" {
15 for_each = var.expire-days > 0 ? [var.expire-days] : []
16 content {
17 id = "expire"
18 enabled = true
19 expiration {
20 days = var.expire-days
21 }
22 }
23 }
24 }

该模块支持各种参数,如存储桶、策略、过期日以及标签:​

1 variable "bucket" { 
2 description = "S3 Bucket Name"
3 type = string
4 }
5
6 variable "policy" {
7 description = "Optional S3 bucket policy to apply. Should be a valid JSON string"
8 type = string
9 default = null
10 }
11
12 variable "expire-days" {
13 description = "If set to positive number, lifecycle policy for expiring the objects after specified number of days will be attached to the bucket"
14 type = number
15 default = 0
16 }
17
18 variable "tags" {
19 description = "Common tags to be applied to all resources"
20 type = map(any)
21}

由于已经创建了可重用的S3模块,我们现在可以从各种环境(如dev或live)调用该模块并传入所需的变量。

1 module "dev-dzone-bucket" { 
2 source = "../modules/s3-bucket"
3 bucket = "dev-dzone-iac-bucket"
4 policy = null
5 expire-days = 7
6 tags = local.tags
7 }
8
9 module "live-dzone-bucket" {
10 source = "../modules/s3-bucket"
11 bucket = "live-dzone-iac-bucket"
12 policy = null
13 expire-days = 14
14 tags = local.tags
15 }

Terraform项目中的文件布局类似于下图 ,在“terraform-modules”(即Terraform模块)下包含用于开发和生产环境的单独文件夹,其中包含 AWS 资源。

一文搞懂基础设施即代码 (IaC)_开发人员_05

PART 05  

启用IaC的工作清单 

将现代IaC平台引入初创公司,或者是具有许多绿地软件项目的公司,可能并不困难。然而,对于大多数公司来说,却并不是一件简单的事情。许多公司,无论大小,都已经存在很多通过云供应商提供的简易控制台创建的基础设施。很多新项目就是这样简单启动的。然后,有一天,一位运维工程师幡然醒悟,意识到现在新项目是生产基础设施。为了使其更加“正式”,运维团队编写了一本运行手册或wiki,详细解说如果有人想要执行一项常见任务,应该单击哪些按钮等等。还有一种常见的情况,那就是周围全是只有一两个人明白的Bash或PowerShell脚本。如果你面临这样的情况,你该怎么办?

(1)保持冷静

你应该明白的是,变化有时候可能是令人感到恐惧的。许多人一想到要触及基础设施,就感到好像要崩溃一样。他们认为这太复杂了,搞不懂这个东西是如何工作的。所以,要有信心,才能解决问题。

(2)正确定义“完美”的概念

开发人员应该在开始评估工具和方法之前,要明白对于公司来说“完美”是什么一个概念。开发人员无论使用何种工具,一些假设都是既定存在的。明白这些才能实现目标。团体决策是正确制定公司云基础设施业务目标的途径之一。

(3)选择评估工具

考虑上述关键点之后,将筛选完美平台的选择范围缩小到几个评估对象。开发人员可以设计一个小项目,目的是测试平台,看它是否符合工作需求。

(4)导入现有基础设施

选择工具之后,试着导入一些现有的基础设施。如果开发人员选择的平台正确,这一步应该轻而易举。

(5)与现有工程实施方案集成

如果基础设施代码集成持续交付管道,则可以开始建立与应用程序代码相同的最佳实施方案。

(6)从小处着手 

新建一项服务或从非关键服务开始——这样即使出问题也不会影响业务。选择一个项目,尽快看到意义和价值,然后进行更新迭代。

PART 06  

结论    

现代IaC是降低云复杂性、释放云潜力从而推动创新的最佳途径。选择合适的平台,使用现代IaC,开发人员可以将标准软件工程实施方案和工具应用于基础设施。大体来说,可以获得以下几点益处。

1.推动创新、提高速度和敏捷性

借助现代IaC,团队可以将现代软件开发中,相同的操作、严谨的测试和自动化应用于云基础设施,从而提高发布的速度和可靠性,以便公司对客户反馈做出快速反应并及时更新。

2.降低基础设施风险

由于开发人员可以使用标准测试框架,因此IaC能够“将风险转移”。尽早的、充分和完全的测试可以成为开发过程以及CI/CD 管道的一部分。由于策略和安全要求也包含在代码里,故每次部署都会自动测试合规性和安全性。

3.加强合作

现代IaC平台使用标准工具和语言,可以打破基础设施、应用程序开发和安全团队之间的孤岛。大家使用共享的实践方案和工具,能促进团队之间的协作。

参考链接:

​https://dzone.com/refcardz/getting-started-with-iac​