深入了解 Terraform:一款基础设施即代码工具
想知道 Terraform 是什么吗? 让我们一起探索一下。
“基础设施即代码”(Infrastructure as Code,IaC)是 DevOps 领域中一个广为人知的概念。 它指的是使用机器可读的配置文件来管理和配置包括物理机和虚拟机在内的整个 IT 基础设施的过程。 这是一种将软件工程方法应用于运营的方式,通过编程脚本来自动化数据中心的各项操作。
虽然 IaC 带来了诸多便利,但同时也面临着一些挑战:
- 需要掌握编程技能
- 难以预测变更的影响
- 需要回滚变更
- 缺乏变更跟踪机制
- 资源自动化能力有限
- 基础设施环境的多样性
为了解决这些挑战,Terraform 应运而生。
什么是 Terraform?
Terraform 是一款由 HashiCorp 开发的开源基础设施即代码工具。 它采用一种易于理解的声明性语言来定义和配置完整的IT基础设施。
Terraform 是一种基础设施配置工具,允许你将云基础设施的设置保存为代码。 它与诸如
CloudFormation
等工具类似,后者主要用于自动化 AWS 基础设施,但 Terraform 的优势在于它可以在多个云平台上使用,而不仅限于 AWS。
以下是使用 Terraform 的一些优势:
- 不仅仅是配置管理,还提供编排能力
- 支持多种云服务提供商,例如 AWS、Azure、GCP、DigitalOcean 等
- 提供不可变基础设施,配置变更更加平稳
- 使用易于理解的 HCL(HashiCorp Configuration Language)语言
- 易于迁移到其他提供商
- 支持仅客户端架构,无需在服务器上进行额外的配置管理
Terraform 核心概念
以下是 Terraform 中常用的一些核心概念和术语:
- 变量 (Variables):也称为输入变量,是 Terraform 模块用于自定义配置的键值对。
- 提供商 (Provider):是与服务 API 交互并访问相关资源的插件。
- 模块 (Module):是一个包含 Terraform 模板的文件夹,其中定义了所有的配置。
- 状态 (State):包含了 Terraform 所管理基础设施的缓存信息以及相关配置。
- 资源 (Resource):指的是一个或多个基础设施对象(如计算实例、虚拟网络等),用于配置和管理基础设施。
- 数据源 (Data Source):由提供商实现,用于从外部对象获取信息并提供给 Terraform。
- 输出值 (Output Value):是 Terraform 模块的返回值,可供其他配置使用。
- 计划 (Plan):确定从基础设施的当前状态转换到期望状态所需创建、更新或删除哪些资源的阶段。
- 应用 (Apply):实际执行基础设施变更,将当前状态更新为期望状态的阶段。
Terraform 生命周期
Terraform 的生命周期包括初始化、计划、应用和销毁四个阶段。
- Terraform init:初始化包含所有配置文件的项目目录。
- Terraform plan:生成执行计划,以达到预期的基础设施状态。它会分析配置文件的变更,并确定如何达到期望的状态。
- Terraform apply:执行计划中定义的基础设施变更,使基础设施达到预期的状态。
- Terraform destroy:删除所有旧的基础设施资源,这些资源在应用阶段后被标记为过时。
Terraform 的工作原理
Terraform 的架构主要由两个组件组成:
Terraform 核心
Terraform 核心接收两个输入来源来完成工作。
第一个输入是用户配置的 Terraform 配置文件,其中定义了需要创建或配置的内容。第二个输入是 Terraform 维护的当前基础设施状态。
Terraform 核心会分析这些输入,并生成一个执行计划。它会比较当前状态和期望状态,计算出为了达到配置文件中指定的状态需要执行哪些操作,包括创建、更新和删除哪些资源。
提供商
架构的第二个组成部分是各种特定技术的提供商。这些提供商可以是云服务商(如 AWS、Azure、GCP),也可以是其他基础设施即服务平台。 它们也可能是更高级的组件提供商,例如 Kubernetes 或其他平台即服务工具,甚至一些软件即服务工具。
通过使用不同的提供商,你可以在不同级别上创建基础设施。 例如,你可以先创建一个 AWS 基础设施,然后在上面部署 Kubernetes,最后在 Kubernetes 集群内部创建服务和组件。
Terraform 提供了数百个不同技术的提供商,每个提供商都允许 Terraform 用户访问其资源。例如,通过 AWS 提供商,你可以访问 AWS 上的各种资源,例如 EC2 实例和 AWS 用户。通过 Kubernetes 提供商,你可以访问诸如服务、部署和命名空间等资源。
总而言之,Terraform 的目标是帮助你配置和管理从基础设施到应用程序的整个应用环境。
接下来,让我们进行一些实际操作。 👨💻
我们将在 Ubuntu 系统上安装 Terraform 并部署一个非常简单的基础设施。
安装 Terraform
首先,下载最新的 Terraform 安装包。
请访问 官方下载页面 以获取适用于你操作系统的最新版本。
[email protected]:~$ wget https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip --2020-08-14 16:55:38-- https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip 正在解析主机 releases.hashicorp.com (releases.hashicorp.com)... 151.101.153.183, 2a04:4e42:24::439 正在连接 releases.hashicorp.com (releases.hashicorp.com)|151.101.153.183|:443... 已连接。 已发出 HTTP 请求,正在等待回应... 200 OK 长度:34851622 (33M) [application/zip] 正在保存至: “terraform_0.13.0_linux_amd64.zip” terraform_0.13.0_linux_amd64.zip 100%[=================================================================>] 33.24M 90.3KB/s 用时 5m 28s 2020-08-14 17:01:06 (104 KB/s) - 已保存 “terraform_0.13.0_linux_amd64.zip” [34851622/34851622]
解压缩下载的安装包。
[email protected]:~$ unzip terraform_0.13.0_linux_amd64.zip Archive: terraform_0.13.0_linux_amd64.zip 正在解压缩: terraform
将 Terraform 可执行文件移动到如下所示的路径,并验证 Terraform 版本。
[email protected]:~$ sudo mv terraform /usr/local/bin/ [sudo] techblik.com 的密码: [email protected]:~$ terraform -v Terraform v0.13.0
以下是 Terraform 的可用命令列表。
[email protected]:~$ terraform 用法: terraform [-version] [-help] <command> [args] 可用的命令如下所示。 最常用、有用的命令显示在前面,其次是 不太常见或更高级的命令。 如果您只是刚开始 使用 Terraform,请坚持使用常用命令。 对于 其他命令,请在使用前阅读帮助和文档。 常用命令: apply 构建或更改基础设施 console 用于 Terraform 插值的交互式控制台 destroy 销毁 Terraform 管理的基础设施 env 工作空间管理 fmt 将配置文件重写为规范格式 get 下载并安装配置的模块 graph 创建 Terraform 资源的可视化图表 import 将现有基础设施导入 Terraform init 初始化 Terraform 工作目录 login 获取并保存远程主机的凭据 logout 删除本地存储的远程主机的凭据 output 从状态文件中读取输出 plan 生成并显示执行计划 providers 打印配置中使用的提供程序树 refresh 针对真实资源更新本地状态文件 show 检查 Terraform 状态或计划 taint 手动标记要重新创建的资源 untaint 手动取消标记为已损坏的资源 validate 验证 Terraform 文件 version 打印 Terraform 版本 workspace 工作空间管理 所有其他命令: 0.12upgrade 为 v0.12 重写 pre-0.12 模块源代码 0.13upgrade 为 v0.13 重写 pre-0.13 模块源代码 debug 调试输出管理(实验性) force-unlock 手动解锁 Terraform 状态 push Terraform Enterprise 遗留版 (v1) 的过时命令 state 高级状态管理
使用 Terraform 预配置 AWS EC2 实例
在这个演示中,我们将使用 Terraform 启动一个新的 AWS EC2 实例。
首先,为这个 Terraform 演示创建一个工作目录。
[email protected]:~$ mkdir terraform_demo
进入该目录并创建一个 Terraform 配置文件,在其中定义提供程序和资源,以启动 AWS EC2 实例。
[email protected]:~$ cd terraform_demo/ [email protected]:~/terraform_demo$ gedit awsec2.tf provider "aws" { access_key = "B5KG6Fe5GUKIATUF5UD" secret_key = "R4gb65y56GBF6765ejYSJA4YtaZ+T6GY7H" region = "us-west-2" } resource "aws_instance" "terraform_demo" { ami = "ami-0a634ae95e11c6f91" instance_type = "t2.micro" }
请注意:这里我更改了访问密钥和密钥,你需要使用你自己的凭据。 😛
从上面的配置中可以看到,我指定了名为 “aws” 的提供商。 在提供商的配置中,我提供了 AWS 用户的凭据和启动实例的区域。
在资源定义中,我提供了 Ubuntu 镜像 (ami-0a634ae95e11c6f91) 的 AMI 详细信息,并指定了实例类型为 t2.micro。
即使你不是专业的开发人员,也能看出配置文件的简洁易读性。
Terraform 初始化
现在,第一步是初始化 Terraform。
[email protected]:~/terraform_demo$ terraform init 正在初始化后端... 正在初始化提供程序插件... - 使用之前安装的 hashicorp/aws v3.2.0 以下提供程序在配置中没有任何版本约束, 因此安装了最新版本。 为了防止自动升级到可能包含破坏性更改的新主要版本, 建议在配置中的 required_providers 块中添加版本约束, 并使用下面建议的约束字符串。 * hashicorp/aws: version = "~> 3.2.0" Terraform 已成功初始化! 现在您可以开始使用 Terraform。 尝试运行“terraform plan”来查看 您的基础设施所需的任何更改。 现在所有 Terraform 命令都应该可以工作。 如果您曾经设置或更改过 Terraform 的模块或后端配置, 请重新运行此命令以重新初始化您的工作目录。 如果你忘记了,其他的 命令会检测到它并提醒您在必要时执行此操作。
Terraform 计划
接下来是计划阶段,此阶段将创建执行图以创建和配置基础设施。
[email protected]:~/terraform_demo$ terraform plan 正在刷新 Terraform 状态内存,然后进行计划... 刷新后的状态将用于计算此计划,但不会 保存到本地或远程状态存储。 ------------------------------------------------------------------------ 已生成执行计划,如下所示。 资源操作使用以下符号表示: + create Terraform 将执行以下操作: # 将创建 aws_instance.terraform_demo + resource "aws_instance" "terraform_demo" { + ami = "ami-0a634ae95e11c6f91" + arn = (apply 后得知) + associate_public_ip_address = (apply 后得知) + availability_zone = (apply 后得知) + cpu_core_count = (apply 后得知) + cpu_threads_per_core = (apply 后得知) + get_password_data = false + host_id = (apply 后得知) + id = (apply 后得知) + instance_state = (apply 后得知) + instance_type = "t2.micro" + ipv6_address_count = (apply 后得知) + ipv6_addresses = (apply 后得知) + key_name = (apply 后得知) + outpost_arn = (apply 后得知) + password_data = (apply 后得知) + placement_group = (apply 后得知) + primary_network_interface_id = (apply 后得知) + private_dns = (apply 后得知) + private_ip = (apply 后得知) + public_dns = (apply 后得知) + public_ip = (apply 后得知) + secondary_private_ips = (apply 后得知) + security_groups = (apply 后得知) + source_dest_check = true + subnet_id = (apply 后得知) + tenancy = (apply 后得知) + volume_tags = (apply 后得知) + vpc_security_group_ids = (apply 后得知) + ebs_block_device { + delete_on_termination = (apply 后得知) + device_name = (apply 后得知) + encrypted = (apply 后得知) + iops = (apply 后得知) + kms_key_id = (apply 后得知) + snapshot_id = (apply 后得知) + volume_id = (apply 后得知) + volume_size = (apply 后得知) + volume_type = (apply 后得知) } + ephemeral_block_device { + device_name = (apply 后得知) + no_device = (apply 后得知) + virtual_name = (apply 后得知) } + metadata_options { + http_endpoint = (apply 后得知) + http_put_response_hop_limit = (apply 后得知) + http_tokens = (apply 后得知) } + network_interface { + delete_on_termination = (apply 后得知) + device_index = (apply 后得知) + network_interface_id = (apply 后得知) } + root_block_device { + delete_on_termination = (apply 后得知) + device_name = (apply 后得知) + encrypted = (apply 后得知) + iops = (apply 后得知) + kms_key_id = (apply 后得知) + volume_id = (apply 后得知) + volume_size = (apply 后得知) + volume_type = (apply 后得知) } } 计划:1 个新增,0 个更改,0 个销毁。 ------------------------------------------------------------------------ 注意:您没有指定“-out”参数来保存此计划,因此如果 随后运行“terraform apply”,Terraform 无法保证会精确执行这些操作。
Terraform 应用
应用阶段将执行配置文件并启动 AWS EC2 实例。 当你运行 apply 命令时,它会询问你,“您想执行这些操作吗?”,你需要输入 yes 然后按回车。
[email protected]:~/terraform_demo$ terraform apply 已生成执行计划,如下所示。 资源操作使用以下符号表示: + create Terraform 将执行以下操作: # 将创建 aws_instance.terraform_demo + resource "aws_instance" "terraform_demo" { + ami = "ami-0a634ae95e11c6f91" + arn = (apply 后得知) + associate_public_ip_address = (apply 后得知) + availability_zone = (apply 后得知) + cpu_core_count = (apply 后得知) + cpu_threads_per_core = (apply 后得知) + get_password_data = false + host_id = (apply 后得知) + id = (apply 后得知) + instance_state = (apply 后得知) + instance_type = "t2.micro" + ipv6_address_count = (apply 后得知) + ipv6_addresses = (apply 后得知) + key_name = (apply 后得知) + outpost_arn = (apply 后得知) + password_data = (apply 后得知) + placement_group = (apply 后得知) + primary_network_interface_id = (apply 后得知) + private_dns = (apply 后得知) + private_ip = (apply 后得知) + public_dns = (apply 后得知) + public_ip = (apply 后得知) + secondary_private_ips = (apply 后得知) + security_groups = (apply 后得知) + source_dest_check = true + subnet_id = (apply 后得知) + tenancy = (apply 后得知) + volume_tags = (apply 后得知) + vpc_security_group_ids = (apply 后得知) + ebs_block_device { + delete_on_termination = (apply 后得知) + device_name = (apply 后得知) + encrypted = (apply 后得知) + iops = (apply 后得知) + kms_key_id = (apply 后得知) + snapshot_id = (apply 后得知) + volume_id = (apply 后得知) + volume_size = (apply 后得知) + volume_type = (apply 后得知) } + ephemeral_block_device { + device_name = (apply 后得知) + no_device = (apply 后得知) + virtual_name = (apply 后得知) } + metadata_options { + http_endpoint = (apply 后得知) + http_put_response_hop_limit = (apply 后得知) + http_tokens = (apply 后得知) } + network_interface { + delete_on_termination = (apply 后得知) + device_index = (apply 后得知) + network_interface_id = (apply 后得知) } + root_block_device { + delete_on_termination = (apply 后得知) + device_name = (apply 后得知) + encrypted = (apply 后得知) + iops = (apply 后得知) + kms_key_id = (apply 后得知) + volume_id = (apply 后得知) + volume_size = (apply 后得知) + volume_type = (apply 后得知) } } 计划:1 个新增,0 个更改,0 个销毁。 您要执行这些操作吗? Terraform 将执行以上描述的操作。 只有输入“yes”才会接受批准。 输入值: yes aws_instance.terraform_demo: 正在创建... aws_instance.terraform_demo: 仍在创建... [经过 10 秒] aws_instance.terraform_demo: 仍在创建... [经过 20 秒] aws_instance.terraform_demo: 仍在创建... [经过 30 秒] aws_instance.terraform_demo: 仍在创建... [经过 40 秒] aws_instance.terraform_demo: 创建已完成,耗时 44 秒 [id=i-0eec33286ea4b0740] 应用完成! 资源:1 个已添加,0 个已更改,0 个已销毁。
转到你的 AWS EC2 控制面板,你将看到一个新的实例已经创建,其 ID 与应用命令末尾提到的 ID 相匹配。
你已经使用 Terraform 成功启动了一个 AWS EC2 实例。
Terraform 销毁
最后,如果要删除基础设施,你需要运行 destroy 命令。
[email protected]:~/terraform_demo$ terraform destroy aws_instance.terraform_demo: 正在刷新状态... [id=i-0eec33286ea4b0740] 已生成执行计划,如下所示。 资源操作使用以下符号表示: - destroy Terraform 将执行以下操作: # 将销毁 aws_instance.terraform_demo - resource "aws_instance" "terraform_demo" { - ami = "ami-0a634ae95e11c6f91" -> null - arn = "arn:aws:ec2:us-west-2:259212389929:instance/i-0eec33286ea4b0740" -> null - associate_public_ip_address = true -> null - availability_zone = "us-west-2c" -> null - cpu_core_count = 1 -> null - cpu_threads_per_core = 1 -> null - disable_api_termination = false -> null - ebs_optimized = false -> null - get_password_data = false -> null - hibernation = false -> null - id = "i-0eec33286ea4b0740" -> null - instance_state = "running" -> null - instance_type = "t2.micro" -> null - ipv6_address_count = 0 -> null - ipv6_addresses = [] -> null - monitoring = false -> null - primary_network_interface_id = "eni-02a46f2802fd15634" -> null - private_dns = "ip-172-31-13-160.us-west-2.compute.internal" -> null - private_ip = "172.31.13.160" -> null - public_dns = "ec2-34-221-77-94.us-west-2.compute.amazonaws.com" -> null - public_ip = "34.221.77.94" -> null - secondary_private_ips = [] -> null - security_groups = [ - "default", ] -> null - source_dest_check = true -> null - subnet_id = "subnet-5551200c" -> null - tags = {} -> null - tenancy = "default" -> null - volume_tags = {} -> null - vpc_security_group_ids = [ - "sg-b5b480d1", ] -> null - credit_specification { - cpu_credits = "standard" -> null } - metadata_options { - http_endpoint = "enabled" -> null - http_put_response_hop_limit = 1 -> null - http_tokens = "optional" -> null } - root_block_device { - delete_on_termination = true -> null - device_name = "/dev/sda1" -> null - encrypted = false -> null - iops = 100 -> null - volume_id = "vol-0be2673afff6b1a86" -> null - volume_size = 8 -> null - volume_type = "gp2" -> null } } 计划:0 个新增,0 个更改,1 个销毁。 您真的要销毁所有资源吗? Terraform 将销毁您以上述方式管理的所有基础设施。 没有撤消操作。 只有输入“yes”才会确认。 输入值: yes aws_instance.terraform_demo: 正在销毁... [id=i-0eec33286ea4b0740] aws_instance.terraform_demo: 仍在销毁... [id=i-0eec33286ea4b0740, 经过 10 秒] aws_instance.terraform_demo: 仍在销毁... [id=i-0eec33286ea4b0740, 经过 20 秒] aws_instance.terraform_demo: 仍在销毁... [id=i-0eec33286ea4b0740, 经过 30 秒] aws_instance.terraform_demo: 销毁已完成,耗时 34 秒 销毁完成! 资源:1 个已销毁。
如果你重新检查 EC2 控制面板,你会看到该实例已终止。
总结
我相信以上内容已经为你提供了使用 Terraform 的初步概念。 你可以继续尝试我刚刚演示的示例。
你还可以了解这些基础设施自动化软件。
如果您有兴趣了解更多信息,我建议您查看
关于使用 Terraform 学习 DevOps 的课程。