AWS CloudFormation基础设施即代码实战:从零搭建自动化运维体系
Meta Description: AWS CloudFormation入门实战教程,手把手教你用YAML模板管理EC2、VPC、RDS等云资源,实现基础设施即代码,告别手动配置。
- 为什么需要CloudFormation?
- 第一个CloudFormation模板:创建S3存储桶
- 实战模板:创建完整Web应用环境
- 模板进阶技巧
- CloudFormation最佳实践
- CloudFormation vs 其他IaC工具
Meta Description: AWS CloudFormation入门实战教程,手把手教你用YAML模板管理EC2、VPC、RDS等云资源,实现基础设施即代码,告别手动配置。
关键词: AWS CloudFormation、基础设施即代码、IaC、AWS自动化运维、CloudFormation模板、AWS资源编排、DevOps实战
一、为什么需要CloudFormation?
在云计算时代,手动在AWS控制台点点点创建资源的方式早已过时。想象一下:你需要在三个区域各部署一套完全相同的Web应用环境——包含VPC、子网、安全组、EC2实例、RDS数据库、S3存储桶。手动操作不仅耗时,还容易出错,更关键的是无法复现。今天配好了,明天要再搭一套怎么办?改配置后如何保证一致性?
AWS CloudFormation(简称CFN)就是为解决这些问题而生的。它是AWS官方提供的基础设施即代码(Infrastructure as Code, IaC)服务,让你用声明式的YAML或JSON模板文件来定义和管理所有AWS资源。写一次模板,就能在任意区域、任意账号下一键创建整套环境。
决策口诀: 只要你的AWS环境超过3个资源,就该用CloudFormation。它不是可选项,而是专业云架构的必选项。
1.1 CloudFormation vs 手动配置
| 对比维度 | 手动控制台配置 | CloudFormation |
|---|---|---|
| 创建速度 | 慢,需逐个点击 | 快,一条命令创建全部 |
| 可复现性 | 无法保证一致 | 模板=唯一真相源 |
| 版本控制 | 无 | 模板可Git管理 |
| 回滚能力 | 手动逐个删除 | 一键自动回滚 |
| 团队协作 | 口头约定 | 模板即文档 |
| 成本 | 免费(但人工贵) | 免费(CFN本身不收费) |
| 学习曲线 | 低 | 中等(需学YAML语法) |
1.2 核心概念速览
Stack(栈):CloudFormation部署的基本单位。一个Stack包含模板中定义的所有资源。创建Stack时,AWS按依赖关系自动创建所有资源;删除Stack时,所有资源一并清理。
Template(模板):描述资源的YAML或JSON文件。包含资源定义、参数、输出、映射等。
Change Set(变更集):对现有Stack的修改预览。先看影响,确认后再执行,避免误操作。
Drift Detection(漂移检测):检查Stack中的实际资源是否与模板定义一致。手动改过的资源会被标记为"漂移"。
二、第一个CloudFormation模板:创建S3存储桶
让我们从最简单的模板开始。以下模板创建一个带版本控制的S3存储桶:
AWSTemplateFormatVersion: '2010-09-09'
Description: 我的第一个CloudFormation模板 - 创建S3存储桶
Parameters:
BucketName:
Type: String
Description: S3存储桶名称(必须全局唯一)
Default: my-first-cfn-bucket-2026
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
VersioningConfiguration:
Status: Enabled
Tags:
- Key: Environment
Value: Development
- Key: ManagedBy
Value: CloudFormation
Outputs:
BucketArn:
Description: S3存储桶ARN
Value: !GetAtt MyBucket.Arn
BucketDomainName:
Description: S3存储桶域名
Value: !GetAtt MyBucket.DomainName
2.1 模板结构解析
AWSTemplateFormatVersion:模板格式版本,固定写2010-09-09即可。
Parameters:输入参数,部署时可自定义。支持类型约束、默认值、描述等。
Resources:核心部分,定义要创建的AWS资源。每种资源有固定的Type和Properties。
Outputs:输出值,部署完成后返回给调用者。常用于传递资源ID给其他Stack。
2.2 部署方式
方式一:AWS CLI命令行
// 创建Stack
aws cloudformation create-stack \
--stack-name my-first-stack \
--template-body file://template.yaml \
--parameters ParameterKey=BucketName,ParameterValue=my-unique-bucket-2026 \
--capabilities CAPABILITY_IAM
// 等待创建完成
aws cloudformation wait stack-create-complete \
--stack-name my-first-stack
// 查看输出
aws cloudformation describe-stacks \
--stack-name my-first-stack \
--query 'Stacks[0].Outputs'
方式二:AWS控制台
- 打开CloudFormation控制台 → 点击"创建堆栈"
- 选择"模板编辑器" → 粘贴模板内容
- 填写参数 → 确认创建
- 等待状态变为
CREATE_COMPLETE
方式三:AWS CDK(进阶推荐)
如果你觉得手写YAML太繁琐,可以用AWS CDK(Cloud Development Kit)用代码生成模板:
from aws_cdk import (
Stack,
aws_s3 as s3,
)
from constructs import Construct
class MyStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
s3.Bucket(self, "MyBucket",
versioned=True,
bucket_name="my-first-cfn-bucket-2026"
)
三、实战模板:创建完整Web应用环境
接下来我们构建一个真实的生产级模板,包含VPC、子网、安全组、EC2和RDS:
AWSTemplateFormatVersion: '2010-09-09'
Description: 生产级Web应用环境 - VPC+EC2+RDS
Parameters:
InstanceType:
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
Description: EC2实例类型
DBName:
Type: String
Default: myapp
Description: 数据库名称
DBUser:
Type: String
Default: admin
NoEcho: true
Description: 数据库用户名
DBPassword:
Type: String
NoEcho: true
MinLength: 8
Description: 数据库密码(至少8位)
Mappings:
RegionMap:
ap-southeast-1:
AMI: ami-0c55b159cbfafe1f0
us-east-1:
AMI: ami-0c02fb55956c7d316
eu-west-1:
AMI: ami-0d71ea30463e0ff8d
Resources:
// VPC
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-VPC'
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-PublicSubnet'
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-PrivateSubnet'
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-IGW'
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-PublicRT'
PublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
// 安全组
WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Web服务器安全组
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-WebSG'
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 数据库安全组
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref WebSecurityGroup
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-DBSG'
// EC2实例
WebServer:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
SubnetId: !Ref PublicSubnet
SecurityGroupIds:
- !Ref WebSecurityGroup
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-WebServer'
// RDS数据库
DBInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceClass: db.t3.micro
Engine: mysql
EngineVersion: '8.0'
DBName: !Ref DBName
MasterUsername: !Ref DBUser
MasterUserPassword: !Ref DBPassword
VPCSecurityGroups:
- !Ref DBSecurityGroup
AllocatedStorage: 20
StorageType: gp3
BackupRetentionPeriod: 7
MultiAZ: false
PubliclyAccessible: false
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-DB'
Outputs:
VPCId:
Value: !Ref VPC
WebServerPublicIP:
Value: !GetAtt WebServer.PublicIp
DBEndpoint:
Value: !GetAtt DBInstance.Endpoint.Address
3.1 关键设计模式解析
参数化(Parameterization):通过Parameters将可变配置外提。不同环境(dev/staging/prod)共用同一模板,仅参数不同。
映射表(Mappings):用RegionMap为不同区域自动选择正确的AMI ID。部署到新区域只需在映射表中加一行。
资源依赖(DependsOn):CloudFormation自动推断大部分依赖关系,但某些隐式依赖(如Route需要IGW先挂载)需手动声明。
安全组嵌套引用:Web安全组允许22/80/443端口;数据库安全组仅允许来自Web安全组的3306端口。最小权限原则。
四、模板进阶技巧
4.1 条件资源创建
Parameters:
Environment:
Type: String
AllowedValues:
- dev
- prod
Conditions:
IsProd: !Equals [!Ref Environment, prod]
Resources:
// 仅在生产环境创建多AZ部署
StandbyDB:
Type: AWS::RDS::DBInstance
Condition: IsProd
Properties:
DBInstanceClass: db.t3.medium
Engine: mysql
MultiAZ: true
4.2 嵌套Stack
大型项目建议拆分为多个Stack,通过嵌套Stack组合:
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-templates/network.yaml
ComputeStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-templates/compute.yaml
Parameters:
VpcId: !GetAtt NetworkStack.Outputs.VPCId
SubnetId: !GetAtt NetworkStack.Outputs.PublicSubnetId
4.3 Drift Detection实战
当有人手动在控制台改了资源配置(比如安全组端口),Drift Detection能立刻发现:
// 启动漂移检测
aws cloudformation detect-stack-drift \
--stack-name my-stack
// 查看漂移结果
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id <id>
// 查看具体哪些资源漂移了
aws cloudformation describe-stack-resource-drifts \
--stack-name my-stack \
--stack-resource-drift-status-filters MODIFIED DELETED
4.4 Change Set安全变更
修改生产环境Stack前,先用Change Set预览影响:
// 创建变更集
aws cloudformation create-change-set \
--stack-name prod-stack \
--change-set-name add-alb \
--template-body file://updated-template.yaml
// 查看变更内容
aws cloudformation describe-change-set \
--stack-name prod-stack \
--change-set-name add-alb
// 确认无误后执行
aws cloudformation execute-change-set \
--stack-name prod-stack \
--change-set-name add-alb
五、CloudFormation最佳实践
5.1 模板管理规范
Git版本控制:所有模板必须纳入Git管理。每次修改提交PR,团队Review后合并。
模块化设计:按功能拆分模板——网络层、计算层、数据库层、监控层。每个Stack不超过200行。
命名规范:Stack名称用${AppName}-${Env}-${Region}格式,如webapp-prod-ap-southeast-1。
标签策略:所有资源必须包含Environment、ManagedBy、Project标签,便于成本分析和权限管理。
5.2 安全注意事项
敏感数据处理:密码等敏感参数使用NoEcho: true,或通过Secrets Manager/SSM Parameter Store引用,不要硬编码在模板中。
IAM最小权限:为CloudFormation服务角色配置最小必要权限。使用CAPABILITY_IAM或CAPABILITY_NAMED_IAM时格外小心。
Stack策略:生产Stack设置阻止更新策略,防止误操作覆盖关键资源:
{
"Statement": [
{
"Effect": "Deny",
"Action": "Update:*",
"Principal": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"ResourceType": [
"AWS::RDS::DBInstance",
"AWS::RDS::DBCluster"
]
}
}
}
]
}
5.3 常见错误与排查
CREATE_FAILED:模板语法错误或权限不足。检查StatusReason字段。
Resource CREATE failed:资源创建失败(如AMI不存在、配额超限)。Stack会自动回滚已创建的资源。
UPDATE_ROLLBACK_FAILED:回滚也失败了,Stack卡在中间状态。需要手动修复后继续回滚:
aws cloudformation continue-update-rollback \
--stack-name stuck-stack \
--resources-to-skip MyProblematicResource
六、CloudFormation vs 其他IaC工具
| 工具 | 语言 | AWS集成度 | 学习曲线 | 社区生态 | 适用场景 |
|---|---|---|---|---|---|
| CloudFormation | YAML/JSON | 原生最佳 | 中 | 中 | 纯AWS环境 |
| Terraform | HCL | 多云支持 | 中 | 最大 | 多云/混合云 |
| Pulumi | Python/TS/Go | 多云支持 | 低(代码) | 增长中 | 熟悉编程语言的团队 |
| AWS CDK | Python/TS/Java | 原生 | 低 | 中 | 厌倦写YAML |
| Ansible | YAML | 多云 | 低 | 大 | 配置管理+部署 |
决策口诀: 纯AWS用CFN/CDK,多云用Terraform,团队会写代码用Pulumi。
⚠️ 文中价格为 2026 年参考价,实际费用随区域和官方调价变动,请以 AWS 官网为准。
🚀 需要 AWS 国际版账号?通过 3.chengzicloud.cloud 获取最新注册教程与专属优惠,助你轻松上云。
七、常见问题FAQ
Q: CloudFormation本身收费吗?
A: 不收费。你只需为CloudFormation创建的AWS资源付费(如EC2、RDS等),CloudFormation服务本身完全免费。
Q: 模板写错了怎么办?Stack会损坏吗?
A: 不会。CloudFormation创建资源失败时会自动回滚,删除已创建的资源,恢复到原始状态。你可以修改模板后重新部署。
Q: 手动修改了控制台的资源,CloudFormation能发现吗?
A: 可以。使用Drift Detection功能检测哪些资源被手动修改。发现漂移后,你可以选择"忽略漂移"或"更新Stack"使模板与实际状态同步。
Q: CloudFormation支持所有AWS服务吗?
A: 覆盖了绝大多数AWS服务(200+种资源类型)。少数新发布的服务可能需要等待CloudFormation支持。可以通过资源类型列表查看支持情况。
Q: 大型项目应该用CloudFormation还是Terraform?
A: 如果只用AWS,CloudFormation是首选——原生集成、零额外成本、与AWS服务深度绑定。如果需要管理多云资源,Terraform的HCL语言和多Provider支持更合适。
Q: 如何管理多个环境(dev/staging/prod)的配置?
A: 推荐使用参数文件(dev.json、staging.json、prod.json)配合同一模板。部署时指定不同参数文件即可创建不同环境的资源。
Q: CloudFormation模板最大支持多少资源?
A: 默认每个Stack最多500个资源。可以通过申请配额提升到更高数量。大型项目建议拆分为多个嵌套Stack,每个Stack控制在200个资源以内。
Q: 团队成员都能操作生产环境的Stack吗?
A: 建议通过IAM权限精细控制,生产环境Stack仅允许DevOps团队操作。结合Change Set机制,任何变更都需要Review和批准后才能执行。
本文由 3.chengzicloud.cloud 提供,点击访问首页了解更多