【问题标题】:How to import an existing S3 bucket exported by a stack, into another stack via CloudFormation YAML如何通过 CloudFormation YAML 将堆栈导出的现有 S3 存储桶导入另一个堆栈
【发布时间】:2020-09-15 06:44:27
【问题描述】:

类似下面的 CloudformationYAML 可以工作。我最终得到一个 lambda 函数,每当新对象出现在 S3 存储桶上时就会触发该函数。

Resources:
  myS3BucketResource:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref myS3BucketName
      AccessControl: Private
      VersioningConfiguration:
        Status: Enabled

LambdaFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: main.handler
      CodeUri:
        Bucket: !Ref CodeBucketName
        Key: !Ref CodeKey
      Role: !GetAtt
        - LambdaRole
        - Arn
      Runtime: nodejs12.x
      Timeout: !Ref LambdaTimeOut
      MemorySize: !Ref LambdaMemory
      FunctionName: !Sub '${Environment}-${FunctionName}'
      Events:
        S3Event:
          Type: S3
          Properties:
            Bucket: !Ref myS3BucketResource
            Events: 
              - 's3:ObjectCreated:Put'

但是,我需要做的是让 lambda 函数使用已经存在的 S3 存储桶,该存储桶是由另一个堆栈创建的。请注意,在上面,S3 存储桶是由同样创建 lambda 的同一个 CF 模板创建的。

我似乎不能只引用 S3Event 的 Bucket 属性中的 S3 存储桶名称,如下所示:

      Events:
        S3Event:
          Type: S3
          Properties:
            Bucket: !Ref myS3BucketName
            Events: 
              - 's3:ObjectCreated:Put'

所以我认为这是因为它需要是资源而不是字符串,至少基于上面的 CF 模板有效。

我读到了关于 Fn::ImportValue 导入由另一个堆栈导出的内容的信息——这就是我需要使用的 S3 存储桶的情况。但我不知道如何在 CF 模板上指定它。

例如,在下面尝试过,但它不起作用。没有Type: AWS::S3::Bucket 行。

Resources:
  myS3BucketResource:
    Type: AWS::S3::Bucket
    Properties:
      Bucket:
        Fn::ImportValue: !Sub "${exportedS3Bucket}"

任何线索将不胜感激。如果有一种方法可以指定 Bucket 而无需通过导入路线,那真的是最好的。

谢谢!

【问题讨论】:

  • 您是否尝试过使用 ARN 而不是名称来配置存储桶?
  • 它应该与存储桶名称一起正常工作。您是否从参数中获取存储桶名称?您是否尝试在 Bucket: 'my-bucket' 中对其进行硬编码作为测试?
  • 我还没有尝试过arn,我会试一试。而且我还没有尝试对存储桶名称进行编码。但是我看不出有任何理由说明为什么在 CF 脚本中作为参数提供的存储桶名称的 !Ref 与硬编码不同。我在 CF 脚本的其他部分引用了相同的参数,它工作得很好。但我也会尝试对其进行硬编码。
  • 因此,使用 ARN 或对存储桶名称进行编码会导致相同的错误:“Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document。发现的错误数量: 1. ID为[LambdaFunction]的资源无效。ID为[S3Event]的事件无效。S3事件必须引用同一模板中的S3存储桶。用户请求回滚。"

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


【解决方案1】:

但是,我需要做的是让 lambda 函数使用已经存在的 S3 存储桶,该存储桶是由另一个堆栈创建的。

假设对 S3 bucket 存储桶堆栈具有控制权,您可以将 export 它在其他堆栈中可见,以便它们可以是 imported。您已经正确指出了这一点

由于您没有提供用于导出其输出的存储桶堆栈的代码,因此我的答案必须基于一个示例。在示例中,请注意 exportedBucket 名称的使用。

桶栈

Resources:
  myS3BucketResource:
    Type: AWS::S3::Bucket

Outputs:
  Name: 
    Value: !Ref myS3BucketResource
    Export:
      Name: exportedBucket  # <---- export bucket

lambda 栈,它将使用桶形式的桶栈:

LambdaFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: main.handler
      CodeUri:
        Bucket: !Ref CodeBucketName
        Key: !Ref CodeKey
      Role: !GetAtt
        - LambdaRole
        - Arn
      Runtime: nodejs12.x
      Timeout: !Ref LambdaTimeOut
      MemorySize: !Ref LambdaMemory
      FunctionName: !Sub '${Environment}-${FunctionName}'
      Events:
        S3Event:
          Type: S3
          Properties:
            Bucket: !ImportValue exportedBucket  # <---- import bucket
            Events: 
              - 's3:ObjectCreated:Put'

【讨论】:

  • 已在创建 S3 存储桶的堆栈上导出存储桶名称。不幸的是,执行您上面提到的操作会导致与我简单地在 S3EventBucket: 属性上指定存储桶名称时相同的错误(请参阅我作为对该问题的评论提供的错误)---这实际上是有道理的,因为导出存储桶名称实际上只是为您提供存储桶名称,而不是真正的整个资源,对吧?这与在那里对其进行硬编码或引用其值是与存储桶名称对应的字符串的参数相同。所以,还是不开心!
  • 哦,我在这里漏掉了一些东西。您实际上是在 S3 堆栈上导出资源本身,而不是存储桶名称。我会试试的。
  • 不幸的是,即使使用导出的 S3 资源也会出现相同的错误:“Transform AWS::Serverless-2016-10-31 failed with: Invalid Serverless Application Specification document. Number of errors found: 1 . ID 为 [LambdaFunction] 的资源无效。ID 为 [S3Event] 的事件无效。S3 事件必须引用同一模板中的 S3 存储桶。用户请求回滚。”该错误似乎表明 S3 存储桶需要位于同一模板上。
【解决方案2】:

找到这个 AWS 文档 => https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-s3.html

有这个:

Bucket
S3 bucket name. This bucket must exist in the same template.

Type: String

Required: Yes

AWS CloudFormation Compatibility: This property is similar to the BucketName property of an AWS::S3::Bucket. This is a required field in SAM. This field only accepts a reference to the S3 bucket created in this template

还有这个 YAML 示例:

Events:
  S3Event:
    Type: S3
    Properties:
      Bucket:
        Ref: ImagesBucket     # This must be the name of an S3 bucket declared in the same template file
      Events: s3:ObjectCreated:*
      Filter:
        S3Key:
          Rules:
          - Name: prefix      # or "suffix"
            Value: value      # The value to search for in the S3 object key names

YAML 上的注释表明 S3 存储桶需要“在同一个模板文件中声明”。而 Bucket 部分中关于 AWS CloudFormation Compatibility: 的位表示“此字段仅接受对此模板中创建的 S3 存储桶的引用”。

除非此 AWS 文档只需要更新,否则似乎没有办法通过 CF 使用现有 S3 存储桶添加 Lambda 事件触发器。这对我的用例来说并不是一个好兆头。

【讨论】:

    猜你喜欢
    • 2020-04-03
    • 2021-02-21
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2019-08-08
    相关资源
    最近更新 更多