为多个实例重用AWS :: CloudFormation :: Init(和userdata?)

时间:2014-12-16 07:21:53

标签: amazon-web-services amazon-ec2 amazon-cloudformation

是否可以在AWS::CloudFormation::Init(和/或userdata)中为模板中的多个EC2::Instance重复使用相同的引导配置?

我需要设置3个文件的内容,然后运行3个命令来引导所有服务器,但Metadata块大约30行(并且可能会增长)。  每个服务器实例都有一组不同的标签,有些标签比其他标签更多。

理想情况下,我认为您应该能够将AWS::CloudFormation::Init声明为资源,并从多个EC2::Instance引用它,但我不认为这是可能的。

我最初认为(作为新手)AWS::CloudFormation::CustomResource可能是合适的,但我认为不是。

我目前正在考虑使用AWS::CloudFormation::Stack导入共享实例模板,但我需要以某种方式将堆栈模板中每个资源的Tags参数传递给实例模板。问题是 - 如果这是最好的方法,我应该在目前有????的3个地点输入什么?

(奖励积分 - userdata与此init阻止之间的区别是什么?)

stack.template

...
"Resources" : {
  "Server1" : {
    "Type": "AWS::CloudFormation::Stack",
    "Properties": {
      "Parameters": {
        "InstanceType": "m1.medium",
        ...
        "Tags": { ???? }
      },
      "TemplateURL": "https://s3.amazonaws.com/mybucket/instance.template"
    }

instance.template

...
"Parameters" : {
   "InstanceType" : {...}
   "KeyName": {...}
   ...
   "Tags": {
       ????
   }
},

"Resources" : {
    "Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "files" : {
              "/etc/apt/apt.conf.d/99auth" : {
                "content" : "APT::Get::AllowUnauthenticated yes;"
              },
              "/etc/apt/sources.list.d/my-repo.list" : {
                "content" : "deb  http://my-repo/repo apt/"
              },
          },
            "commands" : {
              "01-apt-get update" : {
                "command" : "apt-get update"
              },
              "02-apt-get install puppet" : {
                "command" : "apt-get install puppet my-puppet-config"
              },
              "03-puppet apply" : {
                "command" : "puppet apply"
              }
            }
          }
        }
      },
      "Properties" : {
        "InstanceType" : {"Ref" : "InstanceType"},
        "ImageId" : "ami-84a333be",
        "KeyName" : {"Ref" : "KeyName"},
        "SubnetId" : {"Ref" : "SubnetId"},
        "SecurityGroupIds" : [ { "Ref" : "SecurityGroupId"] } ],
        "Tags" : [
          ????
        ]
      }
    }
}

1 个答案:

答案 0 :(得分:8)

  

是否可以重用相同的bootstrapping配置   AWS :: CloudFormation :: Init(和/或userdata)用于多个   EC2 ::模板中的实例?

不,在单个模板中使用AWS :: EC2 :: Instance资源是不可能的。但是,存在资源类型AWS::AutoScaling::LaunchConfiguration,但今天此资源仅适用于Auto Scaling组。理想情况下,AWS将提供可应用于多个AWS :: EC2 :: Instance资源的类似资源类型。话虽如此,有很多value in using Auto Scaling groups

