简体   繁体   English

解决AWS CloudFormation中的循环依赖关系

[英]Work around circular dependency in AWS CloudFormation

The following AWS CloudFormation gives a circular dependency error. 以下AWS CloudFormation给出了循环依赖项错误。 My understanding is that the dependencies flow like this: rawUploads -> generatePreview -> previewPipeline -> rawUploads . 我的理解是,依赖项的流程如下: rawUploads -> generatePreview -> previewPipeline -> rawUploads Although it doesn't seem like rawUploads depends on generatePreview , I guess CF needs to know what lambda to trigger when creating the bucket, even though the trigger is defined in the lambda part of the CloudFormation template. 尽管rawUploads似乎不依赖于generatePreview ,但我猜想CF需要知道创建存储桶时要触发的lambda,即使触发器是在CloudFormation模板的lambda部分中定义的。

I've found some resources online that talk about a similar issue, but it doesn't seem to apply here. 我在网上找到了一些讨论类似问题的资源,但似乎在这里并不适用。 https://aws.amazon.com/premiumsupport/knowledge-center/unable-validate-circular-dependency-cloudformation/ https://aws.amazon.com/premiumsupport/knowledge-center/unable-validate-circular-dependency-cloudformation/

What are my options for breaking this circular dependency chain? 我有什么选择来打破这种循环依赖链? Scriptable solutions are viable, but multiple deployments with manual changes are not for my use case. 可编写脚本的解决方案是可行的,但是对于我的用例而言,具有手动更改的多个部署不可行。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  rawUploads:
    Type: 'AWS::S3::Bucket'
  previewAudioFiles:
    Type: 'AWS::S3::Bucket'

  generatePreview:
    Type: AWS::Serverless::Function
    Properties:
      Handler: generatePreview.handler
      Runtime: nodejs6.10
      CodeUri: .
      Environment:
        Variables:
          PipelineId: !Ref previewPipeline
      Events:
        BucketrawUploads:
          Type: S3
          Properties:
            Bucket: !Ref rawUploads
            Events: 's3:ObjectCreated:*'

  previewPipeline:
    Type: Custom::ElasticTranscoderPipeline
    Version: '1.0'
    Properties:
      ServiceToken:
        Fn::Join:
        - ":"
        - - arn:aws:lambda
          - Ref: AWS::Region
          - Ref: AWS::AccountId
          - function
          - aws-cloudformation-elastic-transcoder-pipeline-1-0-0
      Name: transcoderPipeline
      InputBucket:
        Ref: rawUploads
      OutputBucket:
        Ref: previewAudioFiles

One way is to give the S3 buckets explicit names so that later, instead of relying on Ref: bucketname , you can simply use the bucket name. 一种方法是为S3存储桶指定明确的名称,以便以后无需依赖Ref: bucketname即可使用存储桶名称。 That's obviously problematic if you want auto-generated bucket names and in those cases it's prudent to generate the bucket name from some prefix plus the (unique) stack name, for example: 如果要自动生成的存储桶名称,这显然是有问题的,在这种情况下,谨慎地从一些前缀加上(唯一的)堆栈名称生成存储桶名称,例如:

InputBucket: !Join ["-", ['rawuploads', Ref: 'AWS::StackName']]

Another option is to use a single CloudFormation template but in 2 stages - the 1st stage creates the base resources (and whatever refs are not circular) and then you add the remaining refs to the template and do a stack update. 另一个选择是使用单个CloudFormation模板,但需要两个阶段-第一阶段创建基础资源(以及所有非循环引用),然后将剩余的引用添加到模板中并进行堆栈更新。 Not ideal, obviously, so I would prefer the first approach. 显然,这并不理想,所以我更喜欢第一种方法。

You can also use the first technique in cases when you need a reference to an ARN, for example: 在需要引用ARN的情况下,也可以使用第一种技术,例如:

!Join ['/', ['arn:aws:s3:::logsbucket', 'AWSLogs', Ref: 'AWS:AccountId', '*']]

When using this technique, you may want to also consider using DependsOn because you have removed an implicit dependency which can sometimes cause problems. 使用此技术时,您可能还需要考虑使用DependsOn,因为您已删除了一个隐式依赖关系,该依赖关系有时会导致问题。

This post helped me out in the end: https://aws.amazon.com/premiumsupport/knowledge-center/unable-validate-destination-s3/ 这篇文章最终对我有所帮助: https : //aws.amazon.com/premiumsupport/knowledge-center/unable-validate-destination-s3/

I ended up configuring an SNS topic in CloudFormation. 我最终在CloudFormation中配置了一个SNS主题。 The bucket would push events on this topic, and the Lambda function listens to this topic. 值区会推送与此主题相关的事件,Lambda函数会侦听此主题。 This way the dependency graph is as follows: 这样,依赖图如下所示:

S3 bucket -> SNS topic -> SNS topic policy
Lambda function -> SNS topic
Lambda function -> transcoder pipeline

Something along the lines of this (some policies omitted) 与此类似(省略一些策略)

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
        - Sid: Statement-id
          Effect: Allow
          Principal:
            AWS: "*"
          Action: sns:Publish
          Resource:
            Ref: SNSTopic
          Condition:
            ArnLike:
              aws:SourceArn:
                !Join ["-", ['arn:aws:s3:::rawuploads', Ref: 'AWS::StackName']]
      Topics:
      - Ref: SNSTopic

  rawUploads:
    Type: 'AWS::S3::Bucket'
    DependsOn: SNSTopicPolicy
    Properties:
      BucketName: !Join ["-", ['rawuploads', Ref: 'AWS::StackName']]
      NotificationConfiguration:
        TopicConfigurations:
          - Topic:
              Ref: "SNSTopic"
            Event: 's3:ObjectCreated:*'

  previewAudioFiles:
    Type: 'AWS::S3::Bucket'


  generatePreview:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Join ["-", ['generatepreview', Ref: 'AWS::StackName']]
      Handler: generatePreview.handler
      Runtime: nodejs6.10
      CodeUri: .
      Environment:
        Variables:
          PipelineId: !Ref previewPipeline
      Events:
        BucketrawUploads:
          Type: SNS
          Properties:
            Topic: !Ref "SNSTopic"

  previewPipeline:
    Type: Custom::ElasticTranscoderPipeline
    DependsOn: 'rawUploads'
    Version: '1.0'
    Properties:
      ServiceToken:
        Fn::Join:
        - ":"
        - - arn:aws:lambda
          - Ref: AWS::Region
          - Ref: AWS::AccountId
          - function
          - aws-cloudformation-elastic-transcoder-pipeline-1-0-0
      Name: transcoderPipeline
      InputBucket:
        !Join ["-", ['arn:aws:s3:::rawuploads', Ref: 'AWS::StackName']]
      OutputBucket:
        Ref: previewAudioFiles

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM