Terraform 是什么?
Terraform 是一款 基础设施即代码(Infrastructure as Code, IaC) 工具,由 HashiCorp 公司开发。Terraform 允许您自动化和管理您的基础设施以及运行在该基础设施上的平台和服务。它能够管理诸如计算、存储和网络资源等底层组件,也能管理诸如 DNS 条目和 SaaS 功能等高层组件。
它是开源的,并且使用声明式语言(declarative)来编写配置文件,这些文件可以进行版本控制、复用和共享。
declarative = define WHAT end result you want
使用声明式语言意味着无需定义这些自动化和管理的每一步,只需声明最终结果或目标,Terraform 将自行决定如何执行。
这区别于命令式语言(imperative),即您需要指定如何执行每个步骤。
imperative = specify how to execute each step
总结核心思想就是:通过代码定义来自动化管理云资源(自动创建、更新或销毁),而非手动在控制台点击操作。
基础设施配置(provisioning)
Terraform 是一个用于基础设施配置的工具(Terraform is a tool for infrastructure provisioning)。
假设您刚刚启动了一个项目,创建了一些应用程序,并希望从头开始设置一个基础设施来运行这些应用程序。您的基础设施会是什么样子呢?假设您希望启动多个服务器,在这些服务器上部署构成您应用程序的五个微服务应用作为 Docker 容器,并且还要部署一个数据库容器。您决定使用 AWS 平台来构建整个基础设施。因此,第一步将是前往 AWS 并准备设置,以便应用程序可以部署在那里。这意味着您需要创建私有网络空间、创建 EC2 服务器实例、在每个实例上安装 Docker 以及您应用程序可能需要的任何其他工具。您还需要在服务器上设置安全措施,如防火墙,配置网络等。一旦基础设施准备就绪,您现在就可以在准备好的基础设施上部署您的 Docker 应用程序或 Docker 容器。
正如您所见,这是创建整个设置的两个不同任务或两个独立步骤。一个是配置基础设施,准备一切以便应用程序可以部署。第二个是实际在基础设施上部署应用程序。因此,您甚至可能有两个独立的团队或两个人分别执行这两个任务。一个可能的场景是 DevOps 团队成员配置基础设施,然后开发人员在准备好的基础设施上部署应用程序。
Terraform 用于上述说的第一部分,即配置基础设施以准备应用程序部署。创建 VPC、启动服务器、设置安全性、创建具有权限的 AWS 用户、可能在服务器上安装特定版本的 Docker 等。显然,所有这些都需要按正确的顺序完成,因为一个任务可能依赖于另一个任务。
管理现有基础设施(managing)
现在,让我们回到我们的用例场景:你已经使用 Terraform 在 AWS 上成功为你的项目创建了基础设施,并在其上部署了应用程序。现在,你决定在现有基础设施中增加五台服务器,以便部署更多的微服务,因为你的团队开发了一些新功能,需要将其部署上线。同时,你可能还想添加一些安全配置,或者移除一些最初配置的内容。因此,我们现在进入了管理现有基础设施的阶段,包括添加、重新配置或移除某些内容等。
使用 Terraform,你可以非常轻松地对基础设施进行此类调整。管理基础设施的任务同样重要,因为一旦你为项目创建了初始的基础设施,你将需要不断地对其进行调整和修改。正因如此,你也需要一些自动化工具来为你完成大部分繁重的工作,从而避免手动配置和操作。因此,当你使用 Terraform 来创建、更改或维护基础设施时,另一个有用的功能或常见用例是复制该基础设施。假设在你测试了这个设置并且一切运行良好后,你决定现在要将应用程序发布到生产环境中。于是,你想创建一个与开发环境完全相同的生产环境,并保留第一个环境作为开发环境,以便在其中测试新功能、新微服务和更新,然后再将其发布到生产环境中。同样,你可以在这里使用 Terraform 来自动化这一过程,从而轻松地使用与第一个设置(即开发环境设置)相同的 Terraform 代码来启动一个完全相同的基础设施和设置。你也可以用同样的方法来快速搭建一个相同的 staging 环境。这使得这些任务也变得非常容易。
Terraform 是如何工作的?
Terraform 是如何做到这一切的?它是如何连接到这些基础设施提供商平台,并利用这些技术来部署资源的?例如,Terraform 如何连接到 AWS 创建虚拟空间、启动 EC2 实例、配置网络等?
为了完成这些任务,Terraform 有两个主要组件构成了其架构:
- Terraform Core
- Providers for specific technologies
Terraform Core
Terraform Core 使用两种输入源来完成任务。首先是你作为用户编写的 Terraform 配置文件,其中定义了需要创建或部署的内容;第二个是 Terraform state,Terraform 会保存当前基础设施配置的最新状态。然后,Core 会处理这些输入,制定出需要执行的计划(plan)。它会比较当前状态和你希望达到的状态,即你提到的最终结果。当它发现有差异时,即你想要的状态与当前状态不同,它会计算出需要采取什么措施来达到配置文件中的期望状态。这包括需要创建什么、更新什么、删除什么,以及在基础设施配置中的顺序。
Providers
架构的第二个部分是特定技术的 provider。这可以是像 AWS、Azure 这样的云提供商,或者用于基础设施级别任务的其他即服务平台。但 Terraform 还有为更高层次组件(如 Kubernetes 或其他平台即服务工具,甚至一些软件即服务工具)的 provider。这使得你可以在不同层次上创建资源,例如创建 AWS 基础设施,然后在其上部署或创建 Kubernetes,再在其中创建服务或组件。HashiCorp 和 Terraform 社区已经编写了数千个 providers,用于管理多种不同类型的资源和服务。可以在 Terraform Registry 上找到所有公开可用的 provider。每个 provider 都为 Terraform 用户提供了对其资源的访问权限。例如,通过 AWS provider,你可以访问数百个 AWS 资源,如 EC2 实例、AWS 用户等。通过 Kubernetes provider,你可以访问 Kubernetes 资源,如 services、deployments 和 namespaces 等。这就是 Terraform 的工作方式,它试图从基础设施到应用程序全面帮助你进行部署,这非常方便。
一旦 Core 根据配置文件和状态输入创建执行计划后,它就会使用特定技术的提供者来执行计划,连接到这些平台,并实际执行这些操作步骤。
Terraform 配置文件
现在,我们来看一下 Terraform 配置文件是如何呈现的。这是一个示例,其中配置了 AWS 提供者,并通过提供者创建了两个 AWS 资源,如 VPC。你可以通过一些属性来创建这些资源。同样,这里配置了 Kubernetes 提供者,通过它你可以创建 Kubernetes 命名空间资源,并传递一些属性。语法非常直观,可以说。基本上,你定义你想要创建的技术或提供者的资源,然后定义其属性,Terraform 就会为你创建或执行这些操作。
provider "aws" {
region = "us-east-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "subnet_1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
resource "kubernetes_namespace" "example" {
metadata {
name = "example-namespace"
}
}
理解声明式很重要
之前提到过:Terraform 配置文件采用的声明式方法,这一点很重要,需要理解。
那么,声明式具体是什么意思呢?当你创建一个 Terraform 文件时,你不需要定义创建 VPC 或启动五台 EC2 实例或创建网络配置的具体步骤,而是定义你希望达到的最终状态。例如,你可以说,我希望有五台服务器,网络配置如下,并且我希望有一个 AWS 用户具有这些权限来访问所有服务器。Terraform,帮我完成这些。因此,你定义的是最终结果,而不是具体步骤,这就是声明式方法。在初始设置时,这可能不会有很大的区别。所以,当配置是声明式和命令式时,它们可能看起来非常相似。但当你更新基础设施时,比如移除一台服务器、添加另一台服务器或进行其他调整时,情况就不同了。使用命令式方法时,你可以在配置文件中写入:移除两台服务器,添加防火墙配置,为 AWS 用户添加一些权限等。你给出的是具体的操作指令。而在 Terraform 的声明式方法中,你可以说,我现在希望有七台服务器,这个防火墙配置,以及具有这些权限的用户。你需要做的是将当前状态调整到新的期望状态。因此,你不需要计算和决定需要添加多少台服务器。你只需要说,我希望最终有七台服务器,这就是我想要的。或者你不需要计算和确定需要添加多少权限或哪些权限。你只需要说,我希望最终有这些权限。使用声明式方法,如果你只需调整旧的配置文件并重新执行,而不是添加新的指令集,这显然非常方便,因为你的配置文件将保持干净和简洁。而且,你总是可以通过查看配置文件来知道当前的设置,因为配置文件始终代表最终结果。而在命令式方法中,你需要计算并确定多次指令应用后的差异。
Terraform 命令
你已经创建了 Terraform 配置文件,定义了你在 AWS 上所需的基础设施设置。那么,如何让 Terraform 采取行动呢?Terraform 有一些命令可以执行,以经历不同的阶段,非常清晰明了。
第一个命令是 refresh
。使用这个命令,Terraform 将查询基础设施提供商,如 AWS,以获取最新的状态。这样,Terraform 就会知道当前基础设施的状态。
接下来的命令是 plan
。上面提到,core 部分会将当前状态和配置文件作为输入,根据两者之间的差异来决定需要执行什么操作。这就是所谓的计划(plan)。Terraform 需要做些什么来实现你在 Terraform 配置文件中定义的期望状态。如果是初始设置,它会计算出创建期望设置的所有步骤。如果是更新,它会将现有的设置与新的期望状态进行比较,并确定需要按什么顺序进行哪些更改和调整以创建新的期望状态,例如添加一台新服务器和新的权限等。这只是计划。core 部分在这里会逻辑地构建计划,即需要执行什么。
接下来的命令是实际执行的命令,那就是 apply
命令。使用 apply
,你可以执行这个计划。plan
命令就像是执行 apply
后会发生什么的一个预览。显然,Terraform 在后台会先进行 refresh
以获取最新的状态,然后创建计划,最后执行这个计划。这意味着如果你想执行一个配置文件,你只需执行 apply
命令,它就会自动完成这一切。
另一个命令是 destroy
,显然会销毁整个设置,按照正确的顺序逐个删除元素,并清理所有创建的资源,基本上是撤销所有创建的内容。如果,比如说,你为一个重要的演示日创建了一个环境,并且不想干扰现有的环境,演示结束后,你可以销毁整个设置。destroy
命令像 apply
命令一样,会先检查当前运行的内容,然后创建一个需要按什么顺序删除的计划。