如何解决 AWS CloudFormation 中的此循环引用?

问题描述

我正在使用 CloudFormation 创建一个通用堆栈模板,但遇到了一个相当烦人的循环引用。

总体要求:

  1. 我希望能够提供(很多其他的东西,但主要是)一个 ECS 集群服务,它使用容量提供程序自动扩展,容量提供程序使用自动扩展组,以及自动扩展组正在使用启动模板。

  2. 我不想要静态资源名称。如果由于更新而必须重新创建资源并且该特定资源必须具有唯一名称,则这会导致问题。

问题:

如果没有“知道集群名称”的启动模板(通过 UserData),服务任务就会陷入 PROVISIONING 状态。

所以我们有了第一个依赖链:

启动模板

但是集群有一个依赖链:

集群

因此,我们有一个循环引用:Cluster Launch Template

——

我能想到的一种解决方法是在另一个资源的名称(位于该依赖链之外的资源,例如目标组)上添加一个后缀作为集群的名称;这样,它就不是静态的,而且还删除了循环引用。

我的问题是:有没有更好的方法

感觉应该有一个资源,集群可以订阅,ec2实例可以发布,这样就可以消除循环依赖以及分配资源名称的需要。

解决方法

没有这样的资源可以打破依赖关系,集群名称必须预先定义。这已经被认为是一个问题,它是开放 github 问题的一部分:

注意到的问题之一是:

打破循环依赖,以便可以创建未命名的集群

目前一种解决方法 noted 是部分预定义名称,例如:

ECSCluster:
  Type: AWS::ECS::Cluster
  Properties:
    ClusterName: !Sub ${AWS::StackName}-ECSCluster

LaunchConfiguration:
  Type: AWS::AutoScaling::LaunchConfiguration
  Properties:
    UserData:
      Fn::Base64: !Sub |
          #!/bin/bash
          echo ECS_CLUSTER=${AWS::StackName}-ECSCluster >> /etc/ecs/ecs.config

或者,人们可以尝试通过开发一些 lambda 函数形式的 custom resource 来解决这个问题。因此,您可能可以使用启动模板 (LT) 创建未命名的集群,该模板为集群提供一些虚拟名称。然后,一旦集群运行,您将使用自定义资源创建具有更新集群名称的新版本的 LT,并刷新您的自动缩放组以使用新的 LT 版本。但我不确定这是否有效。尽管如此,它至少可以考虑。

,

分享来自 GitHub 问题的更新。引入新资源打破了循环依赖:集群容量提供者协会。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-clustercapacityproviderassociations.html

要在我的示例中使用它,您:

  1. 创建集群(不指定名称)
  2. 创建启动模板(使用 Ref 获取集群名称)
  3. 创建 Auto Scaling 组
  4. 创建容量提供程序
  5. 创建集群容量提供者协会

一个问题是您必须等待创建新关联,然后才能在集群上创建服务。所以请确保您的服务“取决于”这些关联!