我花了无数个小时在 AWS 控制台里点来点去,手动启动 EC2 实例、配置安全组,最后难免犯错,调试又要耗掉好几个小时。这听起来是否很熟悉?您会在错误的可用区创建实例,忘了给资源打标签,或者因为没有记录步骤,只能花一个下午把上个月搭好的配置一模一样重做一遍。
手动配置基础设施不仅乏味,还容易出错、难以扩展、无法审计。Terraform 正是在这里改变一切。想象一下,您把整个 AWS 基础设施都定义在可版本化的文本文件中,可以审查并自动部署。再也不用点几十个页面,也不会和团队上演“但它在我机器上能跑”的对话。
在本教程中,我将演示如何使用 Terraform 自动化 AWS 基础设施,聚焦一个真实案例:预置一个带自动引导安装 SSM(Systems Manager)代理的 EC2 实例。读完后,您将理解基础设施即代码的基本原理,并拥有可立即在自己 AWS 账户中部署的可用代码。
如果您是 AWS 新手,建议先学习我们的课程,如 AWS 概念、Python 中的 AWS Boto 入门,或 AWS 安全与成本管理。
Terraform 是由 HashiCorp 创建的开源基础设施即代码(IaC)工具,允许您使用 HashiCorp 配置语言(HCL)定义、预置和管理云资源。
您无需在云控制台中点选或编写命令式 bash 脚本,而是在配置文件中声明所需的基础设施,Terraform 会处理实现所需的细节。从命令式到声明式的转变,代表了我们思考云资源方式的根本变化。

