amazon-web-services - Cloud Formation:S3 存储桶和 Lambda 的独立 cloudformation 模板
问题描述
我创建了一个 cloudformation 模板来配置一个 S3 存储桶,其中包含一个将调用 lambda 函数的事件通知。每当在存储桶中创建新对象时,都会触发 Lamba。我遇到的问题是,当我删除堆栈时,存储桶也被删除了。出于调试和测试目的,我不得不删除堆栈。
AWSTemplateFormatVersion: '2010-09-09'
Description: Upload an object to an S3 bucket, triggering a Lambda event, returning the object key as a Stack Output.
Parameters:
Body:
Description: Stack to create s3 bucket and the lambda trigger
Type: String
Default: Test
BucketName:
Description: S3 Bucket name
Type: String
Default: image-process-bucket
Resources:
ImageProcessorExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Policies:
- PolicyName: S3Policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 's3:PutObject'
- 'S3:DeleteObject'
Resource: !Sub "arn:aws:s3:::${BucketName}/*"
ImageProcessor:
Type: AWS::Lambda::Function
Properties:
Description: Prints the filename
Handler: imageProcessor.handler
Role: !GetAtt ImageProcessorExecutionRole.Arn
Code: .
Runtime: nodejs12.x
Environment:
Variables:
BucketName:
Ref: BucketName
Bucket:
Type: AWS::S3::Bucket
DependsOn: BucketPermission
Properties:
BucketName: !Ref BucketName
NotificationConfiguration:
LambdaConfigurations:
- Event: 's3:ObjectCreated:*'
Function: !GetAtt ImageProcessor.Arn
BucketPermission:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !Ref ImageProcessor
Principal: s3.amazonaws.com
SourceAccount: !Ref "AWS::AccountId"
SourceArn: !Sub "arn:aws:s3:::${BucketName}"
为了解决这个问题,我使用 Outputs 将两个资源分开在单独的模板上。问题是我无法删除 Lambda 函数堆栈,因为它被 Bucket 堆栈引用。
- 我想知道什么是正确的方法。是否真的需要将这两种资源分开。我相信需要经常更改 lambda 函数。
- 如果是,那么正确的方法是什么。
- 如果不是,我应该如何处理进行更改的必要性。
- 使用 Outputs 和 Imports 的方法将始终创建依赖项并且不允许删除。这是任何资源中的通用行为。在这种情况下我们如何处理删除。使用这种方法好不好
Description: Upload an object to an S3 bucket, triggering a Lambda event, returning the object key as a Stack Output.
Parameters:
Body:
Description: Stack to create s3 bucket and the lambda trigger
Type: String
Default: Test
BucketName:
Description: S3 Bucket name
Type: String
Default: image-process-bucket
Resources:
ImageProcessorExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Policies:
- PolicyName: S3Policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 's3:PutObject'
- 'S3:DeleteObject'
Resource: !Sub "arn:aws:s3:::${BucketName}/*"
ImageProcessor:
Type: AWS::Lambda::Function
Properties:
Description: Prints the filename
Handler: imageProcessor.handler
Role: !GetAtt ImageProcessorExecutionRole.Arn
Code: .
Runtime: nodejs12.x
Environment:
Variables:
BucketName:
Ref: BucketName
Outputs:
ImageProcessingARN:
Description: ARN of the function
Value:
Fn::Sub: ${ImageProcessor.Arn}
Export:
Name: ImageProcessingARN
ImageProcessingName:
Description: Name of the function
Value: !Ref ImageProcessor
Export:
Name: ImageProcessingName
AWSTemplateFormatVersion: '2010-09-09'
Description: Test
Parameters:
BucketName:
Description: Name of the bucket
Type: String
Default: imageprocess-bucket
Resources:
Bucket:
Type: AWS::S3::Bucket
DependsOn: BucketPermission
Properties:
BucketName: !Ref BucketName
NotificationConfiguration:
LambdaConfigurations:
- Event: 's3:ObjectCreated:*'
Function:
Fn::ImportValue: ImageProcessingARN
BucketPermission:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName:
Fn::ImportValue: ImageProcessingName
Principal: s3.amazonaws.com
SourceAccount: !Ref "AWS::AccountId"
SourceArn: !Sub "arn:aws:s3:::${BucketName}"
解决方案
- 没有正确的方法,它几乎总是取决于您的独特情况。严格来说,不需要将不同 CloudFormation 模板中的资源分开。变化很大的 lambda 函数也不是分离资源的充分理由。
您似乎在两个不同的堆栈中正确地分离了资源。您只是不喜欢必须先删除 S3 存储桶,因为这会使调试更加困难。
如果我的假设是正确的,即您想频繁地删除或更新 Lambda CloudFormation 堆栈而不想删除 S3 存储桶,那么对于这个问题至少有 2 种解决方案:
- 在您的 S3 存储桶上放置一个删除策略和一个UpdateReplacePolicy 。通过添加这些策略,您可以删除 CloudFormation 堆栈,同时保留 S3 存储桶。这将允许您将 S3 存储桶和 Lambda 函数保留在一个 CloudFormation 模板中。要再次创建新堆栈,请从模板中删除 S3 存储桶资源,稍后手动将资源重新导入 CloudFormation 堆栈。
- 使用队列配置作为通知配置。如果您计划将 CloudFormation 模板分离为 S3 存储桶模板和 Lambda 函数模板(基于更改频率和两个模板之间的依赖关系的决定),这是一个很好的方法。在 S3 存储桶模板中放置一个SQS 队列。基于 S3 存储桶模板创建 CloudFormation 堆栈。在 Lambda 函数堆栈中使用 SQS arn(作为 CloudFormation 模板配置参数或使用 ImportValue 内部函数)并让SQS 触发 Lambda 函数. 我认为这是最好的方法,因为您现在可以删除 Lambda 函数堆栈,而无需删除 S3 存储桶堆栈。通过这种方式,您可以有效地减少两个 CloudFormation 堆栈之间的耦合,因为您使 S3 存储桶堆栈中的 SQS 不知道潜在的 Lambda 函数侦听器。
4:我觉得还是可以先删除S3存储桶CloudFormation栈,再删除Image Processing Lambda CloudFormation栈。尽管我认为这不是您通常想要做的事情。
推荐阅读
- python - 如何使用Python从pdf中提取的文本中计算列表中的单词数?
- javascript - Filepond + Pintura Vue 2 将 SVG 转换为 PNG
- php - 如果类别在 Laravel 中没有子类别,则删除图标箭头
- c++ - 检查我在重载运算符中传递和返回的内容
- spring-boot - @StreamListener 不提供 Acknowledgement 标头,即使在 Spring Cloud 中自动提交设置为 false
- css - Atom 中突出显示的文本颜色
- python - 具有多个会话的 SQLAlchemy,如何避免“对象已附加到会话 X”?
- xml - Toast 通知 - 打开链接上带有特定字符的网页
- ruby-on-rails - 如何更改表名?
- python - 条件重采样时间序列数据