如何用CloudFormation模板在同一栈创建DynamoDB表并插入条目?已试Lambda无效
可行,实现方法如下
Lambda自定义资源确实是实现这个需求的标准方式,你之前没成功大概率是权限配置或资源生命周期处理不到位。下面是完整的实现方案:
核心思路
CloudFormation本身没有原生的DynamoDB数据写入能力,必须通过**自定义资源(Custom Resource)**调用Lambda函数来完成数据插入。关键要确保:
- Lambda有足够的权限读写目标DynamoDB表
- 自定义资源能正确响应CloudFormation的回调(成功/失败信号)
- 处理资源的创建、更新、删除逻辑(比如删除栈时可选清理数据)
完整模板示例
AWSTemplateFormatVersion: '2010-09-09' Resources: # 1. 创建DynamoDB表 MyDynamoDBTable: Type: AWS::DynamoDB::Table Properties: TableName: MyTestTable AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 # 2. 创建Lambda执行角色,赋予必要权限 LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: DynamoDBAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - dynamodb:PutItem - dynamodb:DeleteItem # 可选,用于删除栈时清理数据 Resource: !GetAtt MyDynamoDBTable.Arn - PolicyName: LambdaBasicExecution PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* # 3. 编写用于插入数据的Lambda函数 PopulateDynamoDBLambda: Type: AWS::Lambda::Function Properties: Handler: index.handler Runtime: nodejs18.x Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | const AWS = require('aws-sdk'); const dynamodb = new AWS.DynamoDB.DocumentClient(); const response = require('./cfn-response'); exports.handler = async (event, context) => { const tableName = process.env.TABLE_NAME; // 可自定义要插入的数据 const items = [ { id: 'item1', name: 'Sample Item 1', value: '100' }, { id: 'item2', name: 'Sample Item 2', value: '200' } ]; try { // 根据CloudFormation事件类型处理逻辑 if (event.RequestType === 'Create' || event.RequestType === 'Update') { const putRequests = items.map(item => ({ PutRequest: { Item: item } })); await dynamodb.batchWrite({ RequestItems: { [tableName]: putRequests } }).promise(); response.send(event, context, response.SUCCESS, { Message: 'Data inserted successfully' }); } else if (event.RequestType === 'Delete') { // 可选:删除栈时清理数据 const deleteRequests = items.map(item => ({ DeleteRequest: { Key: { id: item.id } } })); await dynamodb.batchWrite({ RequestItems: { [tableName]: deleteRequests } }).promise(); response.send(event, context, response.SUCCESS, { Message: 'Data deleted successfully' }); } } catch (err) { console.error('Error:', err); response.send(event, context, response.FAILED, { Error: err.message }); } }; Environment: Variables: TABLE_NAME: !Ref MyDynamoDBTable # 4. 定义自定义资源,触发Lambda执行数据插入 PopulateDynamoDBResource: Type: Custom::PopulateDynamoDB Properties: ServiceToken: !GetAtt PopulateDynamoDBLambda.Arn # 可传递自定义参数到Lambda,比如动态生成的数据 CustomData: - id: 'item3' name: 'Dynamic Item' value: '300'
关键注意事项
- 权限配置:Lambda角色必须拥有目标DynamoDB表的
PutItem/DeleteItem权限,以及CloudWatch日志权限(用于排查执行错误) - 回调机制:Lambda必须使用
cfn-response模块向CloudFormation返回执行结果,否则会导致栈部署卡住 - 依赖关系:模板通过
!Ref/!GetAtt自动处理依赖,确保DynamoDB表创建完成后再执行数据插入 - 更新逻辑:如果需要在栈更新时重新插入数据,要在Lambda的
Update分支处理重复数据(比如覆盖或跳过) - 问题排查:若Lambda执行失败,直接查看CloudWatch日志,常见问题包括权限不足、主键冲突、数据格式不匹配
内容的提问来源于stack exchange,提问作者Shubhanshu Bhadouria
相关产品推荐
相关产品推荐

