如何在 CloudFormation 中向 Opsworks Stack 注册 ECS 集群?

Posted

技术标签:

【中文标题】如何在 CloudFormation 中向 Opsworks Stack 注册 ECS 集群?【英文标题】:How to register ECS Cluster with Opsworks Stack in CloudFormation? 【发布时间】:2015-11-17 03:03:08 【问题描述】:

我不知道如何在 CloudFormation 中使用 ECS 集群设置 OpsWorks 层。由于以下错误,我的图层创建失败,但似乎没有一种明确的方法可以将集群注册到模板中的堆栈。我尝试将EcsClusterArn 添加到堆栈和层,但没有奏效。 API 有一个命令,但我想在我的模板中包含所有内容。

错误:

Attributes - EcsClusterArn: XXX must be registered to the layer's stack first.

模板片段:

"ecsCluster" : 
  "Type" : "AWS::ECS::Cluster"
,
...
"opsworksStack" : 
  "Type" : "AWS::OpsWorks::Stack",
  "Properties" : 
    "Name" : "my-stack",
    "ServiceRoleArn" : 
      "Fn::Join" : [ "", [ "arn:aws:iam::", 
        "Ref" : "AWS::AccountId"
      , ":role/", 
        "Ref" : "ServiceRole"
       ] ]
    ,
    "DefaultInstanceProfileArn" : 
      "Fn::Join" : [ "", [ "arn:aws:iam::", 
        "Ref" : "AWS::AccountId"
      , ":instance-profile/", 
        "Ref" : "InstanceRole"
       ] ]
    ,
    "UseOpsworksSecurityGroups" : "false",
    "ChefConfiguration" : 
      "BerkshelfVersion" : "3.3.0",
      "ManageBerkshelf" : "true"
    ,
    "ConfigurationManager" : 
      "Name" : "Chef",
      "Version" : "11.10"
    
  
,
"opsworksLayer" : 
  "Type" : "AWS::OpsWorks::Layer",
  "DependsOn" : "ecsCluster",
  "Properties" : 
    "StackId" : 
      "Ref" : "opsworksStack"
    ,
    "Type" : "ecs-cluster",
    "Name" : "my-layer",
    "Shortname" : "my-layer",
    "Attributes" : 
      "EcsClusterArn" : 
        "Fn::Join" : [ "", [ "arn:aws:ecs:", 
          "Ref" : "AWS::Region"
        , ":", 
          "Ref" : "AWS::AccountId"
        , ":cluster/", 
          "Ref" : "ecsCluster"
         ] ]
      
    ,
    "CustomSecurityGroupIds" : [ 
      "Ref" : "ec2DefaultSecurityGroup"
     ],
    "EnableAutoHealing" : "true",
    "AutoAssignElasticIps" : "false",
    "AutoAssignPublicIps" : "false",
    "InstallUpdatesOnBoot" : "true"
  

谢谢, 天

【问题讨论】:

您好 Thien,我只是想知道您是否能够解决此问题?在将 ECS 集群附加到 Opsworks 堆栈时,我也面临同样的错误。 @ManishJoshi 我在 Amazon 创建了一个案例,他们已于 2016 年 2 月 24 日解决了该错误。它现在应该可以在 OpsWorks 层的“属性”部分中使用“EcsClusterArn”,如所述在文档中。 谢谢@Thien,不幸的是它仍然不适合我,我已经向亚马逊提出了案例,他们仍在调查中。如果我也发现此错误的其他原因,我会告诉这里的人:) 【参考方案1】:

我的印象是集群注册到栈失败。为了解决这个问题,我实现了一个 lambda 函数来手动进行注册。我在 github 上发布了一个示例模板:https://github.com/arjenderijke/aws-cloud-examples/blob/master/cloudformation/opsworks/opsworks-ecs-layer.template