命令式 vs. 声明式方式启动 AWS EC2 实例
使用命令式方法,您要写出逐步指令:“先创建这个安全组,然后等待其创建完成,再用该安全组启动这个实例,然后挂载这个卷,接着创建这些标签。”您需要对精确的执行顺序负责,并在每一步处理错误。
采用 Terraform 的声明式方法,您只需定义最终状态:“我想要一个EC2 实例,具备这些规格,连接到这个安全组,并带有这些标签。”Terraform 会分析依赖关系、确定正确顺序并执行计划。如果某处失败,Terraform 确切知道进度停在哪一步。
为什么在 AWS 上首选 Terraform?
- 首先,社区生态极为庞大,几乎所有 AWS 服务都能找到模块、示例和解决方案。
- 其次,Terraform 与云服务商解耦。学会一次,跨 AWS、Azure、GCP 及其他平台都能复用同样的技能与模式。在保持一致工作流的同时,避免厂商锁定。
- 第三,Terraform 的状态管理系统会跟踪每个资源,使更新和变更可预测。它知道您创建了什么,并能安全地修改或销毁。
在动手配置之前,您需要理解构成 Terraform 基石的三个关键概念:
- Resources(资源)是您创建的基础设施组件——EC2 实例、S3 存储桶、安全组。
- Providers(提供商)是让 Terraform 与不同平台交互的插件;AWS 提供商会把您的 HCL 翻译为 AWS API 调用。
- HCL 是用于定义基础设施的人类可读语法,既具表达力又简洁。
理解这些基础后,我们来准备环境,开始构建真实的基础设施。
在编写任何 Terraform 代码前,您需要安装 CLI 并配置 AWS 凭证。我来带您一步步完成。
安装 Terraform 会因操作系统而异:
-
在 macOS 上使用 Homebrew:先用 brew tap hashicorp/tap 安装 HashiCorp 源,再用 brew install hashicorp/tap/terraform 安装 Terraform。
-
在 Windows 上,从 hashicorp.com 下载二进制并加入 PATH,或使用 Chocolatey:choco install terraform。
-
在 Linux 上,下载相应软件包或使用发行版的包管理器。
安装完成后,运行 terraform version 验证安装。
配置 AWS 凭证
配置 AWS 凭证需要一个AWS 账户、一个访问密钥和 IAM 中的密钥。切勿使用根账户。请创建一个具有编程访问权限且具备适当权限(AdministratorAccess)的 IAM 用户。标准做法是在 ~/.aws/credentials 使用 AWS 凭证文件:
[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY技术支持
或者,设置环境变量:AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY。在生产环境中,应使用附加到 EC2 实例或 CI/CD 系统的 IAM 角色,而非长期有效的凭证。
如果您考虑使用亚马逊以外的生态,或希望全局了解“三大云”的对比,推荐阅读这份AWS、Azure 与 GCP 在数据科学与 AI 方面的服务对比。
基础打好后,我们来构建一个实战示例:一个 EC2 实例在启动时自动安装 SSM 代理。
设置项目结构
Terraform 项目受益于清晰的结构化组织。创建三个文件:main.tf 用于资源定义,variables.tf 用于输入参数,outputs.tf 用于部署后需要的值。这样的分离能保持代码有序、易维护。
aws-terraform
├── main.tf
├── output.tf
└── variables.tf技术支持
原因如下:随着项目增长,把所有内容混在一个文件会难以维护。变量让您通过改变输入,把同一份代码复用于不同环境(开发、预发布、生产)。输出能提供实例 ID 或 IP 地址等值,而无需在 AWS 控制台中手动查找。
编写 EC2 资源配置
现在来创建基础设施:一个预装 SSM 代理的 EC2 实例。在 main.tf 文件中加入以下配置:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
data "aws_ami" "amazon_linux" {
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["amazon"]
}
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
user_data = <<-EOF
#!/bin/bash
cd /tmp
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent
EOF
tags = {
Name = "TerraformWebServer"
}
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ec2-ssm-profile"
role = aws_iam_role.ssm_role.name
}
resource "aws_iam_role" "ssm_role" {
name = "ec2-ssm-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "ssm_policy" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}技术支持

Terraform EC2 实例配置
data 块会向 AWS 查询最新的 Amazon Linux 2 AMI。过滤器确保拿到正确的镜像类型,而 owners = ["amazon"] 则确保使用亚马逊官方 AMI。这种方式可在所有区域通用——Terraform 会自动找到正确的区域 AMI。
关键在于 user_data:一段在实例首次启动时运行的 shell 脚本。它会下载并安装 SSM 代理,并设置为开机自启。IAM 角色为 SSM 管理该实例提供所需权限。
同样的模式适用于任何代理。想要 CloudWatch 日志与指标?只需修改 user_data 脚本安装 CloudWatch 代理即可。原则不变:定义您想安装的内容,Terraform 确保每个实例都按要求完成。
在 output.tf 文件中,您可以添加例如实例 ID 的输出。随后,在下一章将介绍的所有 Terraform 命令运行后,该值会显示在终端中。
output "instance_id" {
description = "EC2 instance ID for SSM connection"
value = aws_instance.web_server.id
}技术支持
初始化并应用配置
配置写好后,Terraform 的工作流包含三个命令。首先,下面的命令会下载 AWS 提供商插件并准备您的目录:
terraform init技术支持

terraform init
其次,terraform plan 会准确展示 Terraform 将创建、修改或销毁的内容。这个预览能帮助您在真正变更之前发现错误:
terraform plan技术支持

terraform plan
请仔细审阅输出。您将看到 Terraform 将创建的 EC2 实例、IAM 角色、实例配置文件和策略关联。
最后,terraform apply 会执行变更。Terraform 在继续之前会要求确认。运行该命令后输入 yes:
terraform apply技术支持

terraform apply
若一切顺利,资源创建完成后您会看到如下信息。

确认:已创建 Terraform 资源
几分钟内,您就能获得一台已配置 SSM 的 EC2 实例,无需 SSH 密钥即可访问。请在 AWS 控制台中查看新创建的资源。
运行上述命令后,目录中会出现一个名为 terraform.tfstate 的新文件。Terraform 的状态文件将您的配置映射到真实的 AWS 资源。让我们一起了解该文件的内容。
理解状态文件
状态文件包含已部署基础设施的每个细节:资源 ID、IP 地址、依赖关系。Terraform 会把该状态与您的配置及 AWS 的实际状态进行比较,以决定采取何种操作。丢失状态文件,就等于 Terraform 失去了对已创建一切的跟踪。
把状态保存在本地电脑上很危险。电脑崩溃,状态就没了。多名成员协作时,本地状态冲突会导致损坏。解决方案:远程状态存储。
想深入了解 S3 与 EFS,请查看这篇AWS 存储教程。
配置远程 S3 后端
Terraform 的 S3 后端会把状态存储在一个集中、耐久的位置,团队所有成员都可访问。首先,创建一个 S3 存储桶:
aws s3api create-bucket \
--bucket datacamp-terraform-state \
--region eu-central-1 \
--create-bucket-configuration LocationConstraint=eu-central-1
aws s3api put-bucket-versioning \
--bucket datacamp-terraform-state \
--versioning-configuration Status=Enabled技术支持
版本控制至关重要:它让您可以通过回滚到先前版本,从意外中恢复。
现在,把后端配置加入到 Terraform 代码中:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
backend "s3" {
bucket = "datacamp-terraform-state"
key = "terraform.tfstate"
region = "eu-central-1"
use_lockfile = true
}
}技术支持
再次运行 terraform init 将本地状态迁移到 S3。Terraform 在移动状态文件前会要求确认。

