云形态:S3 bucket和Lambda的独立云形态模板。

问题描述 投票:0回答:1

我已经创建了一个cloudformation模板来配置S3 bucket,该模板带有一个事件通知,该通知将调用一个lambda函数。每当 bucket 中创建一个新对象时,就会触发 lamba。我遇到的问题是,当我删除堆栈时,bucket也会被删除。为了调试和测试的目的,我不得不删除堆栈。

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. 使用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}"
amazon-web-services amazon-s3 aws-lambda amazon-cloudformation
1个回答
0
投票
  1. 没有正确的方法,它几乎总是取决于你的独特情况。严格来说,不需要在不同的 CloudFormation 模板中分离资源。经常变化的 lambda 函数也不是分离资源的充分理由。
  2. 您似乎正确地将资源分离在两个不同的堆栈中。你只是不喜欢你必须先删除S3桶,因为这使调试更加困难。

  3. 如果我的假设是正确的,您希望频繁地删除或更新Lambda CloudFormation堆栈,同时又不想删除S3 bucket,那么这个问题至少有2种解决方案。

    • 把一个 删除政策 和一个 更新替换政策 在您的S3 bucket上。通过添加这些策略,您可以删除 CloudFormation 堆栈,同时保留 S3 bucket。这将允许您在一个 CloudFormation 模板中保留 S3 bucket 和 Lambda 函数。要再次创建新的堆栈,请从模板中删除 S3 bucket 资源,并 手动导入 资源回到CloudFormation堆栈中。
    • 使用 队列配置 作为 通知配置. 如果你打算将CloudFormation模板分离在S3桶模板和Lambda函数模板中,这是一个很好的方法(根据两个模板之间的变化频率和依赖关系来决定)。把一个 SQS队列 中的S3 bucket模板。基于S3 bucket模板创建CloudFormation栈。在Lambda函数栈中使用SQS arn(作为CloudFormation模板配置参数或使用ImportValue内在函数),并让 SQS触发Lambda函数. 我认为这是最好的方法,因为您现在可以删除Lambda函数栈,而不必删除S3桶栈。这样你就有效地减少了两个CloudFormation栈之间的耦合,因为你使S3 bucket栈中的SQS不知道潜在的Lambda函数监听器。

    4:我认为还是可以先删除S3 bucket CloudFormation栈,再删除图像处理Lambda CloudFormation栈。虽然我认为这不是你通常想要做的事情。

© www.soinside.com 2019 - 2024. All rights reserved.