CloudFormation 基础设施即代码
AWS CloudFormation 是 AWS 的原生基础设施即代码(IaC)服务。
核心概念
基础设施即代码(IaC)
传统 vs IaC:
传统部署方式:
├─ 手动点击控制台
├─ 配置不一致
├─ 难以复制
├─ 无版本控制
├─ 容易出错
└─ 难以审计
IaC 方式:
├─ 代码定义基础设施
├─ 版本控制
├─ 可复现
├─ 自动化部署
├─ 代码审查
└─ 自我文档化
IaC 的优势:
速度
├─ 快速部署环境
├─ 批量创建资源
└─ 自动化流程
一致性
├─ 消除配置漂移
├─ 环境标准化
└─ 减少人为错误
可靠性
├─ 测试验证
├─ 回滚能力
└─ 灾难恢复
可扩展性
├─ 轻松复制环境
├─ 多区域部署
└─ 模块化复用
CloudFormation 架构
┌──────────────────────────────────┐
│ 模板(Template) │
│ ├─ JSON/YAML 格式 │
│ ├─ 声明式语法 │
│ └─ 描述所需资源 │
└────────────┬─────────────────────┘
│
▼
┌──────────────────────────────────┐
│ 堆栈(Stack) │
│ ├─ 资源的集合 │
│ ├─ 生命周期管理 │
│ └─ 整体操作 │
└────────────┬─────────────────────┘
│
┌────────┴────────┐
│ │
┌───▼───────┐ ┌─────▼──────┐
│ 创建资源 │ │ 更新资源 │
│ 删除资源 │ │ 回滚变更 │
└───────────┘ └────────────┘
模板结构
模板组成部分
AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC and EC2 infrastructure'
# 元数据(可选)
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "Network Configuration"
Parameters:
- VpcCIDR
- SubnetCIDR
# 参数(可选)
Parameters:
EnvironmentName:
Type: String
Default: Development
AllowedValues:
- Development
- Staging
- Production
InstanceType:
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
# 映射(可选)
Mappings:
RegionAMI:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
us-west-2:
AMI: ami-0d1cd67c26f5fca19
# 条件(可选)
Conditions:
IsProduction: !Equals [!Ref EnvironmentName, Production]
CreateBackup: !And
- !Condition IsProduction
- !Equals [!Ref EnableBackup, 'true']
# 资源(必需)
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${EnvironmentName}-VPC'
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: !FindInMap [RegionAMI, !Ref 'AWS::Region', AMI]
SubnetId: !Ref MySubnet
Tags:
- Key: Environment
Value: !Ref EnvironmentName
# 输出(可选)
Outputs:
VPCId:
Description: VPC ID
Value: !Ref MyVPC
Export:
Name: !Sub '${AWS::StackName}-VPC-ID'
InstanceId:
Description: EC2 Instance ID
Value: !Ref MyEC2Instance
内置函数
引用函数:
# Ref - 引用参数或资源
!Ref ParameterName
!Ref LogicalResourceId
# GetAtt - 获取资源属性
!GetAtt MyInstance.PublicDnsName
!GetAtt MyDB.Endpoint.Address
条件函数:
# Equals - 相等比较
!Equals [!Ref EnvironmentName, Production]
# If - 条件判断
!If [IsProduction, t3.large, t3.micro]
# And/Or/Not - 逻辑运算
!And [Condition1, Condition2]
!Or [Condition1, Condition2]
!Not [Condition1]
字符串函数:
# Sub - 字符串替换
!Sub '${EnvironmentName}-VPC'
!Sub
- 'arn:aws:s3:::${BucketName}/*'
- BucketName: !Ref MyBucket
# Join - 字符串连接
!Join ['-', [!Ref EnvironmentName, 'VPC']]
# Split - 字符串分割
!Split [',', 'a,b,c']
查找函数:
# FindInMap - 映射查找
!FindInMap [RegionAMI, !Ref 'AWS::Region', AMI]
# ImportValue - 导入其他堆栈的输出
!ImportValue OtherStack-VPC-ID
# Select - 选择列表元素
!Select [0, !GetAZs '']
堆栈管理
堆栈生命周期
创建堆栈:
提交模板
│
▼
验证语法
│
▼
按依赖顺序创建资源
│
├─ 资源 A
├─ 资源 B(依赖 A)
└─ 资源 C(依赖 B)
│
▼
CREATE_COMPLETE(全部成功)
或
CREATE_FAILED(部分失败)
│
└─ 自动回滚(可选)
更新堆栈:
变更集(Change Set)
├─ 预览变更
├─ 评估影响
├─ 批准执行
└─ 安全更新
更新行为:
├─ 无中断(No Interruption)
│ └─ 在线更新,不影响服务
├─ 某些中断(Some Interruption)
│ └─ 短暂中断
└─ 替换(Replacement)
└─ 删除重建资源
删除堆栈:
删除策略:
├─ Delete(默认)
│ └─ 删除堆栈时删除资源
├─ Retain
│ └─ 保留资源(手动管理)
└─ Snapshot
└─ 删除前创建快照(RDS、EBS)
删除顺序:
├─ 按依赖关系逆序删除
├─ 子资源先删除
└─ 父资源后删除
堆栈策略
防止意外更新:
{
"Statement": [
{
"Effect": "Deny",
"Action": "Update:*",
"Principal": "*",
"Resource": "LogicalResourceId/ProductionDB"
},
{
"Effect": "Allow",
"Action": "Update:*",
"Principal": "*",
"Resource": "*"
}
]
}
作用:
├─ 保护关键资源
├─ 防止误删除
├─ 强制审批流程
└─ 生产环境必备
嵌套堆栈
模块化设计
架构:
主堆栈(Parent Stack)
├─ 网络堆栈(Nested Stack)
│ ├─ VPC
│ ├─ Subnets
│ └─ Route Tables
├─ 安全堆栈(Nested Stack)
│ ├─ Security Groups
│ └─ Network ACLs
├─ 计算堆栈(Nested Stack)
│ ├─ EC2 Instances
│ └─ Auto Scaling Groups
└─ 数据库堆栈(Nested Stack)
├─ RDS
└─ ElastiCache
优势:
可重用性
├─ 标准化模块
├─ 跨项目共享
└─ 减少重复
可维护性
├─ 单一职责
├─ 独立更新
└─ 易于理解
可扩展性
├─ 模块化添加功能
├─ 组合复杂架构
└─ 团队协作
嵌套堆栈示例:
Resources:
NetworkStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-templates/network.yaml
Parameters:
VpcCIDR: 10.0.0.0/16
PublicSubnetCIDR: 10.0.1.0/24
TimeoutInMinutes: 30
ComputeStack:
Type: AWS::CloudFormation::Stack
DependsOn: NetworkStack
Properties:
TemplateURL: https://s3.amazonaws.com/my-templates/compute.yaml
Parameters:
VPCId: !GetAtt NetworkStack.Outputs.VPCId
SubnetId: !GetAtt NetworkStack.Outputs.PublicSubnetId
StackSets
多账户/多区域部署
概念:
单个模板 → 多个堆栈
├─ 跨 AWS 账户
├─ 跨 AWS 区域
├─ 集中管理
└─ 一致性保证
使用场景:
├─ 组织级别基线配置
├─ 安全标准部署
├─ 跨区域灾备
└─ 多环境一致性
部署策略:
并行部署
├─ 同时创建所有实例
├─ 速度最快
└─ 风险较高
顺序部署
├─ 逐个创建实例
├─ 速度较慢
└─ 风险可控
金丝雀部署
├─ 先部署到测试账户
├─ 验证成功后全量部署
└─ 最安全
Drift Detection
配置漂移检测
概念:
配置漂移(Configuration Drift)
├─ 实际资源状态
│ 与
├─ 模板定义状态
│ 不一致
原因:
├─ 手动修改资源
├─ 其他工具修改
├─ 控制台操作
└─ 未通过 CloudFormation 更新
检测流程:
触发漂移检测
│
▼
CloudFormation 比较
├─ 模板定义
└─ 实际状态
│
▼
生成漂移报告
├─ 漂移资源列表
├─ 属性差异
└─ 预期值 vs 实际值
│
▼
修复漂移
├─ 更新堆栈(覆盖手动修改)
└─ 更新模板(保留手动修改)
最佳实践
1. 模板组织
目录结构:
cloudformation/
├── templates/
│ ├── network/
│ │ ├── vpc.yaml
│ │ └── subnets.yaml
│ ├── compute/
│ │ ├── ec2.yaml
│ │ └── autoscaling.yaml
│ └── database/
│ └── rds.yaml
├── parameters/
│ ├── dev.json
│ ├── staging.json
│ └── prod.json
└── policies/
└── stack-policy.json
2. 参数化
环境差异化:
# 开发环境参数
{
"ParameterKey": "InstanceType",
"ParameterValue": "t3.micro"
},
{
"ParameterKey": "MinSize",
"ParameterValue": "1"
},
{
"ParameterKey": "MaxSize",
"ParameterValue": "2"
}
# 生产环境参数
{
"ParameterKey": "InstanceType",
"ParameterValue": "m5.large"
},
{
"ParameterKey": "MinSize",
"ParameterValue": "3"
},
{
"ParameterKey": "MaxSize",
"ParameterValue": "10"
}
3. 标签策略
统一标签:
Tags:
- Key: Environment
Value: !Ref EnvironmentName
- Key: Project
Value: !Ref ProjectName
- Key: CostCenter
Value: !Ref CostCenter
- Key: Owner
Value: !Ref OwnerEmail
- Key: ManagedBy
Value: CloudFormation
4. 变更管理
变更流程:
1. 创建变更集
├─ 预览影响
└─ 评估风险
2. 代码审查
├─ 团队评审
└─ 安全检查
3. 批准执行
├─ 获得批准
└─ 执行变更
4. 验证结果
├─ 功能测试
└─ 性能验证
5. 监控告警
├─ 观察指标
└─ 响应问题
5. 版本控制
Git 工作流:
main(生产)
├─ 已部署到生产的稳定版本
├─ 受保护分支
└─ 需要审批合并
staging
├─ 预生产环境
├─ 集成测试
└─ UAT
develop
├─ 开发分支
├─ 功能集成
└─ 持续集成
feature/*
├─ 功能开发
└─ 开发者分支
故障排查
常见问题
1. 创建失败:
排查步骤:
├─ 查看堆栈事件
├─ 识别失败资源
├─ 检查错误消息
├─ 验证权限
└─ 检查配额限制
常见原因:
├─ 资源命名冲突
├─ IAM 权限不足
├─ 资源限制(VPC 数量)
├─ 依赖关系错误
└─ 参数验证失败
2. 更新卡住:
UPDATE_IN_PROGRESS 超时
可能原因:
├─ 资源更新卡住
├─ Auto Scaling 无法达到期望数量
├─ ELB 健康检查失败
└─ 等待信号超时
解决方法:
├─ 检查资源日志
├─ 验证依赖服务
├─ 手动干预(如需要)
└─ 回滚变更
3. 删除失败:
DELETE_FAILED 状态
常见原因:
├─ 资源被其他服务使用
├─ S3 bucket 非空
├─ RDS 删除保护
└─ 手动创建的依赖资源
解决方法:
├─ 清理依赖
├─ 禁用删除保护
├─ 保留策略(Retain)
└─ 手动删除资源
CloudFormation vs Terraform
对比
| 特性 | CloudFormation | Terraform |
|---|---|---|
| 供应商 | AWS 原生 | HashiCorp |
| 多云支持 | 仅 AWS | 支持多云 |
| 语法 | JSON/YAML | HCL |
| 状态管理 | AWS 管理 | 需要配置后端 |
| 成本 | 免费 | 开源免费 |
| 学习曲线 | 中等 | 中等 |
| 社区 | AWS 文档 | 丰富的社区 |
选择建议
选择 CloudFormation:
- 仅使用 AWS
- 喜欢原生集成
- 不想管理状态
- 使用 AWS 特性(StackSets)
选择 Terraform:
- 多云环境
- 已有 Terraform 经验
- 需要更灵活的语法
- 活跃的社区模块
CloudFormation 是 AWS 上实现基础设施即代码的强大工具,掌握它能显著提升运维效率和一致性!