Terraform S3 远程后端
运行命令后,S3 存储桶中应已包含新的状态文件。您可以在 AWS 控制台中查看。
使用原生 S3 锁文件锁定状态
您可能注意到我们在 main.tf 文件中添加了这行:use_lockfile = true。此设置启用 Terraform 的最新功能:原生 S3 状态锁。此前,您需要单独的 DynamoDB 表来实现锁定。

Terraform 状态锁
这种简化让您的基础设施搭建少用了一项 AWS 服务,同时仍能提供同样的竞态保护。多位工程师可以安全协作,确保同一时间只有一个人的变更会被应用。
随着基础设施增长,硬编码值与复制粘贴的代码会变成维护噩梦。Terraform 的变量系统与模块能解决这些问题。
用输入变量重构
之前我们创建了 variables.tf 文件。现在,您可以把此前在 main.tf 中硬编码的值移入这个用于存放变量的新文件:
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "eu-central-1"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}技术支持
现在在 main.tf 中的资源里引用这些变量:
provider "aws" {
region = var.aws_region
}
resource "aws_instance" "web_server" {
instance_type = var.instance_type
# ... rest of configuration
tags = {
Environment = var.environment
}
}技术支持
注意,AWS S3 存储桶是全局唯一的,因此在 main.tf 的 backend 参数中,区域不能使用变量。这里必须保留硬编码的区域,比如 “eu-central-1”,而不能用 var.region_aws。
变量既然已经定义,您也可以定义不同环境(如开发或生产),其中变量值有所不同。这可以通过创建扩展名为 .tfvars 的新文件来完成。
例如,您可以创建用于开发的 terraform-dev.tfvars 和用于生产的 terraform-prod.tfvars:
开发环境:
aws_region = "eu-central-1"
instance_type = "t2.micro"技术支持
生产环境:
aws_region = "eu-central-1"
instance_type = "t3.medium"技术支持
然后,通过指定相应文件来部署到不同环境:
terraform apply -var-file="terraform-dev.tfvars”技术支持
变量解决了环境特定值的问题,但如果要复用整套基础设施模式怎么办?这时模块就至关重要了。
创建可复用的资源模块
模块将相关资源封装为可复用组件。最佳实践是创建专门的文件夹。例如,您可以创建如下目录结构:
modules/
ec2-with-ssm/
main.tf
variables.tf
outputs.tf技术支持
您可以把先前创建的 variables.tf 文件移到模块文件夹(或新建一个)。关键变化在 main.tf 文件。模块中的 main.tf 应包含我们的资源,因此从 AMI 开始到文件末尾的内容都应移到这里:
data "aws_ami" "amazon_linux" {
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["amazon"]
}
resource "aws_instance" "web_server" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
user_data = <<-EOF
#!/bin/bash
cd /tmp
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent
EOF
tags = {
Name = "TerraformWebServer"
}
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ec2-ssm-profile"
role = aws_iam_role.ssm_role.name
}
resource "aws_iam_role" "ssm_role" {
name = "ec2-ssm-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "ssm_policy" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}技术支持
为替代这些变更,您在主配置中保留其余内容,但新增一个指向特定模块的 module 参数。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
backend "s3" {
bucket = "datacamp-terraform-state"
key = "terraform.tfstate"
region = "eu-central-1"
use_lockfile = true
}
}
provider "aws" {
region = var.aws_region
}
module "web_server" {
source = "./modules/ec2-with-ssm"
instance_type = var.instance_type
}技术支持
现在,按此前的方式运行 init、plan 和 apply,您会部署与之前相同的资源。不同之处在于,模块让您以可复用的相似配置快速启动基础设施,这是将 Terraform 扩展到更复杂项目的关键。
接下来,我们转入另一个重要主题:安全。
基础设施代码需要与应用代码同等的安全严格性。因此,保护您的 Terraform 部署至关重要。
管理机密与敏感数据
切勿把机密提交到 Git。绝对不要。请使用 AWS Secrets Manager 存储敏感值。您可以在 Terraform 中使用如下资源:
resource "aws_secretsmanager_secret" "example" {
name = "example"
}技术支持
对于特定环境的机密,您可以使用带有 TF_VAR_ 前缀的环境变量。
例如,您可以在 variables.tf 文件中使用 variable "aws_access_key" {},并在终端用 export TF_VAR_aws_access_key=<access_key_value> 导出。Terraform 会自动加载这些变量值,而无需在代码中暴露。
处理配置漂移
另一个重要的配置主题是漂移。当有人绕过 Terraform,直接通过 AWS 控制台或 CLI 修改基础设施时就会发生。请经常运行 terraform plan 检测漂移。计划输出会显示与配置不匹配的资源。
出现漂移时,您有两种选择:若手动更改是有意为之,则更新 Terraform 代码以匹配现实;否则运行 terraform apply 将基础设施强制回到代码定义的目标状态。正确选择取决于手动更改是否是出于目的。
清理资源
最后,在确定不再需要时移除所有资源也很重要,以避免不必要的成本。您可以使用以下命令清理资源:
terraform destroy技术支持
请仔细审阅销毁计划。Terraform 会删除它创建的每个资源。对于生产环境,考虑使用 terraform destroy -target 只移除特定资源,而非全部。
结论
您已经学会了 Terraform 的核心流程:用代码定义基础设施,用 plan 预览变更,用 apply 应用变更,并通过状态管理跟踪一切。我们涵盖了自动安装代理的 EC2 部署、将状态迁移到带原生锁定的 S3、通过变量与模块实现扩展,以及用机密管理保障安全。
请以对待应用代码的同等严谨来对待基础设施代码。使用版本控制,对变更进行代码审查,并先在非生产环境测试。CI/CD 流水线可自动执行 terraform apply,让基础设施更新如同应用发布一样顺畅。
下一步:探索 GitHub Actions 或 GitLab CI,在您推送代码时自动运行 Terraform。基础设施即代码与自动化结合,能重塑团队管理云资源的方式,以可靠、可复现、受版本控制的基础设施替代手工控制台操作。
我的建议是在此基础上继续进阶,报名 AWS 云从业者(CLF-C02) 技能路径,它会教会您获得亚马逊 CLF-C02 认证所需的一切。
我花了无数个小时在 AWS 控制台里点来点去,手动启动 EC2 实例、配置安全组,最后难免犯错,调试又要耗掉好几个小时。这听起来是否很熟悉?您会在错误的可用区创建实例,忘了给资源打标签,或者因为没有记录步骤,只能花一个下午把上个月搭好的配置一模一样重做一遍。
手动配置基础设施不仅乏味,还容易出错、难以扩展、无法审计。Terraform 正是在这里改变一切。想象一下,您把整个 AWS 基础设施都定义在可版本化的文本文件中,可以审查并自动部署。再也不用点几十个页面,也不会和团队上演“但它在我机器上能跑”的对话。
在本教程中,我将演示如何使用 Terraform 自动化 AWS 基础设施,聚焦一个真实案例:预置一个带自动引导安装 SSM(Systems Manager)代理的 EC2 实例。读完后,您将理解基础设施即代码的基本原理,并拥有可立即在自己 AWS 账户中部署的可用代码。
如果您是 AWS 新手,建议先学习我们的课程,如 AWS 概念、Python 中的 AWS Boto 入门,或 AWS 安全与成本管理。
什么是 Terraform?
Terraform 是由 HashiCorp 创建的开源基础设施即代码(IaC)工具,允许您使用 HashiCorp 配置语言(HCL)定义、预置和管理云资源。
您无需在云控制台中点选或编写命令式 bash 脚本,而是在配置文件中声明所需的基础设施,Terraform 会处理实现所需的细节。从命令式到声明式的转变,代表了我们思考云资源方式的根本变化。
命令式 vs. 声明式方式启动 AWS EC2 实例
使用命令式方法,您要写出逐步指令:“先创建这个安全组,然后等待其创建完成,再用该安全组启动这个实例,然后挂载这个卷,接着创建这些标签。”您需要对精确的执行顺序负责,并在每一步处理错误。
采用 Terraform 的声明式方法,您只需定义最终状态:“我想要一个EC2 实例,具备这些规格,连接到这个安全组,并带有这些标签。”Terraform 会分析依赖关系、确定正确顺序并执行计划。如果某处失败,Terraform 确切知道进度停在哪一步。
为什么在 AWS 上首选 Terraform?
在动手配置之前,您需要理解构成 Terraform 基石的三个关键概念:
理解这些基础后,我们来准备环境,开始构建真实的基础设施。
设置 Terraform 的 AWS 环境
在编写任何 Terraform 代码前,您需要安装 CLI 并配置 AWS 凭证。我来带您一步步完成。
安装 Terraform
安装 Terraform 会因操作系统而异:
在 macOS 上使用 Homebrew:先用
brew tap hashicorp/tap安装 HashiCorp 源,再用brew install hashicorp/tap/terraform安装 Terraform。在 Windows 上,从 hashicorp.com 下载二进制并加入 PATH,或使用 Chocolatey:
choco install terraform。在 Linux 上,下载相应软件包或使用发行版的包管理器。
安装完成后,运行
terraform version验证安装。配置 AWS 凭证
配置 AWS 凭证需要一个AWS 账户、一个访问密钥和 IAM 中的密钥。切勿使用根账户。请创建一个具有编程访问权限且具备适当权限(
AdministratorAccess)的 IAM 用户。标准做法是在~/.aws/credentials使用 AWS 凭证文件:或者,设置环境变量:
AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY。在生产环境中,应使用附加到 EC2 实例或 CI/CD 系统的 IAM 角色,而非长期有效的凭证。如果您考虑使用亚马逊以外的生态,或希望全局了解“三大云”的对比,推荐阅读这份AWS、Azure 与 GCP 在数据科学与 AI 方面的服务对比。
在 AWS 上使用 Terraform 部署带代理的 EC2
基础打好后,我们来构建一个实战示例:一个 EC2 实例在启动时自动安装 SSM 代理。
设置项目结构
Terraform 项目受益于清晰的结构化组织。创建三个文件:
main.tf用于资源定义,variables.tf用于输入参数,outputs.tf用于部署后需要的值。这样的分离能保持代码有序、易维护。原因如下:随着项目增长,把所有内容混在一个文件会难以维护。变量让您通过改变输入,把同一份代码复用于不同环境(开发、预发布、生产)。输出能提供实例 ID 或 IP 地址等值,而无需在 AWS 控制台中手动查找。
编写 EC2 资源配置
现在来创建基础设施:一个预装 SSM 代理的 EC2 实例。在
main.tf文件中加入以下配置:Terraform EC2 实例配置
data块会向 AWS 查询最新的 Amazon Linux 2 AMI。过滤器确保拿到正确的镜像类型,而owners = ["amazon"]则确保使用亚马逊官方 AMI。这种方式可在所有区域通用——Terraform 会自动找到正确的区域 AMI。关键在于
user_data:一段在实例首次启动时运行的 shell 脚本。它会下载并安装 SSM 代理,并设置为开机自启。IAM 角色为 SSM 管理该实例提供所需权限。同样的模式适用于任何代理。想要 CloudWatch 日志与指标?只需修改
user_data脚本安装 CloudWatch 代理即可。原则不变:定义您想安装的内容,Terraform 确保每个实例都按要求完成。在
output.tf文件中,您可以添加例如实例 ID 的输出。随后,在下一章将介绍的所有 Terraform 命令运行后,该值会显示在终端中。初始化并应用配置
配置写好后,Terraform 的工作流包含三个命令。首先,下面的命令会下载 AWS 提供商插件并准备您的目录:
terraform init
其次,
terraform plan会准确展示 Terraform 将创建、修改或销毁的内容。这个预览能帮助您在真正变更之前发现错误:terraform plan
请仔细审阅输出。您将看到 Terraform 将创建的 EC2 实例、IAM 角色、实例配置文件和策略关联。
最后,
terraform apply会执行变更。Terraform 在继续之前会要求确认。运行该命令后输入 yes:terraform apply
若一切顺利,资源创建完成后您会看到如下信息。
确认:已创建 Terraform 资源
几分钟内,您就能获得一台已配置 SSM 的 EC2 实例,无需 SSH 密钥即可访问。请在 AWS 控制台中查看新创建的资源。
在 AWS S3 上管理 Terraform 状态
运行上述命令后,目录中会出现一个名为
terraform.tfstate的新文件。Terraform 的状态文件将您的配置映射到真实的 AWS 资源。让我们一起了解该文件的内容。理解状态文件
状态文件包含已部署基础设施的每个细节:资源 ID、IP 地址、依赖关系。Terraform 会把该状态与您的配置及 AWS 的实际状态进行比较,以决定采取何种操作。丢失状态文件,就等于 Terraform 失去了对已创建一切的跟踪。
把状态保存在本地电脑上很危险。电脑崩溃,状态就没了。多名成员协作时,本地状态冲突会导致损坏。解决方案:远程状态存储。
想深入了解 S3 与 EFS,请查看这篇AWS 存储教程。
配置远程 S3 后端
Terraform 的 S3 后端会把状态存储在一个集中、耐久的位置,团队所有成员都可访问。首先,创建一个 S3 存储桶:
版本控制至关重要:它让您可以通过回滚到先前版本,从意外中恢复。
现在,把后端配置加入到 Terraform 代码中:
再次运行
terraform init将本地状态迁移到 S3。Terraform 在移动状态文件前会要求确认。Terraform S3 远程后端
运行命令后,S3 存储桶中应已包含新的状态文件。您可以在 AWS 控制台中查看。
使用原生 S3 锁文件锁定状态
您可能注意到我们在
main.tf文件中添加了这行:use_lockfile = true。此设置启用 Terraform 的最新功能:原生 S3 状态锁。此前,您需要单独的 DynamoDB 表来实现锁定。Terraform 状态锁
这种简化让您的基础设施搭建少用了一项 AWS 服务,同时仍能提供同样的竞态保护。多位工程师可以安全协作,确保同一时间只有一个人的变更会被应用。
用 Terraform 在 AWS 上扩展基础设施
随着基础设施增长,硬编码值与复制粘贴的代码会变成维护噩梦。Terraform 的变量系统与模块能解决这些问题。
用输入变量重构
之前我们创建了
variables.tf文件。现在,您可以把此前在main.tf中硬编码的值移入这个用于存放变量的新文件:现在在
main.tf中的资源里引用这些变量:注意,AWS S3 存储桶是全局唯一的,因此在
main.tf的backend参数中,区域不能使用变量。这里必须保留硬编码的区域,比如“eu-central-1”,而不能用var.region_aws。变量既然已经定义,您也可以定义不同环境(如开发或生产),其中变量值有所不同。这可以通过创建扩展名为
.tfvars的新文件来完成。例如,您可以创建用于开发的
terraform-dev.tfvars和用于生产的terraform-prod.tfvars:开发环境:
生产环境:
然后,通过指定相应文件来部署到不同环境:
变量解决了环境特定值的问题,但如果要复用整套基础设施模式怎么办?这时模块就至关重要了。
创建可复用的资源模块
模块将相关资源封装为可复用组件。最佳实践是创建专门的文件夹。例如,您可以创建如下目录结构:
您可以把先前创建的
variables.tf文件移到模块文件夹(或新建一个)。关键变化在main.tf文件。模块中的main.tf应包含我们的资源,因此从 AMI 开始到文件末尾的内容都应移到这里:为替代这些变更,您在主配置中保留其余内容,但新增一个指向特定模块的 module 参数。
现在,按此前的方式运行
init、plan和apply,您会部署与之前相同的资源。不同之处在于,模块让您以可复用的相似配置快速启动基础设施,这是将 Terraform 扩展到更复杂项目的关键。接下来,我们转入另一个重要主题:安全。
在 AWS 上使用 Terraform 的安全最佳实践
基础设施代码需要与应用代码同等的安全严格性。因此,保护您的 Terraform 部署至关重要。
管理机密与敏感数据
切勿把机密提交到 Git。绝对不要。请使用 AWS Secrets Manager 存储敏感值。您可以在 Terraform 中使用如下资源:
对于特定环境的机密,您可以使用带有
TF_VAR_前缀的环境变量。例如,您可以在
variables.tf文件中使用variable "aws_access_key" {},并在终端用export TF_VAR_aws_access_key=<access_key_value>导出。Terraform 会自动加载这些变量值,而无需在代码中暴露。处理配置漂移
另一个重要的配置主题是漂移。当有人绕过 Terraform,直接通过 AWS 控制台或 CLI 修改基础设施时就会发生。请经常运行
terraform plan检测漂移。计划输出会显示与配置不匹配的资源。出现漂移时,您有两种选择:若手动更改是有意为之,则更新 Terraform 代码以匹配现实;否则运行
terraform apply将基础设施强制回到代码定义的目标状态。正确选择取决于手动更改是否是出于目的。清理资源
最后,在确定不再需要时移除所有资源也很重要,以避免不必要的成本。您可以使用以下命令清理资源:
请仔细审阅销毁计划。Terraform 会删除它创建的每个资源。对于生产环境,考虑使用
terraform destroy -target只移除特定资源,而非全部。结论
您已经学会了 Terraform 的核心流程:用代码定义基础设施,用
plan预览变更,用apply应用变更,并通过状态管理跟踪一切。我们涵盖了自动安装代理的 EC2 部署、将状态迁移到带原生锁定的 S3、通过变量与模块实现扩展,以及用机密管理保障安全。请以对待应用代码的同等严谨来对待基础设施代码。使用版本控制,对变更进行代码审查,并先在非生产环境测试。CI/CD 流水线可自动执行
terraform apply,让基础设施更新如同应用发布一样顺畅。下一步:探索 GitHub Actions 或 GitLab CI,在您推送代码时自动运行 Terraform。基础设施即代码与自动化结合,能重塑团队管理云资源的方式,以可靠、可复现、受版本控制的基础设施替代手工控制台操作。
我的建议是在此基础上继续进阶,报名 AWS 云从业者(CLF-C02) 技能路径,它会教会您获得亚马逊 CLF-C02 认证所需的一切。