前言:为什么选择SAM+CloudFormation?
作为AWS开发者,你是否遇到过这些痛点:
- 手动创建Lambda、API Gateway等资源太繁琐,容易出错?
- 开发环境与生产环境配置不一致,导致"本地能跑,线上不行"?
- 资源依赖关系复杂,不知道如何批量管理和部署?
AWS SAM(Serverless Application Model) 是解决这些问题的最佳工具——它基于CloudFormation,提供更简洁的语法定义Serverless资源,支持本地开发测试,还能一键部署到AWS,真正实现"基础设施即代码"(IaC)。今天这份指南,带你从0到1掌握SAM+CloudFormation的全套配置流程!
一、环境搭建:三步搞定开发环境
1. 核心工具安装
(1)AWS CLI(必备)
# Windows(PowerShell)
Invoke-WebRequest -Uri "https://awscli.amazonaws.com/AWSCLIV2.msi" -Outfile "AWSCLIV2.msi"
Start-Process msiexec.exe -Wait -ArgumentList '/I AWSCLIV2.msi /quiet'
# macOS(Homebrew)
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# 验证安装
aws --version # 输出 aws-cli/2.x.x 即成功
(2)AWS SAM CLI(Serverless开发工具)
# Windows(PowerShell)
Invoke-WebRequest -Uri "https://github.com/aws/aws-sam-cli/releases/latest/download/AWS_SAM_CLI_64_PY3.msi" -Outfile "AWS_SAM_CLI_64_PY3.msi"
Start-Process msiexec.exe -Wait -ArgumentList '/I AWS_SAM_CLI_64_PY3.msi /quiet'
# macOS(Homebrew)
brew tap aws/tap
brew install aws-sam-cli
# Linux
wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip
unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
sudo ./sam-installation/install
# 验证安装
sam --version # 输出 SAM CLI, version 1.x.x 即成功
(3)辅助工具(可选)
- Docker:用于本地模拟Lambda环境(
sam local命令依赖); - VS Code + AWS Toolkit插件:提供模板语法提示、一键部署功能。
2. AWS凭证配置
# 配置Access Key和Secret Key
aws configure
# 输入以下信息:
# AWS Access Key ID [None]: 你的Access Key(从IAM控制台获取)
# AWS Secret Access Key [None]: 你的Secret Key
# Default region name [None]: us-east-1(或其他区域)
# Default output format [None]: json
# 验证配置
aws sts get-caller-identity
# 输出用户ARN即配置成功
3. 项目初始化(快速上手)
# 创建SAM项目(Node.js示例)
sam init --runtime nodejs20.x --name my-serverless-app --app-template hello-world
# 进入项目目录
cd my-serverless-app
# 查看项目结构
tree
# ├── README.md
# ├── events/ # 测试事件
# ├── hello-world/ # Lambda函数代码
# ├── template.yaml # SAM模板(核心配置文件)
# └── samconfig.toml # 部署配置(首次部署后生成)
二、核心概念:SAM与CloudFormation的关系
1. 架构层次
SAM模板(template.yaml)
↓ sam build
SAM打包模板(.aws-sam/build/template.yaml)
↓ sam deploy
CloudFormation模板(转换为标准CFN语法)
↓ CloudFormation服务
AWS资源(Lambda、API Gateway、VPC等)
2. 关键差异
| 特性 | SAM模板 | 原生CloudFormation模板 |
|---|---|---|
| 语法 | 简洁(如AWS::Serverless::Function) | 冗长(如AWS::Lambda::Function) |
| 资源类型 | 支持Serverless专用类型 | 仅支持标准AWS资源类型 |
| 本地开发 | 支持(sam local) | 不支持 |
| 打包部署 | 一键完成(sam build/deploy) | 需手动打包上传 |
| 底层依赖 | 最终转换为CloudFormation | 直接执行 |
3. 核心模板结构
AWSTemplateFormatVersion: "2010-09-09" # 固定版本
Transform: AWS::Serverless-2016-10-31 # SAM转换标识
Description: "My Serverless Application"
Parameters: # 输入参数(如VPC ID、数据库密码)
VpcId:
Type: String
Default: "vpc-xxxxxx"
Globals: # 全局配置(所有函数共享)
Function:
Timeout: 30
MemorySize: 1024
Resources: # 资源定义(Lambda、API Gateway等)
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
CodeUri: src/
Outputs: # 输出结果(如API端点、函数ARN)
ApiEndpoint:
Value: !Sub "https://${Api}.execute-api.${AWS::Region}.amazonaws.com/dev"
三、实战配置:生产级模板示例(NestJS+VPC)
1. 完整template.yaml(带VPC配置)
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "NestJS Serverless App with VPC"
# 参数定义(可通过sam deploy --parameter-overrides修改)
Parameters:
DatabaseHost:
Type: String
Default: "my-aurora-cluster.cluster-xxxx.us-east-1.rds.amazonaws.com"
Description: "Aurora PostgreSQL host"
DatabasePassword:
Type: String
NoEcho: true # 敏感信息不显示
Default: "YourStrongPassword123!"
Description: "Database password"
VpcId:
Type: String
Default: "vpc-019dc15b736c3a72b"
Description: "Existing VPC ID"
PrivateSubnet1Id:
Type: String
Default: "subnet-0015d272e6a9780fc"
Description: "Private subnet 1 ID"
PrivateSubnet2Id:
Type: String
Default: "subnet-059ff661e98af5fd0"
Description: "Private subnet 2 ID"
SecurityGroupId:
Type: String
Default: "sg-0ef5ca38e76692f56"
Description: "Lambda security group ID"
# 全局配置(所有函数共享)
Globals:
Function:
Timeout: 30
MemorySize: 1024
Runtime: nodejs20.x
Architectures: ["arm64"] # ARM架构更便宜
Environment:
Variables:
NODE_OPTIONS: "--enable-source-maps" # 调试用
Api:
OpenApiVersion: "2.0"
Cors: # 跨域配置
AllowMethods: "'*'"
AllowHeaders: "'Content-Type,Authorization'"
AllowOrigin: "'*'"
MaxAge: 600
# 资源定义
Resources:
# API Gateway
NestjsApi:
Type: AWS::Serverless::Api
Properties:
StageName: dev
BinaryMediaTypes: # 支持二进制文件(如图片)
- "image/*"
- "multipart/form-data"
# Lambda函数(带VPC配置)
NestjsFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda.handler # NestJS入口文件
CodeUri: dist/ # 编译后的代码目录
VpcConfig: # 部署到私有子网(访问Aurora)
SecurityGroupIds:
- !Ref SecurityGroupId
SubnetIds:
- !Ref PrivateSubnet1Id
- !Ref PrivateSubnet2Id
Environment:
Variables:
DB_HOST: !Ref DatabaseHost
DB_PASSWORD: !Ref DatabasePassword
DB_TYPE: "postgres"
Policies: # IAM权限
- AWSLambdaVPCAccessExecutionRole # VPC访问权限
- AWSLambdaBasicExecutionRole # CloudWatch日志权限
Events: # API Gateway触发
ApiEvent:
Type: Api
Properties:
Path: /{proxy+} # 所有路径
Method: ANY
RestApiId: !Ref NestjsApi
# 输出结果
Outputs:
ApiEndpoint:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${NestjsApi}.execute-api.${AWS::Region}.amazonaws.com/dev"
Export:
Name: !Sub "${AWS::StackName}-ApiEndpoint"
FunctionArn:
Description: "Lambda Function ARN"
Value: !GetAtt NestjsFunction.Arn
Export:
Name: !Sub "${AWS::StackName}-FunctionArn"
2. 关键配置说明
(1)VPC配置
- Lambda部署到私有子网,需指定
SecurityGroupIds和SubnetIds; - 必须添加
AWSLambdaVPCAccessExecutionRole权限,否则无法访问VPC内资源; - 安全组需允许Lambda访问数据库端口(如5432)。
(2)环境变量
- 敏感信息(如数据库密码)用
Parameters定义,并设置NoEcho: true; - 部署时可通过
sam deploy --parameter-overrides DatabasePassword=xxx覆盖默认值。
(3)API Gateway
BinaryMediaTypes支持上传/下载二进制文件;Cors配置解决跨域问题,生产环境建议限制AllowOrigin为指定域名。
四、部署流程:从本地开发到线上发布
1. 本地开发测试
(1)启动本地API服务器
# 编译NestJS代码
npm run build
# 启动本地API Gateway模拟器(端口3001)
sam local start-api --port 3001
# 带环境变量文件启动
sam local start-api --env-vars env.json
(2)本地调用Lambda函数
# 调用函数(使用默认事件)
sam local invoke NestjsFunction
# 带自定义事件调用
sam local invoke NestjsFunction --event events/api-event.json
(3)环境变量文件(env.json)
{
"NestjsFunction": {
"DB_HOST": "localhost",
"DB_PORT": "5432",
"DB_PASSWORD": "local-password"
}
}
2. 打包部署
(1)首次部署(交互式配置)
# 构建代码(打包Lambda依赖)
sam build
# 首次部署,生成samconfig.toml
sam deploy --guided
# 交互式配置选项:
# Stack Name: my-nestjs-stack
# AWS Region: us-east-1
# Confirm changes before deploy: y
# Allow SAM CLI IAM role creation: y
# Save arguments to samconfig.toml: y
(2)后续部署(一键完成)
# 直接使用samconfig.toml配置部署
sam deploy
(3)部署成功后输出
CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------------------------------
Key ApiEndpoint
Description API Gateway endpoint URL
Value https://abc123.execute-api.us-east-1.amazonaws.com/dev
Key FunctionArn
Description Lambda Function ARN
Value arn:aws:lambda:us-east-1:123456789012:function:my-nestjs-stack-NestjsFunction-XXXXXX
---------------------------------------------------------------------------------------------------------------------
五、堆栈管理:CloudFormation核心操作
1. 查看堆栈状态
# 查看特定堆栈信息
aws cloudformation describe-stacks --stack-name my-nestjs-stack
# 查看堆栈资源列表
aws cloudformation describe-stack-resources --stack-name my-nestjs-stack
# 查看堆栈事件(排查部署失败)
aws cloudformation describe-stack-events --stack-name my-nestjs-stack
2. 更新堆栈(修改模板后)
# 修改template.yaml后,重新部署
sam build && sam deploy
# 或直接用CloudFormation更新
aws cloudformation update-stack --stack-name my-nestjs-stack --template-body file://template.yaml
3. 删除堆栈(清理资源)
# 删除整个堆栈(删除所有资源)
aws cloudformation delete-stack --stack-name my-nestjs-stack
# 查看删除进度
aws cloudformation describe-stacks --stack-name my-nestjs-stack --query "Stacks[0].StackStatus"
六、故障排除:常见问题速解
1. 部署失败:权限不足
现象:CloudFormation报错AccessDenied
解决方案:
- 确保AWS用户拥有
IAMFullAccess、LambdaFullAccess、APIGatewayAdministrator权限; - SAM部署需要创建IAM角色,需允许
iam:CreateRole、iam:AttachRolePolicy等操作。
2. Lambda无法访问VPC内数据库
现象:Lambda连接Aurora超时
解决方案:
- 检查Lambda的VPC配置:确保子网和安全组正确;
- 安全组规则:数据库安全组允许Lambda安全组访问5432端口;
- 路由表:私有子网需配置NAT网关(访问外网)或VPC Endpoints(访问AWS服务)。
3. 本地开发:sam local启动失败
现象:sam local start-api报错Docker not running
解决方案:
- 安装并启动Docker Desktop;
- 确保Docker与SAM CLI版本兼容(推荐Docker 20.10+)。
4. 模板验证失败
现象:sam validate报错Invalid template property
解决方案:
- 检查YAML语法(如缩进、冒号);
- 确保SAM资源类型正确(如
AWS::Serverless::Function而非AWS::Lambda::Function); - 使用
sam validate --lint进行更详细的语法检查。
七、最佳实践:生产环境配置优化
1. 安全最佳实践
- 敏感信息管理:使用AWS Secrets Manager存储数据库密码,而非硬编码在模板中;
- 最小权限原则:自定义IAM策略,避免使用
AWSLambdaFullAccess等宽泛权限; - 加密配置:启用Lambda代码加密、API Gateway HTTPS、数据库存储加密。
2. 性能优化
- 内存配置:Lambda内存越大,CPU和网络带宽越高,根据负载调整(推荐1024MB起);
- 冷启动优化:使用ARM架构(arm64)、减少依赖包大小、启用Lambda SnapStart(Java);
- API缓存:为API Gateway启用缓存,减少Lambda调用次数。
3. 成本优化
- 按需扩缩容:使用Lambda的Provisioned Concurrency应对突发流量,避免过度配置;
- 删除闲置资源:测试环境用完后及时删除堆栈,避免资源浪费;
- 区域选择:选择成本较低的区域(如us-east-1比us-west-2便宜)。
4. 监控与日志
- 启用CloudWatch Logs和X-Ray追踪,监控Lambda执行情况;
- 设置告警:Lambda错误率>1%、API Gateway 5xx错误>0时触发告警;
- 使用SAM CLI查看日志:
sam logs -n NestjsFunction --tail。
八、总结:SAM+CloudFormation核心价值
- 基础设施即代码:所有资源通过模板定义,版本控制,可重复部署;
- 环境一致性:开发、测试、生产环境配置一致,避免"配置漂移";
- 一键部署:从本地开发到线上发布,流程标准化,减少人工操作;
- 资源管理:通过CloudFormation堆栈统一管理资源,一键创建/删除。
无论是小型Serverless应用,还是复杂的VPC内服务部署,SAM+CloudFormation都是AWS开发的最佳实践。掌握这套工具链,能大幅提升开发效率,降低运维成本!
