AWS CloudFormation基础设施即代码实战:从零搭建自动化运维体系

📅 · AWS 国际版实战教程 - ChengziCloud

一句话结论

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控制台

  1. 打开CloudFormation控制台 → 点击"创建堆栈"
  2. 选择"模板编辑器" → 粘贴模板内容
  3. 填写参数 → 确认创建
  4. 等待状态变为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集成度学习曲线社区生态适用场景
CloudFormationYAML/JSON原生最佳中中纯AWS环境
TerraformHCL多云支持中最大多云/混合云
PulumiPython/TS/Go多云支持低(代码)增长中熟悉编程语言的团队
AWS CDKPython/TS/Java原生低中厌倦写YAML
AnsibleYAML多云低大配置管理+部署

决策口诀: 纯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 提供,点击访问首页了解更多