【问题标题】:Cloud Formation: separate cloudformation template of S3 bucket and LambdaCloud Formation:S3 存储桶和 Lambda 的独立 cloudformation 模板
【发布时间】:2020-09-02 05:34:11
【问题描述】:

我创建了一个 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 堆栈正在引用它。

  1. 我想知道什么是正确的方法。是否真的需要将这两种资源分开。我认为需要经常更改 lambda 函数。
  2. 如果是,正确的做法是什么。
  3. 如果不是,我应该如何处理进行更改的必要性。
  4. 使用输出和导入的方法将始终创建依赖项并且不允许删除。这是任何资源中的通用行为。在这种情况下我们如何处理删除。用这种方法好不好
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}"

【问题讨论】:

  • 下面的同名回答将对您有所帮助。但是,我想问,为什么要删除函数堆栈而不是更新它?如果您按照 Hadronymous 的建议使用 Retain,则可以将两者放回一个堆栈并删除整个堆栈,同时保留存储桶。

标签: amazon-web-services amazon-s3 aws-lambda amazon-cloudformation


【解决方案1】:
  1. 没有正确的方法,它几乎总是取决于您的独特情况。严格来说,不需要将不同 CloudFormation 模板中的资源分开。变化很大的 lambda 函数也不是分离资源的充分理由。
  2. 您似乎在两个不同的堆栈中正确地分离了资源。您只是不喜欢必须先删除 S3 存储桶,因为这会使调试更加困难。

  3. 如果我的假设是正确的,即您想频繁地删除或更新 Lambda CloudFormation 堆栈而不想删除 S3 存储桶,那么对于这个问题至少有 2 种解决方案:

    • 在您的 S3 存储桶上放置 Deletion PolicyUpdateReplacePolicy。通过添加这些策略,您可以删除 CloudFormation 堆栈,同时保留 S3 存储桶。这将允许您将 S3 存储桶和 Lambda 函数保留在一个 CloudFormation 模板中。要再次创建新堆栈,请从模板中删除 S3 存储桶资源,稍后将 manually import 资源重新放入 CloudFormation 堆栈。
    • Queue Configuration 用作Notification Configuration。如果您计划将 CloudFormation 模板分离为 S3 存储桶模板和 Lambda 函数模板(基于更改频率和两个模板之间的依赖关系的决定),这是一个很好的方法。在 S3 存储桶模板中放入 SQS queue。基于 S3 存储桶模板创建 CloudFormation 堆栈。使用 Lambda 函数堆栈中的 SQS arn(作为 CloudFormation 模板配置参数或使用 ImportValue 内部函数)并让SQS trigger the Lambda function。我认为这是最好的方法,因为您现在可以删除 Lambda 函数堆栈,而无需删除 S3 存储桶堆栈。通过这种方式,您可以有效地减少两个 CloudFormation 堆栈之间的耦合,因为您使 S3 存储桶堆栈中的 SQS 不知道潜在的 Lambda 函数侦听器。

    4:我觉得还是可以先删除S3 bucket CloudFormation stack,再删除Image Processing Lambda CloudFormation stack。虽然我认为这不是您通常想要做的事情。

【讨论】:

    猜你喜欢
    • 2021-05-06
    • 2023-04-11
    • 2021-08-08
    • 1970-01-01
    • 2015-04-30
    • 2021-09-23
    • 2017-01-28
    • 1970-01-01
    • 2021-08-13
    相关资源
    最近更新 更多