【问题标题】:Create then change a resource in Cloud Formation在 Cloud Formation 中创建然后更改资源
【发布时间】:2020-12-30 17:12:34
【问题描述】:

首先,我对 Cloud Formation 很陌生。我正在尝试构建一个模板来部署一个相当简单的环境,其中包含两个服务。

我需要一个 S3 存储桶,只要创建一个对象,它就会触发一条消息发送到 SQS。创建这些资产时,S3 配置必须包含指向 SQS 队列的指针。但是 SQS Queue 必须有一个专门允许 S3 存储桶权限的策略。这会产生循环依赖。为了打破这个圈子,我想做以下事情:

  1. 创建 S3 存储桶
  2. 创建 SQS 队列,引用 S3 存储桶
  3. 修改 S3 存储桶以引用 SQS 队列。

当我尝试这个时,我收到一个错误,告诉我它找不到 SQS 队列。当我在 #3 中放置一个 DependsOn 命令时,它会在循环依赖中出错。

你能声明一个资源,然后在模板中用新参数重新声明它吗?如果是这样,你会怎么做。我是不是搞错了?

【问题讨论】:

  • 能否展示导致问题的实际可重现代码以及确切的错误消息?

标签: amazon-web-services amazon-cloudformation


【解决方案1】:

在这种情况下导致循环依赖的原因是使用 RefFn::GetAtt 等内部函数,这需要引用资源可用。为避免这种情况,您可以在不引用资源的情况下指定资源 ARN。以下是 CloudFormation 执行以下操作的示例模板:

  1. 创建队列
  2. 添加队列策略以向不存在的存储桶授予权限
  3. 创建存储桶

模板:

Parameters:
  BucketName:
    Description: S3 Bucket name
    Type: String
    Default: mynewshinybucket

Resources:
  Queue:
    Type: AWS::SQS::Queue

  QueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref Queue
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action: SQS:SendMessage
            Resource: !GetAtt Queue.Arn
            Principal:
              AWS: '*'
            Condition:
              ArnLike:
                # Specify bucket ARN by referring to a parameter instead of the actual bucket resource which does not yet exist
                aws:SourceArn: !Sub arn:aws:s3:::${BucketName}

  Bucket:
    Type: AWS::S3::Bucket
    # Create the bucket after the queue policy to avoid "Unable to validate the following destination configurations" errors
    DependsOn: QueuePolicy
    Properties:
      BucketName: !Ref BucketName
      NotificationConfiguration:
        QueueConfigurations:
        - Event: 's3:ObjectCreated:Put'
          Queue: !GetAtt Queue.Arn

编辑: 当使用 Ref/GetAtt/Sub 从另一个资源中检索值时,它们都需要该资源可用。 CloudFormation 将确保使用该函数的资源将始终在引用资源之后创建。这样就可以检测到循环依赖。 Sub 用于字符串替换,但在与参数或资源(Source) 一起使用时与 Ref 完全一样。

关键是我们指的是始终可用的参数(而不是资源)。 在这种情况下使用 Sub 稍微简单一些,因为使用 Ref 需要额外的Join。例如,这会给你同样的结果:

            aws:SourceArn: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref BucketName

另一种方法是在不使用任何内部函数的情况下对存储桶 ARN 进行硬编码。重要的是不要引用bucket本身来避免循环依赖。

【讨论】:

  • 所以 Ref 和 GetAtt 要求资源可用,但 !Sub 不需要?
  • @blindy 好问题。其实我的意思不够清楚,我在答案中添加了另一种解释。
猜你喜欢
  • 2018-09-15
  • 1970-01-01
  • 2021-05-29
  • 2021-01-06
  • 1970-01-01
  • 2020-11-04
  • 2019-07-05
  • 2021-05-23
  • 2018-12-07
相关资源
最近更新 更多