Terraform
创建基础设施
您可以使用 Terraform 来创建和管理您的基础设施代码。在本教程中,您将使用 Terraform 在 Amazon Web Services (AWS) 上配置一个 EC2 实例。EC2 实例是在 AWS 上运行的虚拟机,是许多基础设施项目的常见组成部分。要配置您的基础设施,您将编写配置来定义您的提供程序和实例,设置 AWS 凭证的环境变量,初始化一个新的本地工作区,然后应用您的配置来创建您的实例。
先决条件
要遵循本教程,您需要
- 已安装 Terraform CLI(1.2.0+)。
- 已安装 AWS CLI。
- 一个 AWS 账户和 关联的凭证,允许您在
us-west-2区域中创建资源,包括一个 EC2 实例、VPC 和安全组。
此系列教程中的资源符合 AWS 免费套餐 的资格。我们不对您可能产生的任何费用负责。请记住完成此系列教程中后面的 销毁基础设施 教程,以删除您在遵循这些教程时创建的基础设施。
编写配置
创建一个新的目录,用于您在本教程中将使用的 Terraform 配置。
$ mkdir learn-terraform-get-started-aws
进入该目录。
$ cd learn-terraform-get-started-aws
Terraform 配置文件是纯文本文件,使用 HashiCorp 的配置语言 HCL,文件名称以 .tf 结尾。当您使用 Terraform CLI 执行操作时,Terraform 会加载当前工作目录中的所有配置文件,并自动解析配置中的依赖关系。这允许您将配置组织到多个文件中,并以您选择的任何顺序进行组织。
Terraform 配置组织成几种类型的块,这些块允许您配置 Terraform 本身、Terraform 提供程序以及构成您基础设施的资源和数据源。
terraform 块
terraform {} 块配置 Terraform 本身,包括要安装哪些提供程序以及使用 Terraform 的哪个版本来配置您的基础设施。使用一致的文件结构可以更轻松地维护您的 Terraform 项目,因此我们建议在专用的 terraform.tf 文件中配置您的 Terraform 块。
创建并打开一个名为 terraform.tf 的新文件,其中包含以下配置以定义您的 Terraform 块。
terraform.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.92"
}
}
required_version = ">= 1.2"
}
Terraform 使用称为 providers 的二进制插件来通过调用您的云提供商的 API 来管理您的资源。Terraform 提供程序与 Terraform 二进制文件分开分发和版本控制。通过将提供程序与 Terraform 二进制文件解耦,Terraform 可以支持具有 API 的任何基础设施供应商。 required_providers 块允许您为配置使用的提供程序设置版本约束。HashiCorp 维护 Terraform Registry,您可以从中获取公共 Terraform 提供程序和模块。
在 required_providers 块中设置每个提供程序的 source 和 version 参数。
The source 参数指定主机名(可选)、命名空间和提供程序名称。在示例配置中,aws 提供程序的源是 hashicorp/aws,这是 registry.terraform.io/hashicorp/aws 的缩短形式,即提供程序在 Terraform Registry 中的地址。
The version 参数设置 AWS 提供程序的版本约束。如果您没有指定版本约束,Terraform 默认使用提供程序的最新版本。我们建议使用版本约束,以确保 Terraform 不安装您尚未与配置一起测试过的版本。字符串 ~> 5.92 表示您的配置支持提供程序的任何主版本为 5 且次版本大于或等于 92 的版本。
示例配置还定义了 Terraform 本身所需的版本。字符串 >= 1.2 表示您的配置支持 Terraform 的任何版本大于或等于 1.2。当您安装 Terraform 时,您可能安装了当前可用的最新版本。
您可以通过运行 terraform -version 命令来检查您当前的 Terraform 版本。
$ terraform -version
Terraform v1.12.0
on darwin_arm64
配置块
使用您的文本编辑器将以下配置粘贴到名为 main.tf 的新文件中。
main.tf
provider "aws" {
region = "us-west-2"
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
tags = {
Name = "learn-terraform"
}
}
当您编写新的 Terraform 配置时,我们建议将您的提供程序块和其他主要基础设施定义在 main.tf 中,作为最佳实践。随着您向配置添加内容,您可以选择将相关基础设施组织到不同的文件中。
查看您的 main.tf 文件中的块。
提供程序
The provider 块配置适用于由您的提供程序管理的所有资源的选项,例如创建它们的区域。此 provider 块配置了 aws 提供程序。提供程序块的标签对应于 required_providers 列表中提供程序的名称在您的 terraform 块中。
main.tf
provider "aws" {
region = "us-west-2"
}
您可以在 Terraform 配置中使用多个提供程序块来配置多个提供程序或同一提供程序的多个实例,这些实例具有不同的配置,例如不同的区域。Terraform 提供程序必须向您的云提供程序的 API 进行身份验证才能管理您的资源。提供程序通常支持多种身份验证方法。
Terraform 的 AWS 提供程序使用与 AWS CLI 相同的身份验证方法。如果您尚未这样做,请将您的 AWS 凭证配置为终端中的环境变量。
要使用您的 IAM 凭证对 Terraform AWS 提供程序进行身份验证,请设置 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 环境变量。
$ export AWS_ACCESS_KEY_ID=
$ export AWS_SECRET_ACCESS_KEY=
使用 AWS CLI 验证您的凭证。
$ aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************ZJZK env
secret_key ****************St8S env
region <not set> None None
数据源
你可以使用 data 块来查询你的云提供商,获取关于其他资源的信息。这个数据源会获取与过滤器匹配的最新 AWS AMI 的数据,因此你无需将 AMI ID 硬编码到你的配置中。数据源有助于保持你的配置动态,并避免可能过时的硬编码值。
main.tf
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
}
owners = ["099720109477"] # Canonical
}
数据源有一个 ID,你可以使用它在配置中引用数据属性。数据源 ID 以 data 前缀开头,后跟块的类型和名称。在这个例子中,data.aws_ami.ubuntu 数据源加载了配置的提供商区域中最新 Ubuntu Noble Numbat 版本的 AMI。
资源
一个 resource 块定义了你的基础设施组件。示例配置定义了一个资源块来创建 AWS EC2 实例。
main.tf
resource "aws_instance" "app_server" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
tags = {
Name = "learn-terraform"
}
}
提供商开发者决定支持的资源类型及其参数。一个 resource 块的第一行声明了一个**资源类型**和一个**资源名称**。在这个例子中,资源类型是 aws_instance。资源类型的前缀对应于提供商的名称,字符串的其余部分是提供商定义的资源类型。资源类型和资源名称共同构成配置中资源的唯一**资源地址**。你的 EC2 实例的资源地址是 aws_instance.app_server。你可以通过其资源地址在配置的其他部分引用资源。
你的 resource 块中的参数配置资源及其行为
ami参数通过引用你的data.aws_ami.ubuntu数据源的id属性来指定要使用的机器镜像。instance_type参数将t2.micro硬编码为类型,该类型符合 AWS 免费套餐的资格。tags参数设置 EC2 实例的名称。你还可以在 tags 参数中设置 EC2 实例的其他标签。
格式化配置
我们建议使用一致的格式化以确保可读性。 terraform fmt 命令会自动根据 HashiCorp 推荐的风格重新格式化当前目录中的所有配置文件。
在你的终端中,使用 Terraform 格式化你的配置文件。
$ terraform fmt
main.tf
Terraform 会打印它修改过的文件的名称(如果有)。在这种情况下,提供的示例配置并不完全符合推荐的风格,因此 Terraform 更新了你的 main.tf 文件。
初始化你的工作区
在应用你的配置之前,你必须使用 terraform init 命令初始化你的 Terraform 工作区。作为初始化的一部分,Terraform 会下载并安装配置中定义的提供商,并将其安装在当前工作目录中。
初始化您的 Terraform 工作区。
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.92"...
- Installing hashicorp/aws v5.98.0...
- Installed hashicorp/aws v5.98.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Terraform 下载了 aws 提供商并将其安装在当前工作目录的隐藏 .terraform 子目录中。Terraform 还创建了一个名为 .terraform.lock.hcl 的文件,该文件指定了与你的工作区一起使用的确切提供商版本,从而确保运行之间的一致性。
验证配置
使用 terraform validate 命令确保你的配置在语法上有效且内部一致。
$ terraform validate
Success! The configuration is valid.
上述示例配置有效,因此 Terraform 会返回一条成功消息。
validate 命令可以帮助你识别配置中的错误。例如,如果你拼写错误资源名称或引用资源不支持的参数,Terraform 会在验证配置时报告错误。
创建基础设施
Terraform 对你的基础设施进行更改分为两个步骤。
Terraform 会为它将要进行的更改创建一个执行计划。请查看此计划,以确保 Terraform 将会进行你期望的更改。
一旦你批准了执行计划,Terraform 将使用你的工作区的提供程序应用这些更改。
此工作流程可确保你在 Terraform 对你的基础设施进行更改之前,能够检测并解决配置中的任何意外问题。
现在使用 terraform apply 命令规划和应用你的配置。Terraform 将打印出执行计划,并在应用更改之前要求你确认。你的配置包含单个资源,aws_instance.app_server,因此你的计划将指示 Terraform 将创建你的 EC2 实例。
$ terraform apply
data.aws_ami.ubuntu: Reading...
data.aws_ami.ubuntu: Read complete after 1s [id=ami-0026a04369a3093cc]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.app_server will be created
+ resource "aws_instance" "app_server" {
+ ami = "ami-0026a04369a3093cc"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ disable_api_stop = (known after apply)
+ disable_api_termination = (known after apply)
+ ebs_optimized = (known after apply)
+ enable_primary_ipv6 = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
+ id = (known after apply)
+ instance_initiated_shutdown_behavior = (known after apply)
+ instance_lifecycle = (known after apply)
+ instance_state = (known after apply)
+ instance_type = "t2.micro"
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ monitoring = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ placement_partition_number = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ spot_instance_request_id = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Name" = "learn-terraform"
}
+ tags_all = {
+ "Name" = "learn-terraform"
}
+ tenancy = (known after apply)
+ user_data = (known after apply)
+ user_data_base64 = (known after apply)
+ user_data_replace_on_change = false
+ vpc_security_group_ids = (known after apply)
+ capacity_reservation_specification (known after apply)
+ cpu_options (known after apply)
+ ebs_block_device (known after apply)
+ enclave_options (known after apply)
+ ephemeral_block_device (known after apply)
+ instance_market_options (known after apply)
+ maintenance_options (known after apply)
+ metadata_options (known after apply)
+ network_interface (known after apply)
+ private_dns_name_options (known after apply)
+ root_block_device (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
输出格式类似于 Git 等工具生成的 diff 格式。 + 符号位于 resource "aws_instance" "app_server" 旁边,表示当你应用此计划时,Terraform 将使用 aws_instance.app_server 作为其 ID 创建资源。
Terraform 会显示将在你的 EC2 实例上设置的属性,并指示某些值将在应用后 (known after apply)。 Terraform 尚未创建任何基础设施。如果计划显示了意外的更改,你可以在完成应用步骤之前取消操作。在这种情况下,该计划是可以接受的,因此在确认提示符处键入 yes 以继续。应用你的计划需要几分钟时间。
Enter a value: yes
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Creation complete after 14s [id=i-0c636e158c30e48f9]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
你现在已经使用 Terraform 创建了基础设施。访问 EC2 控制台 并找到你的新 EC2 实例。
检查状态
当你应用你的配置时,Terraform 会将关于你的基础设施的数据写入名为 terraform.tfstate 的文件。 Terraform 将关于你的基础设施的数据存储在其状态文件中,它使用该文件在其生命周期内管理资源。
使用 terraform state list 命令列出你的 Terraform 工作区的状态中的资源和数据源。
$ terraform state list
data.aws_ami.ubuntu
aws_instance.app_server
即使数据源不是实际的资源,Terraform 也会在你的状态文件中跟踪它。使用 terraform show 命令打印出你的工作区的整个状态。
$ terraform show
# data.aws_ami.ubuntu:
data "aws_ami" "ubuntu" {
architecture = "x86_64"
arn = "arn:aws:ec2:us-west-2::image/ami-0026a04369a3093cc"
block_device_mappings = [
{
device_name = "/dev/sda1"
ebs = {
"delete_on_termination" = "true"
"encrypted" = "false"
"iops" = "0"
"snapshot_id" = "snap-051c478203945e90f"
"throughput" = "0"
"volume_size" = "8"
"volume_type" = "gp3"
}
## ...
}
}
当你使用 Terraform 规划和应用对你的工作区的基础设施的更改时,Terraform 会比较你的状态文件中的上次已知状态、你的当前配置以及你的提供程序返回的数据,以创建其执行计划。
你的状态文件可能包含关于你的基础设施的敏感信息,例如密码或安全密钥,因此你必须安全地存储你的状态文件,并限制对只有需要使用 Terraform 管理你的基础设施的人员的访问。默认情况下,Terraform 在本地创建你的状态文件。随着你的基础设施运营的成熟,使用 HCP Terraform 远程存储你的状态将让你更容易与你的团队协作并保持你的状态文件安全。
继续学习下一个教程,了解如何修改你的基础设施。
交互式终端
您可以在我们的交互式终端中学习如何在不设置云账户的情况下创建您的基础设施。
启动终端
本教程包括一个免费的交互式命令行实验室,您可以跟随实际云基础设施进行操作。