打破硬件限制:如何用Sunshine打造你的个人游戏串流服务器
Terraform on AWS 入门实战:从 EC2 实例部署到状态管理、CI/CD、成本估算与模块复用
本篇指南聚焦于使用 HashiCorp 的 Terraform 在 Amazon Web Services(AWS)上做基础设施即代码(IaC)的完整落地路径。你将掌握从 AWS 凭证配置、编写第一个 main.tf 部署 EC2 实例,到 Terraform 状态远端化、多环境 Workspace 管理、CI/CD 自动化、资源依赖处理、成本估算与密钥管理的实战方案,读完即可独立完成一套可维护、可协作、可审计的 AWS 基础设施交付流程。本文整理自 Refine 文档站的生态集成博客(documentation/blog/2024-09-12-terraform-aws.md),并结合仓库内的文档站配置做了路径与上下文的校正。
为什么用 Terraform 管理 AWS 基础设施
随着应用规模扩大,跨多环境、多区域的基础设施管理成为运维痛点:手工在控制台上点选资源既枯燥又易错,而自行编写脚本又需要大量工程投入。Terraform 这类 IaC 工具给出的解法是——用声明式的可复用配置来定义一切资源,从存储桶到 Kubernetes 集群都可以通过配置文件拉起。
本指南面向初学者,按以下脉络展开:
- 前置条件:AWS 账户与凭证、AWS CLI、Terraform 安装;
- 为 Terraform 配置 AWS 访问凭证;
- 编写第一个 Terraform 配置并部署一台 EC2 实例;
- 状态管理(S3 远端 State)、多环境 Workspaces、安全最佳实践;
- 用 CI/CD 流水线自动化 Terraform;
- 处理资源依赖、修改已有基础设施、销毁清理;
- 成本估算、敏感数据管理、模块复用。
无论你是已经在用 AWS、还是想以 IaC 方式探索 AWS,这套流程都能覆盖绝大多数基础设施的交付场景。
前置条件
开始用 Terraform 管理 AWS 基础设施之前,需要准备三样东西:
AWS 账户与凭证
需要一个 AWS 账户(免费注册即可)。创建账户时会得到一个拥有全部权限的 root 用户。
按安全最佳实践,你应该为 Terraform 单独创建一个权限受限的 IAM 用户:在 IAM 服务中新建一个用户,并妥善保存生成的 Access Key 与 Secret Access Key——Terraform 将使用这对密钥对 AWS 账户进行身份认证与操作。
AWS CLI
AWS CLI 允许你从命令行管理 AWS 服务。按你的操作系统下载安装后,运行 aws configure,按提示填入 Access Key 完成配置:
aws configure
Terraform 本体
Terraform 以单一二进制文件形式分发。为你的系统下载对应的 Terraform 二进制后,即可在终端执行 Terraform 命令。记得将其加入 PATH 环境变量,保证全局可用:
# 验证安装
terraform version
配置 Terraform 使用的 AWS 凭证
账户与工具就绪后,需要为 Terraform 配置与 AWS 交互的访问凭证。常见的两种方式是:
方式一:环境变量(Access Key / Secret Key)
创建 IAM 用户时 AWS 生成的 Access Key 与 Secret Key,相当于程序化访问 AWS API 的"用户名 + 密码"。可以直接通过环境变量传给 Terraform:
export AWS_ACCESS_KEY_ID=<your_access_key>
export AWS_SECRET_ACCESS_KEY=<your_secret_key>
Terraform 在需要凭证时会主动检查这两个环境变量。
方式二:~/.aws/credentials 文件
另一种做法是把密钥保存进 AWS CLI 默认读取的本地凭证文件(Linux/macOS 上位于 ~/.aws/credentials):
[default]
aws_access_key_id = <your_access_key>
aws_secret_access_key = <your_secret_key>
Terraform 会自动检查该文件。两种途径配置好之后,Terraform 就具备在你的 AWS 账户中构建基础设施的能力了。
补充说明:Terraform 的 AWS Provider 实际上遵循一套标准凭证链(环境变量 →
~/.aws/credentials→ 实例元数据 / 角色等),上述两种方式是最常用的前两级。原文仅演示了前两种,实际项目中还会用到 IAM Role、~/.aws/config中切换 profile 等途径,可按需扩展。
编写第一个 Terraform 配置:部署 EC2 实例
Terraform 代码使用 HCL(HashiCorp Configuration Language) 编写,配置文件以 .tf 结尾,用于声明 Provider 与资源。
声明 AWS Provider
按 AWS Provider 的文档要求,创建 main.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
要点说明:
required_providers显式声明依赖的 Provider 及其来源与版本约束。~> 5.0表示兼容 5.x 系列;对生产环境,更严格的版本钉扎(如精确到小版本)可以减少意外升级带来的破坏。provider "aws"块中的region = "us-east-1"决定了后续资源默认创建在哪个区域。
定义 EC2 实例资源
接下来定义一台 EC2 实例:
resource "aws_instance" "refine-dev" {
ami = "ami-0fc5d935ebf8bc3bc"
instance_type = "t2.micro"
tags = {
Name = "refine-dev"
}
}
ami:镜像 ID。原文使用了一个 us-east-1 区域的免费 Linux 镜像(Ubuntu)。注意 AMI ID 是区域相关的,换区域时需要在 EC2 控制台的 AMI 列表里重新确认,或使用data源按名称动态查询,这是原文没有展开的一个常见坑点;instance_type = "t2.micro":属于 AWS 免费额度(Free Tier)覆盖的规格,适合入门实验,避免产生意外账单;tags中的Name让实例在控制台中可读、可检索。
合并后完整的 main.tf 如下:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "refine-dev" {
ami = "ami-0fc5d935ebf8bc3bc"
instance_type = "t2.micro"
}
init / plan / apply:Terraform 的标准工作流
配置就绪后,按三步执行:
terraform init
初始化 Terraform 工作目录,并下载 AWS Provider 插件。
terraform plan
Terraform 读取配置文件,计算并输出将要创建的基础设施(资源清单与变更计划)。确认计划无误后执行:
terraform apply
Terraform 调用 AWS API 实际创建出这台 EC2 实例。init → plan → apply 这条链路是 Terraform 的核心循环,后续的修改、销毁都围绕它展开。
状态管理:把 State 放到 S3 远端后端
Terraform 通过 State 文件追踪它所管理的基础设施。State 记录了"配置应该是什么样"与"云上实际是什么样"之间的映射,是 Terraform 做差异计算(plan)的依据。
默认 State 保存在本地 .terraform.tfstate 文件中,这在团队协作中会引发覆盖与冲突问题。推荐做法是把 State 存储到 AWS S3 等远端后端,让团队成员共享同一份状态:
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "terraform.tfstate"
region = "us-west-2"
}
}
配置远端 State 后,团队成员读写的是同一份状态文件,避免互相覆盖。生产环境通常还会在 S3 backend 上叠加 DynamoDB 状态锁(dynamodb_table 参数)来防止两个 apply 并发执行;从源码结构看这类配置属于 backend 块的可选参数,可按团队规模逐步引入。
Workspaces:一份配置管理多套环境
Workspaces 允许你在同一份配置上维护 dev、staging、production 等独立环境——每个 Workspace 拥有独立的 State,而无需复制多份配置文件:
terraform workspace new dev
terraform workspace new prod
terraform workspace select dev
select 切换后,后续 plan / apply 操作的都将是该 Workspace 的独立状态。这为"一套配置、多套环境"提供了轻量的多环境管理方案;配合变量文件(如 dev.tfvars / prod.tfvars)可以实现环境与参数解耦。
安全最佳实践:IAM 角色与策略
基础设施的安全核心在于最小权限。两个方面值得在配置中落实:
为 EC2 实例绑定 IAM 角色
避免把长期有效的 Access Key 硬编码进实例或代码里,改用 IAM 实例角色,让实例通过角色临时获取凭证。原文给出的示例:
resource "aws_iam_instance_profile" "ec2_profile" {
name = "example_profile"
role = aws_iam_role.ec2_role.name
}
resource "aws_instance" "example" {
ami = "ami-0fc5d935ebf8bc3bc"
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.ec2_profile.name
}
注意:该示例引用了
aws_iam_role.ec2_role,实际使用中还需要声明对应的aws_iam_role资源(含角色信任策略与权限策略),并遵循最小权限原则——只授予实例真正需要的 API 权限。
策略执行层
原文还提到可引入 Terraform Sentinel(HashiCorp 的策略即代码产品),在 plan 与 apply 阶段强制执行安全策略,例如禁止创建公网暴露的高权限资源。这类策略门禁适合在组织层面统一部署。
用 CI/CD 流水线自动化 Terraform
把 Terraform 接入 CI/CD 流水线(如 GitHub Actions、Jenkins)后,基础设施变更与应用代码一样走"提交 → 评审 → 自动部署"的闭环。原文给出的 GitHub Actions 工作流示例:
name: Terraform Apply
on:
push:
branches:
- main
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan
- name: Terraform Apply
run: terraform apply -auto-approve
落地时的几点工程化补充:
- Secrets 注入:CI 环境中 AWS 凭证应通过流水线的密钥管理(如 Actions Secrets)注入为
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY环境变量,而不是写死在 workflow 里; init参数:使用 S3 远端 State 时,terraform init会自动读取配置中的 backend 块完成迁移,无需额外参数;- 审批环节:
-auto-approve适合低风险的 dev 环境;对生产环境,更稳妥的做法是流水线只跑plan并输出结果,apply走人工审批或受保护分支触发。
自动化后,团队的基础设施交付更快、更可复现。
处理资源依赖
Terraform 会根据配置中的引用关系自动推导资源依赖并决定创建顺序;在引用关系无法表达依赖时,才需要显式声明。原文用 depends_on 举例:
resource "aws_instance" "web" {
ami = "ami-0fc5d935ebf8bc3bc"
instance_type = "t2.micro"
}
resource "aws_elb" "web_elb" {
depends_on = [aws_instance.web]
instances = [aws_instance.web.id]
}
其中 depends_on 强制 web_elb 在 web 实例创建完成后再创建;而 instances 通过引用 aws_instance.web.id 也天然建立了依赖。实践中优先依赖"引用即依赖"的隐式推导,仅在引用不成立(例如仅需要执行顺序保证)时才使用 depends_on。
说明:原文示例中
aws_elb(第一代负载均衡器)与instance/instances参数是旧版资源写法,新版资源aws_lb(Application/Network LB)的挂载方式不同。作为理解depends_on语义的示例是够用的,生产环境请以当前 Provider 版本的资源文档为准。
修改基础设施:变更即代码
IaC 的关键价值之一是基础设施可以随代码持续演进。原文演示了一个小改动:给已存在的实例补充标签:
resource "aws_instance" "refine-dev" {
ami = "ami-0fc5d935ebf8bc3bc"
instance_type = "t2.micro"
tags = {
Name = "refine-dev"
}
}
保存后重新走一遍循环:
terraform plan
terraform apply
plan 会输出为实例添加标签所需的变更,确认后 apply 完成更新。这里需要澄清原文的一处表述:添加 tags 属于 Terraform 的原地更新(in-place update),实例不会被销毁重建;只有当变更属性无法原地修改时(例如某些网络或镜像类变更),Terraform 才会销毁并重建资源。另外,原文称更新过程会保持"同一 IP 地址"——对普通公网 IP 这并不成立,若需要固定 IP,应额外绑定 Elastic IP 并通过 aws_eip 资源管理。
用代码管理基础设施的直接收益:协作更顺畅、可接入版本控制、变更可审计可自动化——所有修改都能通过 Pull Request 评审,而不是在生产控制台上"手工热修"。
清理资源:terraform destroy
实验完成后,及时销毁资源以避免持续计费是最佳实践:
terraform destroy
Terraform 会列出所有将被销毁的资源并要求确认,输入 yes 后即可删除 AWS 上对应的基础设施(本文场景中即那台 EC2 实例及其关联的网络安全组)。
这正是声明式配置相对控制台操作的又一优势:Terraform 依据 State 精确知道"它创建过什么、要删什么",你不必手工排查孤儿资源,也不必手工解开纠缠的依赖关系。
需要重建时,随时重新 terraform apply 即可——配置代码就是唯一事实来源(single source of truth)。
成本估算:部署前用 Infracost 预知账单
意外的云账单是 IaC 流程中常见的问题。可以在部署前使用 Infracost 对 Terraform 配置做成本估算,提前看清基础设施决策的费用影响:
infracost breakdown --path=./path_to_your_terraform
它会解析你的 Terraform 配置(或 plan 文件),输出各项资源的预估月成本。将 Infracost 接入 plan 阶段或 CI 流水线后,成本影响就可以像代码评审意见一样被讨论和把关。
管理与 Secrets:别把密钥写进配置
访问密钥等敏感信息不应硬编码进 .tf 文件。两种常用手段:
环境变量传递
export AWS_ACCESS_KEY_ID=<your_access_key>
export AWS_SECRET_ACCESS_KEY=<your_secret_key>
声明 sensitive 变量
在 Terraform 配置中把变量标记为敏感,plan / apply 输出会自动隐藏其值:
variable "secret_key" {
type = string
sensitive = true
}
调用时通过 TF_VAR_ 前缀环境变量传值(如 export TF_VAR_secret_key=...)或经 CI 密钥管理注入。对更复杂的密钥体系,可进一步接入 AWS Secrets Manager,让密钥的轮换与分发由 AWS 侧统一管理。
模块(Modules):复用与组织基础设施代码
模块是 Terraform 复用和整理基础设施代码的基本单元,对 EC2 实例、VPC 这类重复性搭建尤其有用,能让代码保持 DRY(Don't Repeat Yourself)。原文的模块调用示例:
module "ec2_instance" {
source = "./modules/ec2"
instance_type = "t2.micro"
ami = "ami-0fc5d935ebf8bc3bc"
tags = {
Name = "refine-dev"
}
}
source 指向本地模块目录(也可以是远程模块地址),模块内部的 variable / output 定义其接口。通过模块,团队可以把标准组件(如"合规 VPC + 子网 + 安全组")沉淀成可复用单元,避免重复造轮子。
小结
回到 IaC 的价值主线:配置代码是基础设施的唯一事实来源。需要复现一个月前搭建的环境?直接 apply 那个历史提交即可,不必翻阅口口相传的运维笔记;变更统一走 Pull Request,与 CI/CD 流水线无缝集成,告别的正是"雪花式"的生产热修。
推荐的落地路径:先把 Terraform 配置纳入版本控制、对团队开放协作,再逐步把更多云上基础设施转化为代码——从单台 EC2 起步,最终具备用 Terraform 管理生产应用基础设施的能力。
本文整理自 Refine 文档站博客 documentation/blog/2024-09-12-terraform-aws.md(最后更新于 2024-09-12,补充了状态管理、模块、密钥、Workspace、安全、CI/CD、依赖与成本估算章节),该文档随 Refine 文档站(Docusaurus 构建,站点配置见 documentation/docusaurus.config.js)对外发布。文中 Terraform 命令与 HCL 示例可直接复制使用;AMI ID、Provider 版本与
aws_elb等 AWS 侧细节请以当前 Provider 版本和你所在区域的实际资源为准。
更多推荐




所有评论(0)