AWS 基础设施即代码深度对决:Terraform vs CloudFormation 全面对比与五大核心服务实战
AWS 生态中,基础设施即代码(Infrastructure as Code,IaC)已经从"锦上添花"变成了"必备技能"。
- 引言:为什么 IaC 选型决定架构天花板
- VPC 网络架构:谁更擅长编排复杂拓扑
- IAM 权限管理:策略即代码的两种哲学
- CloudWatch 监控与告警:可观测性即代码
- AWS Organizations 多账号治理:IaC 的终极考验
- 日常运维体验:状态管理、漂移检测与团队协作
- 终极选型决策矩阵
- 混合方案:两者并用是否可行?
引言:为什么 IaC 选型决定架构天花板
AWS 生态中,基础设施即代码(Infrastructure as Code,IaC)已经从"锦上添花"变成了"必备技能"。但在选型时,几乎所有团队都会卡在同一个问题上:Terraform 还是 CloudFormation?
这个问题看似简单,实则牵扯到 VPC 网络拓扑管理、IAM 权限边界定义、CloudWatch 监控配置、多账号组织架构部署等一系列连锁决策。选错了工具,不是写几行代码的事——是整个运维体系的重构成本。
本文不站队,不推货。我们从VPC 网络编排、IAM 策略管理、CloudWatch 可观测性、多账号 Organizations 治理、以及日常运维体验五个维度,逐一解剖两者的差异。每个维度都给出真实代码片段,让你看完就知道自己该选谁。
一个真实的选型困境
某跨境电商团队,AWS 上跑了三年,基础设施全部用 CloudFormation 管理。业务扩展到东南亚后开始用阿里云国际版做本地化部署。运维负责人面临两难:要么在阿里云手动管资源、要么引入 Terraform 统一编排。最终他们选择用 Terraform 管理跨云核心网络(VPC 互通、域名解析),保留 CloudFormation 管 AWS 应用层。这个"双轨制"运行了一年,结果是:运维脚本减少 60%,但团队学习曲线陡峭了三个月。
这个案例说明一个核心事实:IaC 工具的选择不是纯技术问题,而是团队能力、业务版图、现有资产三者权衡的结果。下面我们从五个维度展开这个权衡过程。
一、VPC 网络架构:谁更擅长编排复杂拓扑
1.1 CloudFormation 的 VPC 定义方式
CloudFormation 对 AWS 资源的覆盖是天级同步的——新服务发布当天就能用。定义 VPC 及其组件(子网、路由表、NAT 网关、Internet 网关)完全原生:
// CloudFormation YAML
Resources:
MainVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Name
Value: MainVPC
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MainVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
InternetGateway:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MainVPC
InternetGatewayId: !Ref InternetGateway
内建函数 !Ref、!GetAtt、!Select 让资源引用非常直观。但代价是:这段 YAML 只在 AWS 有效。如果你想同时管理阿里云 VPC,就得另起炉灶。
1.2 Terraform 的 VPC 定义方式
Terraform 用 HCL(HashiCorp Configuration Language)定义同样的 VPC:
// Terraform HCL
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "MainVPC"
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = data.aws_availability_zones.available.names[0]
map_public_ip_on_launch = true
}
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
}
Terraform 的资源引用用 aws_vpc.main.id 这种点号语法,比 YAML 的 !Ref 更接近编程语言习惯。更关键的是:Provider 体系让同一套语法能管理多云资源。
1.3 Transit Gateway 场景对比
| 场景 | CloudFormation | Terraform |
|---|---|---|
| TGW + 多 VPC 挂载 | 原生支持,AWS::EC2::TransitGateway + AWS::EC2::TransitGatewayAttachment | 同样原生,aws_ec2_transit_gateway + aws_ec2_transit_gateway_vpc_attachment |
| TGW 跨账号共享 | 需配合 AWS RAM,CloudFormation StackSet 分发 | 需配合 AWS RAM,Terraform aws_ram_* 资源 + 多 Provider 配置 |
| TGW 路由表管理 | 静态路由 + AWS::EC2::TransitGatewayRoute | 静态路由 + aws_ec2_transit_gateway_route,支持 for_each 批量路由 |
| 跨 Region TGW Peering | 需要在两个 Region 分别创建 Stack | 多 Provider alias 配置,一个 terraform apply 搞定 |
结论:单 Region、纯 AWS 环境,两者差异不大。跨 Region 或混合云场景,Terraform 的多 Provider 架构优势明显。
二、IAM 权限管理:策略即代码的两种哲学
2.1 CloudFormation 的 IAM 原生优势
CloudFormation 定义 IAM 角色和策略完全原生:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: S3Access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
Resource: !Sub "arn:aws:s3:::${BucketName}/*"
IAM 策略是 JSON 文档,CloudFormation 的 YAML 语法刚好与之天然兼容。
2.2 Terraform 的 IAM 定义方式
Terraform 有两种方式定义 IAM:
方式一:内联 JSON(与 CFn 类似)
resource "aws_iam_role" "lambda_role" {
name = "lambda-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
方式二:aws_iam_policy_document 数据源(推荐)
data "aws_iam_policy_document" "s3_access" {
statement {
effect = "Allow"
actions = ["s3:GetObject", "s3:PutObject"]
resources = ["${aws_s3_bucket.data.arn}/*"]
}
}
resource "aws_iam_policy" "s3_access" {
name = "s3-access-policy"
policy = data.aws_iam_policy_document.s3_access.json
}
2.3 IAM 管理对比
| 维度 | CloudFormation | Terraform |
|---|---|---|
| IAM 策略语法 | 原生 JSON/YAML,无学习成本 | jsonencode() 或 aws_iam_policy_document 数据源 |
| 权限边界(Permission Boundary) | PermissionsBoundary 属性 | permissions_boundary 参数 |
| SCP(Service Control Policy) | 无原生支持,需 Custom Resource 调用 Organizations API | aws_organizations_policy 资源 |
| IAM Access Analyzer | 手动在控制台触发 | aws_accessanalyzer_analyzer 资源可 IaC 管理 |
| 策略模拟测试 | 无 IaC 原生支持 | terraform plan 可预览变更,但不做策略语义校验 |
Terraform 的杀手锏:SCP 可以直接以资源形式管理,这对多账号 Organizations 治理至关重要。CloudFormation 要到 2023 年底才逐步补齐 Organizations 相关资源类型。
三、CloudWatch 监控与告警:可观测性即代码
3.1 CloudFormation 定义 CloudWatch
HighCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: high-cpu-alarm
AlarmDescription: CPU utilization exceeds 80%
MetricName: CPUUtilization
Namespace: AWS/EC2
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: InstanceId
Value: !Ref WebServer
AlarmActions:
- !Ref SNSTopic
配合 CloudFormation 的 AWS::CloudWatch::Dashboard 资源,你可以在一个 Stack 里同时定义资源和监控:
MainDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: MainDashboard
DashboardBody: !Sub |
{
"widgets": [
{
"type": "metric",
"properties": {
"metrics": [
["AWS/EC2", "CPUUtilization", {"stat": "Average"}]
],
"period": 300,
"title": "EC2 CPU"
}
}
]
}
3.2 Terraform 定义 CloudWatch
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
alarm_name = "high-cpu-alarm"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 300
statistic = "Average"
threshold = 80
dimensions = {
InstanceId = aws_instance.web.id
}
alarm_actions = [aws_sns_topic.alerts.arn]
}
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = "MainDashboard"
dashboard_body = jsonencode({
widgets = [{
type = "metric"
properties = {
metrics = [["AWS/EC2", "CPUUtilization", { stat = "Average" }]]
period = 300
title = "EC2 CPU"
}
}]
})
}
3.3 CloudWatch 管理对比
| 维度 | CloudFormation | Terraform |
|---|---|---|
| 告警定义 | 原生 YAML,语法直观 | HCL + jsonencode(),Dashboard 定义较繁琐 |
| 复合告警(Composite Alarm) | AWS::CloudWatch::CompositeAlarm | aws_cloudwatch_composite_alarm |
| 跨账号/跨 Region 告警 | 需 StackSet 编排 | 多 Provider 配置,天然支持 |
| Logs Insights 查询 | 无法通过 IaC 定义 | 不支持定义查询语法,但可用 aws_cloudwatch_query_definition |
| Contributor Insights | CloudFormation 原生支持 | Terraform 也支持 aws_cloudwatch_contributor_insights_rule |
| ServiceLens / X-Ray | CloudFormation 不支持 X-Ray 组 | Terraform 有 aws_xray_group、aws_xray_sampling_rule |
注意:CloudWatch Dashboard 的 JSON Body 在两种工具中都不好维护。生产环境建议用专门的监控即代码工具(如 Grafana Terraform Provider)来补充。
四、AWS Organizations 多账号治理:IaC 的终极考验
4.1 CloudFormation 的多账号方案:StackSets
CloudFormation 管理多账号的标准方案是 StackSets:
// 创建 StackSet,通过 Organizations 自动部署到所有成员账号
MyStackSet:
Type: AWS::CloudFormation::StackSet
Properties:
StackSetName: SecurityBaseline
PermissionModel: SERVICE_MANAGED
AutoDeployment:
Enabled: true
RetainStacksOnAccountRemoval: false
Capabilities:
- CAPABILITY_IAM
- CAPABILITY_NAMED_IAM
ManagedExecution:
Active: true
Parameters:
- ParameterKey: LogsRetentionDays
ParameterValue: "90"
TemplateURL: https://s3.amazonaws.com/bucket/security-baseline.yaml
StackSets 的优势是 AWS 原生集成,无需额外工具。劣势是:只支持 CloudFormation 模板,无法编排非 AWS 资源。
4.2 Terraform 的多账号方案:多 Provider + Workspace
// 定义多个 AWS Provider,指向不同账号
provider "aws" {
alias = "management"
region = "us-east-1"
}
provider "aws" {
alias = "dev"
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::222222222222:role/OrganizationAccountAccessRole"
}
}
provider "aws" {
alias = "prod"
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::333333333333:role/OrganizationAccountAccessRole"
}
}
// 在 dev 账号创建 S3 桶
resource "aws_s3_bucket" "dev_data" {
provider = aws.dev
bucket = "dev-data-bucket"
}
// 在 Organizations 管理账号创建 SCP
resource "aws_organizations_policy" "deny_public_s3" {
provider = aws.management
name = "deny-public-s3"
content = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Deny"
Action = ["s3:PutBucketPublicAccessBlock"]
Resource = ["*"]
Condition = {
StringNotEquals = {
"s3:PublicAccessBlockConfiguration" : "true"
}
}
}]
})
}
4.3 Organizations 多账号对比
| 维度 | CloudFormation (StackSets) | Terraform |
|---|---|---|
| 部署模型 | 推模式:管理账号推到成员账号 | 拉模式:以成员账号身份执行 |
| Organizations 集成 | SERVICE_MANAGED 权限模型,自动发现新账号 | 需手动配置 Provider 或遍历 aws_organizations_organization 数据源 |
| SCP 管理 | 不支持直接创建 SCP(需 Lambda 自定义资源) | aws_organizations_policy 资源,原生支持 |
| OU 结构管理 | 不支持直接创建 OU | aws_organizations_organizational_unit 资源 |
| Control Tower | 与 Control Tower 深度集成 | 可以管理 Control Tower 创建的资源,但不触发 AFT |
| 外部资源编排 | 不支持 | 同时管理 AWS + Datadog + PagerDuty + GitHub |
关键发现:如果你只管理 AWS 资源且已用 Organizations + Control Tower,StackSets 更省心。如果需要跨云、需要管理 SCP/OU 结构本身、或团队已有 Terraform 经验,Terraform 是更好的选择。
五、日常运维体验:状态管理、漂移检测与团队协作
5.1 状态管理
| 特性 | CloudFormation | Terraform |
|---|---|---|
| 状态存储 | AWS 托管(无需自行管理) | 需自行管理(S3 + DynamoDB 锁,或 Terraform Cloud) |
| 状态文件格式 | 不可见(AWS 内部管理) | JSON 明文,可审计可修复 |
| 状态锁定 | 自动(Stack 级别) | DynamoDB 或 Terraform Cloud |
| 状态回滚 | ROLLBACK 模式自动回滚 | 无自动回滚,需 terraform destroy + 重新 apply |
5.2 漂移检测(Drift Detection)
CloudFormation 的漂移检测是 AWS 原生功能:
// 检测整个 Stack 的漂移
aws cloudformation detect-stack-drift --stack-name MainStack
// 查看漂移详情
aws cloudformation describe-stack-resource-drifts --stack-name MainStack
Terraform 的漂移检测本质上是 terraform plan:
terraform plan -detailed-exitcode
// 返回 0:无变更
// 返回 1:有错误
// 返回 2:有漂移(需要变更)
| 场景 | CloudFormation | Terraform |
|---|---|---|
| 漂移检测粒度 | 资源级别,可逐个资源查询 | plan 输出所有差异 |
| 漂移修复 | 需手动或重新部署 Stack | terraform apply 自动修复 |
| 检测速度 | 快(AWS 服务端计算) | 慢(本地计算,需调用 API) |
| 第三方工具集成 | 较弱 | 丰富(Atlantis、Spacelift、Env0、Terrateam) |
5.3 模块化与复用
CloudFormation 的模块化手段:
- 嵌套 Stack:
AWS::CloudFormation::Stack资源引用外部模板 - 模块(Module):2023 年推出,注册到 CloudFormation Registry
- Include / Transform:
AWS::Include引用代码片段 - 宏(Macros):Lambda 函数预处理模板
Terraform 的模块化手段:
- Module:从 Terraform Registry 或 Git 仓库引用
for_each/count:原生循环,创建资源组local/variable:丰富的变量体系- Provider 抽象:不同 Provider 共用同一套模块语法
// Terraform 模块示例:用 for_each 批量创建多个 VPC
module "vpcs" {
source = "terraform-aws-modules/vpc/aws"
for_each = var.environments
name = "vpc-${each.key}"
cidr = each.value.cidr
azs = each.value.azs
}
CloudFormation 要达到同样的批量创建效果,需要在 YAML 里手动写多次,或用 Lambda 宏做模板预处理,复杂度明显更高。
六、终极选型决策矩阵
| 决策因子 | 选 CloudFormation | 选 Terraform |
|---|---|---|
| 技术栈 | 纯 AWS,无多云需求 | 多云 / 混合云 |
| SCP / OU 管理 | 不需要用 IaC 管 SCP | 需要用 IaC 管 SCP 和 OU 结构 |
| 团队技能 | 团队熟悉 YAML/JSON | 团队需要编程式 DSL |
| 状态管理 | 不想管状态文件 | 可以接受 S3 + DynamoDB 维护 |
| Control Tower | 深度使用 Control Tower | Control Tower 不是核心依赖 |
| 第三方集成 | 不需要外部服务编排 | 需同时编排 Datadog、PagerDuty 等 |
| 模块生态 | 只有 AWS 模块 | Terraform Registry 有超过 4000 个 Provider |
| 成本 | 免费(AWS 服务不另收费) | 开源免费,Terraform Cloud 有付费版 |
| CI/CD 集成 | CodePipeline 原生支持 | 所有主流 CI/CD 平台支持(GitHub Actions、GitLab CI、Jenkins) |
七、混合方案:两者并用是否可行?
答案是:可以,但需要明确边界。
一个越来越常见的模式是:
- Terraform 管理"基础设施的基础":Organizations OU 结构、SCP、IAM Identity Center(原 AWS SSO)、VPC 骨架、Transit Gateway、Route53 托管区
- CloudFormation 管理"应用层基础设施":Lambda 函数、API Gateway、ECS 服务、CloudWatch Dashboard(配合 Serverless Framework 或 AWS SAM)
// Terraform 创建核心 VPC,输出 VPC ID
output "main_vpc_id" {
value = aws_vpc.main.id
}
// StackSets 引用 VPC ID,部署应用 Stack 到所有账号
// 参数从 Terraform 输出获取,通过 SSM Parameter Store 传递
resource "aws_ssm_parameter" "vpc_id" {
name = "/network/main-vpc-id"
type = "String"
value = aws_vpc.main.id
}
这种分工的核心逻辑是:谁更擅长什么,就让它做什么。Terraform 强在多 Provider 编排和资源循环,CloudFormation 强在 AWS 原生集成和 StackSets 自动分发。
八、2026年最新趋势
- CloudFormation IaC Generator:从现有资源反向生成 CloudFormation 模板,迁移存量资源更方便
- Terraform Stacks(2024 年底 GA):HashiCorp 的多账号 / 多 Region 编排方案,直接对标 StackSets
- OpenTofu:Terraform 的开源分支,2025 年已支持 State Encryption 和 Provider 兼容性改进
- AWS CDK:用 TypeScript/Python 写 Infrastructure,编译成 CloudFormation 执行——IaC 的第三条路
- Platform Engineering 崛起:越来越多的团队用 Backstage + Terraform 搭建内部开发者平台
总结
Terraform 和 CloudFormation 没有绝对的优劣。如果你的架构圈定在 AWS 单一云、深度使用 Organizations + Control Tower,并且团队规模较小——CloudFormation + StackSets 可能更省心。如果你有跨云规划、需要管理 SCP/OU 本身、或者团队有较强的工程化需求——Terraform 是更灵活的选择。
最重要的是:选一个,然后深入用透。比工具选择更重要的是团队对 IaC 工程实践的成熟度——版本控制、代码审查、CI/CD 集成、漂移监控、成本标签——这些才是决定基础设施稳定性的真正变量。
本文由 7.chengzicloud.cloud 提供,点击访问首页了解更多