这是一个简单的示例,允许您在单个模板中使用单个启动配置和多个Auto Scaling组资源执行此操作。自动扩展通常配置有多个实例,但我使用MinSize和MaxSize为1来镜像您使用AWS :: EC2 :: Instance资源类型进行的配置。即使我们使用Auto Scaling组的单个实例,我们仍然可以通过单实例弹性获得Auto Scaling的优势。如果实例变得不健康,Auto Scaling将自动替换实例。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources" : {
    "LaunchConfig" : {
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
      "Properties" : {
        "InstanceType" : { "Ref" : "InstanceType" },
        "ImageId" : "ami-84a333be",
        "KeyName" : { "Ref" : "KeyName" },
        "SecurityGroupIds" : [{"Ref" : "SecurityGroupId"}],
        "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [
          "#!/bin/bash -v\n",

          "# Run cfn-init\n",
          "/opt/aws/bin/cfn-init -v ",
          "    -stack ", { "Ref": "AWS::StackName" },
          "    -resource LaunchConfig ",
          "    --region ", { "Ref" : "AWS::Region" }, "\n",

          "# Signal success\n",
          "/opt/aws/bin/cfn-signal -e $? '", { "Ref" : "WaitConditionHandle" }, "'\n"
        ]]}}
      },
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "files" : {
              "/etc/apt/apt.conf.d/99auth" : {
                "content" : "APT::Get::AllowUnauthenticated yes;"
              },
              "/etc/apt/sources.list.d/my-repo.list" : {
                "content" : "deb  http://my-repo/repo apt/"
              }
            },
            "commands" : {
              "01-apt-get update" : {
                "command" : "apt-get update"
              },
              "02-apt-get install puppet" : {
                "command" : "apt-get install puppet my-puppet-config"
              },
              "03-puppet apply" : {
                "command" : "puppet apply"
              }
            }
          }
        }
      }
    },   
    "ASG1" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "Properties" : {
        "AvailabilityZones" : [ { "Ref" : "AZ" } ],
        "VPCZoneIdentifier" : [ { "Ref" : "SubnetId" } ],
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MaxSize" : "1",
        "MinSize" : "1",
        "Tags" : [
          { "Key" : "Name", "Value": "Server1", "PropagateAtLaunch" : "true" },
          { "Key" : "Version", "Value": "1.0", "PropagateAtLaunch" : "true" }
        ]
      }
    },
    "ASG2" : {
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
      "Properties" : {
        "AvailabilityZones" : [ { "Ref" : "AZ" } ],
        "VPCZoneIdentifier" : [ { "Ref" : "SubnetId" } ],
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
        "MaxSize" : "1",
        "MinSize" : "1",
        "Tags" : [
          { "Key" : "Name", "Value": "Server2", "PropagateAtLaunch" : "true" },
          { "Key" : "Version", "Value": "1.0", "PropagateAtLaunch" : "true" }
        ]
      }
    },
    "WaitConditionHandle" : {
      "Type" : "AWS::CloudFormation::WaitConditionHandle"
    },
    "WaitCondition" : {
      "Type" : "AWS::CloudFormation::WaitCondition",
      "Properties" : {
        "Handle" : { "Ref" : "WaitConditionHandle" },
        "Timeout" : "300"
      }
    }
  }
}

这是一个不完整的示例,您可以使用Auto Scaling做更多的事情,但我只想给您一个简单的示例,与多个实例共享启动配置。每个Auto Scaling组都会定义自己的一组标记。


  

我目前正在考虑使用AWS :: CloudFormation :: Stack进行导入   共享实例模板,但我需要以某种方式传递标签   将堆栈模板中的每个资源的参数放入实例中   模板。问题是 - 如果这是最好的方法,我该怎么做   输入目前有?????

的3个地点

我会推荐上面描述的解决方案,但我也想回答一些关于如何使用嵌套堆栈方法的问题。

<强> stack.template

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources" : {
    "Server1" : {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/mybucket/instance.template",
        "Parameters": {
          "InstanceType": "m1.medium",
          "TagName": "Server1"
          "TagVersion": "1.0"
        }
      }
    },
    "Server2" : {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/mybucket/instance.template",
        "Parameters": {
          "InstanceType": "m1.medium",
          "TagName": "Server2"
          "TagVersion": "1.0"
        }
      }
    }
  }
}

<强> instance.template

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters" : {
     "InstanceType" : {...},
     "KeyName": {...}
     "TagName": {
       "Description" : "The name tag to be applied to each instance",
       "Type" : "String"
     },
     "TagVersion": {
       "Description" : "The version tag to be applied to each instance",
       "Type" : "String"
     }
  },

  "Resources" : {
    "Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          ...
        }
      },
      "Properties" : {
        "InstanceType" : { "Ref" : "InstanceType" },
        "ImageId" : "ami-84a333be",
        "KeyName" : { "Ref" : "KeyName" },
        "SubnetId" : { "Ref" : "SubnetId" },
        "SecurityGroupIds" : [ { "Ref" : "SecurityGroupId"] } ],
        "Tags" : [
          { "Key" : "Name", "Value": { "Ref" : "TagName" } },
          { "Key" : "Version", "Value": { "Ref" : "TagVersion" } },
        ]
      }
    }
  }
}

没有将整个标记数组作为参数传递的标准,因此您可以看到我只是将每个标记分解为自己的参数并将它们传递给嵌套的堆栈。


  

(奖励积分 - userdata与此init之间的区别   方框?)

UserData允许您在首次启动时将任意数据传递给实例。通常,这是一个shell脚本,可以在实例启动时自动执行任务。例如,您可以简单地运行yum update。

"UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [
  "#!/bin/bash\n"
  "yum update -y", "\n"
]]}}

当与AWS::CloudFormation::Init元数据结合使用时,UserData变得更加有用,它允许您构建引导配置。在这种情况下,UserData仅用于调用执行AWS :: CloudFormation :: Init元数据的cfn-init脚本。我在上面的第一个示例中使用启动配置包含了此模式。请务必注意,UserData部分仅在第一次引导实例期间执行一次。在考虑如何处理实例更新时,请务必牢记这一点。