cloudformation 模板包含一个完整的 opsworks 堆栈示例,其中包含一个 ecs 层和其他最少的所需资源。堆栈通常无法创建,因为 ecs 集群未自动注册。为了解决这个问题,模板实现了一个运行 aws lambda 函数的自定义资源。此函数将集群注册到堆栈。通过使用此自定义资源,不再发生错误。

 "OpsworksRegisterCluster": 
  "Type": "AWS::Lambda::Function",
  "Properties": 
    "Handler": "index.lambda_handler",
    "Role":  "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] ,
    "Code": 
      "ZipFile":   "Fn::Join": ["\n", [
        "import boto3",
        "import json",
        "import cfnresponse",
        "ecsclient = boto3.client('ecs')",
        "opsworksclient = boto3.client('opsworks',",
        "  region_name='us-east-1',",
        "  endpoint_url='https://opsworks.us-east-1.amazonaws.com')",
        "def lambda_handler(event, context):",
        "  try:",
        "    if (event['RequestType'] == 'Create'):",
        "      ecscluster = ecsclient.describe_clusters(clusters=[",
        "        event['ResourceProperties']['EcsClusterName']])",
        "      response = opsworksclient.register_ecs_cluster(",
        "        EcsClusterArn=ecscluster['clusters'][0]['clusterArn'],",
        "        StackId=event['ResourceProperties']['OpsworksStackId']",
        "      )",
        "      responseData = ",
        "      responseData['data'] = response['EcsClusterArn']",
        "      cfnresponse.send(event, context, cfnresponse.SUCCESS,   responseData, \"CustomResourcePhysicalID\")",
        "    else:",
        "      responseData = ",
        "      cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")",
        "  except Exception as e:",
        "    responseData = ",
        "    responseData['error'] = e.message",
        "    cfnresponse.send(event, context, cfnresponse.FAILED, responseData, \"CustomResourcePhysicalID\")"
      ]]
    ,
    "Runtime": "python2.7",
    "Timeout": "10"
  
,

【讨论】:

【参考方案2】:

据大家所知,几天前我在使用 AWS cloudformation 时遇到了这个问题,为此我向 Amazon 提出了一个案例。

似乎这个问题仍然存在于他们的 API 中(正如 Thien 在 cmets 中指出的那样,这个 bug 应该在 2016 年 2 月解决)并且尚未解决,不确定是因为我使用的是嵌套堆栈存在这个问题(可能在单个模板中不是这样,我没试过)。

AWS 人员要求我使用 lambda 函数来解决此问题,它与上面 @Arjen 提供的 lambda 函数非常相似。所以如果你遇到这个问题,请使用上面提供的 lambda 函数。

谢谢, 马尼什

【讨论】:

【参考方案3】:

根据Adding an ECS Cluster Layer to a Stack 部分,将集群与堆栈关联需要两个操作

[...] 向堆栈注册集群,然后创建关联层。 AWS OpsWorks 控制台结合了这些步骤;层创建会自动注册指定的集群。 如果您使用 AWS OpsWorks API、CLI 或 SDK,则必须使用单独的操作来注册集群并创建关联层[强调我的]

您声明您尝试将EcsClusterArn 添加到堆栈和层,但没有成功,但错误消息确认Amazon ECS 集群必须注册到层的首先堆栈,而您的示例模板实际上缺少这方面?以防万一,您可能只需要重复您的响应。来自AWS::OpsWorks::Layer 的片段也在AWS::OpsWorks::Stack 内:

   "Attributes" : 
      "EcsClusterArn" : 
        "Fn::Join" : [ "", [ "arn:aws:ecs:", 
          "Ref" : "AWS::Region"
        , ":", 
          "Ref" : "AWS::AccountId"
        , ":cluster/", 
          "Ref" : "ecsCluster"
         ] ]
      
    ,

【讨论】:

是的,这就是我之前尝试过的,但从我发布的内容中删除了它。我只是仔细检查过,它仍然给我同样的错误。

以上是关于如何在 CloudFormation 中向 Opsworks Stack 注册 ECS 集群?的主要内容,如果未能解决你的问题,请参考以下文章

AWS CloudFormation 脚本失败 - 不允许 Cognito 使用您的电子邮件身份

如何在 CloudFormation 中启用 VirtualMFADevice?

如何在 cloudformation“Fn::Sub”中转义“$”

如何知道 sam/cloudformation 堆栈 lambda 正在执行啥

Cloudformation - 如何在代码中设置 SNS 订阅的过滤策略?

如何使用 CloudFormation 添加用户池的资源服务器?