具有 launchConfiguration 和 AutoScalingGroup 的 aws cloudformation 中的 cfn 信号
cfn-signal in aws cloudformation with launchConfiguration and AutoScalingGroup
我的 AWS Cloudformation 模板中有以下配置。
模板基于instance1
创建一个EC2实例。我在 LaunchConfiguration 中使用对相同实例的引用来创建相同类型的实例。
我面临的问题是在我的 AutoScalingGroup 模板中包含 CreationPolicy 元素。当 ASG 启动实例并等待 cfn 信号时,我收到以下错误。
+ /opt/aws/bin/cfn-signal -e 0 --stack ss07 --resource Instance1 --region us-west-2
ValidationError: Resource Instance1 is in CREATE_COMPLETE state and cannot be signaled
似乎以某种方式引用了已存在的 instance1,而不是 LaunchConfig 创建的实例。我看到了其中嵌入了 LaunchConfig 的示例,但我想将实例详细信息保存在一处而不是两处。
"instance1": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"AWS::CloudFormation::Init": {
"configSets": {
"install": ["yum_packages","install_cfn"]
},
"yum_packages": {
"packages" : {
"yum" : {
"awslogs" : [],
"ruby" : [],
"wget" : [],
"httpd" : []
}
}
},
"install_cfn": {
"files": {
"/etc/cfn/cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{
"Ref": "AWS::StackId"
},
"\n",
"region=",
{
"Ref": "AWS::Region"
},
"\n"
]
]
},
"mode": "000400",
"owner": "root",
"group": "root"
},
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServer.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -v ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource splitsweetInstance ",
" --configsets install ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
},
"mode": "000400",
"owner": "root",
"group": "root"
}
},
"services": {
"sysvinit": {
"cfn-hup": { "enabled": "true", "ensureRunning": "true", "files": [
"/etc/cfn/cfn-hup.conf",
"/etc/cfn/hooks.d/cfn-auto-reloader.conf"
]
}
}
}
}
}
},
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT10M"
}
},
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI", {
"Ref": "AWS::Region"
}, {
"Fn::FindInMap": [
"AWSInstanceType2Arch", {
"Ref": "instanceType1"
},
"Arch"
]
}
]
},
"InstanceType": {"Ref": "instanceType1"},
"KeyName": {"Ref": "KeyName"},
"Monitoring": "false",
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum install -y aws-cfn-bootstrap\n",
"# Install the files and packages from the metadata\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource splitsweetInstance ",
" --configsets install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"wget ", { "Fn::FindInMap": [ "Region2CodeDeployAgent", { "Ref": "AWS::Region"}, "url"] }, "\n",
"chmod +x ./install\n",
"./install auto\n",
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource splitsweetInstance ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}},
"Tags": [
{
"Key": "Name",
"Value": "inst1"
}
],
"SecurityGroupIds": [
{ "Fn::GetAtt" : [ "instance1Sg", "GroupId" ] }
]
}
}
我的启动配置如下 -
"LaunchConfig1": {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI", {
"Ref": "AWS::Region"
}, {
"Fn::FindInMap": [
"AWSInstanceType2Arch", {
"Ref": "instanceType1"
},
"Arch"
]
}
]
},
"InstanceId" : { "Ref":"instance1"},
"InstanceMonitoring" : "false",
"InstanceType" : { "Ref": "instanceType1"},
"KeyName" : { "Ref" : "KeyName" },
"SecurityGroups" : [ { "Fn::GetAtt" : [ "instance1Sg", "GroupId" ] } ]
}
}
这是我的 AutoScalingGroup 模板 -
"AutoScalingGroup1": {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs": { "Ref": "AWS::Region" } },
"Cooldown" : "60",
....
"LaunchConfigurationName" : {"Ref":"LaunchConfig1"},
"MaxSize" : "3",
"MinSize" : "1",
"TargetGroupARNs" : [ {"Ref":"TargetGroup1"} ],
"VPCZoneIdentifier" : [ { "Ref": "subnetCache1" }, { "Ref": "subnetCache2" }, { "Ref": "subnetCache3" } ]
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT6M",
"Count" : "1"
}
}
}
问题在于,通过指定 InstanceId
property in your LaunchConfiguration
资源,它重新使用了用于启动初始 EC2 实例的相同用户数据,包括对由 [= 发出信号的逻辑资源的硬编码引用12=] 命令。根据文档,
When you use an instance to create a launch configuration, all properties are derived from the instance with the exception of BlockDeviceMapping
and AssociatePublicIpAddress
. You can override any properties from the instance by specifying them in the launch configuration.
要让 cfn-signal
发出正确的资源信号,您需要覆盖 LaunchConfiguration
资源中的 UserData
以包含引用启动配置而不是引用启动配置的用户数据脚本原始 EC2 实例。不幸的是,这将需要复制用户数据脚本,或重写脚本以动态找出与脚本当前 运行 所在的实例关联的逻辑资源,因此可以使用完全相同的用户数据原始 EC2 实例和自动缩放组。
我同意 wjordan 的观点,您遇到的部分问题是 LaunchConfiguration
中的 InstanceId
属性。另外查看您的代码示例,我无法弄清楚 splitsweetInstance
在哪里被引用。
但是我的 CloudFormation AutoScalingGroup
不是这样设置的,我仍然遇到同样的错误 CREATE_COMPLETE state and cannot be signaled
。
我的解决方案是在 AutoScalingGroup
上设置 DesiredCapacity
(希望这对其他人也有帮助)可以在这里找到:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-group.html#cfn-as-group-desiredcapacity
根据文档:
CloudFormation will not mark the Auto Scaling group as successful (by setting its status to CREATE_COMPLETE) until the desired capacity is reached.
这就是我的 CloudFormation 模板部分的样子:
"WebServerGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"VPCZoneIdentifier" : { "Ref" : "Subnets" },
"LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
"MinSize" : "2",
"MaxSize" : "4",
"DesiredCapacity" : "2",
"TargetGroupARNs" : [ { "Ref" : "ALBTargetGroup" } ]
}
下面是 UserData 部分的 "signal" 部分:
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource WebServerGroup ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
为了解决这个问题,我确保添加了 CreationPolicy 和 UpdatePolicy[=在使用 UserData[= 中的 cfn-signal 之前,Autoscaling 组中的 21=] 21=] LaunchTemplate 部分
CreationPolicy:
AutoScalingCreationPolicy:
MinSuccessfulInstancesPercent: somepercent
ResourceSignal:
Count: somenumber
Timeout: someminutes
UpdatePolicy:
AutoScalingScheduledAction:
IgnoreUnmodifiedGroupSizeProperties: 'true'
AutoScalingRollingUpdate:
MinInstancesInService: 'somenumber'
MaxBatchSize: 'somenumber'
PauseTime: someminutes
WaitOnResourceSignals: 'true'
我的 AWS Cloudformation 模板中有以下配置。
模板基于instance1
创建一个EC2实例。我在 LaunchConfiguration 中使用对相同实例的引用来创建相同类型的实例。
我面临的问题是在我的 AutoScalingGroup 模板中包含 CreationPolicy 元素。当 ASG 启动实例并等待 cfn 信号时,我收到以下错误。
+ /opt/aws/bin/cfn-signal -e 0 --stack ss07 --resource Instance1 --region us-west-2
ValidationError: Resource Instance1 is in CREATE_COMPLETE state and cannot be signaled
似乎以某种方式引用了已存在的 instance1,而不是 LaunchConfig 创建的实例。我看到了其中嵌入了 LaunchConfig 的示例,但我想将实例详细信息保存在一处而不是两处。
"instance1": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"AWS::CloudFormation::Init": {
"configSets": {
"install": ["yum_packages","install_cfn"]
},
"yum_packages": {
"packages" : {
"yum" : {
"awslogs" : [],
"ruby" : [],
"wget" : [],
"httpd" : []
}
}
},
"install_cfn": {
"files": {
"/etc/cfn/cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{
"Ref": "AWS::StackId"
},
"\n",
"region=",
{
"Ref": "AWS::Region"
},
"\n"
]
]
},
"mode": "000400",
"owner": "root",
"group": "root"
},
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServer.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -v ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource splitsweetInstance ",
" --configsets install ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
},
"mode": "000400",
"owner": "root",
"group": "root"
}
},
"services": {
"sysvinit": {
"cfn-hup": { "enabled": "true", "ensureRunning": "true", "files": [
"/etc/cfn/cfn-hup.conf",
"/etc/cfn/hooks.d/cfn-auto-reloader.conf"
]
}
}
}
}
}
},
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT10M"
}
},
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI", {
"Ref": "AWS::Region"
}, {
"Fn::FindInMap": [
"AWSInstanceType2Arch", {
"Ref": "instanceType1"
},
"Arch"
]
}
]
},
"InstanceType": {"Ref": "instanceType1"},
"KeyName": {"Ref": "KeyName"},
"Monitoring": "false",
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xe\n",
"yum install -y aws-cfn-bootstrap\n",
"# Install the files and packages from the metadata\n",
"/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource splitsweetInstance ",
" --configsets install ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"wget ", { "Fn::FindInMap": [ "Region2CodeDeployAgent", { "Ref": "AWS::Region"}, "url"] }, "\n",
"chmod +x ./install\n",
"./install auto\n",
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource splitsweetInstance ",
" --region ", { "Ref" : "AWS::Region" }, "\n"
]]}},
"Tags": [
{
"Key": "Name",
"Value": "inst1"
}
],
"SecurityGroupIds": [
{ "Fn::GetAtt" : [ "instance1Sg", "GroupId" ] }
]
}
}
我的启动配置如下 -
"LaunchConfig1": {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI", {
"Ref": "AWS::Region"
}, {
"Fn::FindInMap": [
"AWSInstanceType2Arch", {
"Ref": "instanceType1"
},
"Arch"
]
}
]
},
"InstanceId" : { "Ref":"instance1"},
"InstanceMonitoring" : "false",
"InstanceType" : { "Ref": "instanceType1"},
"KeyName" : { "Ref" : "KeyName" },
"SecurityGroups" : [ { "Fn::GetAtt" : [ "instance1Sg", "GroupId" ] } ]
}
}
这是我的 AutoScalingGroup 模板 -
"AutoScalingGroup1": {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs": { "Ref": "AWS::Region" } },
"Cooldown" : "60",
....
"LaunchConfigurationName" : {"Ref":"LaunchConfig1"},
"MaxSize" : "3",
"MinSize" : "1",
"TargetGroupARNs" : [ {"Ref":"TargetGroup1"} ],
"VPCZoneIdentifier" : [ { "Ref": "subnetCache1" }, { "Ref": "subnetCache2" }, { "Ref": "subnetCache3" } ]
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT6M",
"Count" : "1"
}
}
}
问题在于,通过指定 InstanceId
property in your LaunchConfiguration
资源,它重新使用了用于启动初始 EC2 实例的相同用户数据,包括对由 [= 发出信号的逻辑资源的硬编码引用12=] 命令。根据文档,
When you use an instance to create a launch configuration, all properties are derived from the instance with the exception of
BlockDeviceMapping
andAssociatePublicIpAddress
. You can override any properties from the instance by specifying them in the launch configuration.
要让 cfn-signal
发出正确的资源信号,您需要覆盖 LaunchConfiguration
资源中的 UserData
以包含引用启动配置而不是引用启动配置的用户数据脚本原始 EC2 实例。不幸的是,这将需要复制用户数据脚本,或重写脚本以动态找出与脚本当前 运行 所在的实例关联的逻辑资源,因此可以使用完全相同的用户数据原始 EC2 实例和自动缩放组。
我同意 wjordan 的观点,您遇到的部分问题是 LaunchConfiguration
中的 InstanceId
属性。另外查看您的代码示例,我无法弄清楚 splitsweetInstance
在哪里被引用。
但是我的 CloudFormation AutoScalingGroup
不是这样设置的,我仍然遇到同样的错误 CREATE_COMPLETE state and cannot be signaled
。
我的解决方案是在 AutoScalingGroup
上设置 DesiredCapacity
(希望这对其他人也有帮助)可以在这里找到:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-as-group.html#cfn-as-group-desiredcapacity
根据文档:
CloudFormation will not mark the Auto Scaling group as successful (by setting its status to CREATE_COMPLETE) until the desired capacity is reached.
这就是我的 CloudFormation 模板部分的样子:
"WebServerGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"VPCZoneIdentifier" : { "Ref" : "Subnets" },
"LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
"MinSize" : "2",
"MaxSize" : "4",
"DesiredCapacity" : "2",
"TargetGroupARNs" : [ { "Ref" : "ALBTargetGroup" } ]
}
下面是 UserData 部分的 "signal" 部分:
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource WebServerGroup ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
为了解决这个问题,我确保添加了 CreationPolicy 和 UpdatePolicy[=在使用 UserData[= 中的 cfn-signal 之前,Autoscaling 组中的 21=] 21=] LaunchTemplate 部分
CreationPolicy:
AutoScalingCreationPolicy:
MinSuccessfulInstancesPercent: somepercent
ResourceSignal:
Count: somenumber
Timeout: someminutes
UpdatePolicy:
AutoScalingScheduledAction:
IgnoreUnmodifiedGroupSizeProperties: 'true'
AutoScalingRollingUpdate:
MinInstancesInService: 'somenumber'
MaxBatchSize: 'somenumber'
PauseTime: someminutes
WaitOnResourceSignals: 'true'