我正在使用CloudFormation模板,该模板会根据我的要求调出尽可能多的实例,并且希望等待它们在完成堆栈创建/更新之前完成初始化(通过用户数据)。
创建或更新堆栈应该等待来自所有新创建的实例的信号,以确保它们的初始化完成。
如果任何创建的实例无法初始化,我不希望将堆栈创建或更新视为成功。
CloudFormation似乎只在等待首次创建堆栈时来自实例的信号。更新堆栈并增加实例数似乎忽略了信令。更新操作非常快速地成功完成,而实例仍在初始化。
由于更新堆栈而创建的实例可能无法初始化,但更新操作已被视为成功。
使用CloudFormation,我怎样才能让现实符合预期?
我想要在创建堆栈时应用相同的行为,以及更新堆栈时的行为。
我发现只有以下问题符合我的问题:UpdatePolicy in Autoscaling group not working correctly for AWS CloudFormation update
已开放一年,但未收到答案。
我正在创建另一个问题,因为我需要添加更多信息,而且我不确定这些细节是否与该问题的作者相匹配。
为了证明这个问题,我根据Auto Scaling Group header on this AWS documentation page下面的示例创建了一个模板,其中包括信令。
创建的模板已经过调整:
ap-northeast-1
中)。 cfn-signal
命令已经过引导,并在考虑到此更改时根据需要进行调用。以下是保存到template.yml
的模板:
Parameters:
DesiredCapacity:
Type: Number
Description: How many instances would you like in the Auto Scaling Group?
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones: !GetAZs ''
LaunchConfigurationName: !Ref LaunchConfig
MinSize: !Ref DesiredCapacity
MaxSize: !Ref DesiredCapacity
CreationPolicy:
ResourceSignal:
Count: !Ref DesiredCapacity
Timeout: PT5M
UpdatePolicy:
AutoScalingScheduledAction:
IgnoreUnmodifiedGroupSizeProperties: true
AutoScalingRollingUpdate:
MinInstancesInService: 1
MaxBatchSize: 2
PauseTime: PT5M
WaitOnResourceSignals: true
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: ami-b7d829d6
InstanceType: t2.micro
UserData:
'Fn::Base64':
!Sub |
#!/bin/bash -xe
sleep 120
apt-get -y install python-setuptools
TMP=`mktemp -d`
curl https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz | \
tar xz -C $TMP --strip-components 1
easy_install $TMP
/usr/local/bin/cfn-signal -e $? \
--stack ${AWS::StackName} \
--resource AutoScalingGroup \
--region ${AWS::Region}
现在我用一个实例创建堆栈,通过:
$ aws cloudformation create-stack \
--region=ap-northeast-1 \
--stack-name=asg-test \
--template-body=file://template.yml \
--parameters ParameterKey=DesiredCapacity,ParameterValue=1
等待几分钟完成创建后,让我们看看一些关键的堆栈事件:
$ aws cloudformation describe-stack-events \
--region=ap-northeast-1 \
--stack-name=asg-test
...
{
"Timestamp": "2017-02-03T05:36:45.445Z",
...
"LogicalResourceId": "AutoScalingGroup",
...
"ResourceStatus": "CREATE_COMPLETE",
...
},
{
"Timestamp": "2017-02-03T05:36:42.487Z",
...
"LogicalResourceId": "AutoScalingGroup",
...
"ResourceStatusReason": "Received SUCCESS signal with UniqueId ...",
"ResourceStatus": "CREATE_IN_PROGRESS"
},
{
"Timestamp": "2017-02-03T05:33:33.274Z",
...
"LogicalResourceId": "AutoScalingGroup",
...
"ResourceStatusReason": "Resource creation Initiated",
"ResourceStatus": "CREATE_IN_PROGRESS",
...
}
...
您可以看到自动缩放组已于05:33:33开始启动。在05:36:42(启动后3分钟),它收到了成功信号。这使得自动缩放组仅在05:36:45之后才能达到自己的成功状态。
那太棒了 - 像魅力一样工作。
现在让我们尝试通过更新堆栈将此自动缩放组中的实例数增加到2:
$ aws cloudformation update-stack \
--region=ap-northeast-1 \
--stack-name=asg-test \
--template-body=file://template.yml \
--parameters ParameterKey=DesiredCapacity,ParameterValue=2
在等待更短的时间完成更新之后,让我们看看一些新的堆栈事件:
$ aws cloudformation describe-stack-events \
--region=ap-northeast-1 \
--stack-name=asg-test
{
"ResourceStatus": "UPDATE_COMPLETE",
...
"ResourceType": "AWS::CloudFormation::Stack",
...
"Timestamp": "2017-02-03T05:45:47.063Z"
},
...
{
"ResourceStatus": "UPDATE_COMPLETE",
...
"LogicalResourceId": "AutoScalingGroup",
"Timestamp": "2017-02-03T05:45:43.047Z"
},
{
"ResourceStatus": "UPDATE_IN_PROGRESS",
...,
"LogicalResourceId": "AutoScalingGroup",
"Timestamp": "2017-02-03T05:44:20.845Z"
},
{
"ResourceStatus": "UPDATE_IN_PROGRESS",
...
"ResourceType": "AWS::CloudFormation::Stack",
...
"Timestamp": "2017-02-03T05:44:15.671Z",
"ResourceStatusReason": "User Initiated"
},
....
现在你可以看到,虽然自动缩放组在05:44:20开始更新,但它在05:45:43完成 - 这不到一分半钟即可完成,考虑到用户数据中的休眠时间为120秒。
堆栈更新然后进行到完成,而自动缩放组没有收到任何信号。
新实例确实存在。
在我的实际用例中,我已经连接到其中一个新实例,发现即使在堆栈更新完成后它仍处于初始化过程中。
我已阅读并重新阅读围绕CreationPolicy
和UpdatePolicy
的文档,但未能确定我遗漏的内容。
看一下上面使用的更新策略,我不明白它实际上在做什么。为什么WaitOnResourceSignals
是真的,但它不等待?是否有其他用途?
或者这些新实例是否属于“滚动更新”政策?如果他们不属于那里,那么我希望他们属于创作政策,但这似乎也不适用。
因此,我真的不知道还有什么可以尝试。
我有一种偷偷摸摸的感觉,它的运作符合设计/预期,但如果是那么WaitOnResourceSignals
属性的重点是什么,我怎样才能达到上述期望?
答案 0 :(得分:5)
AutoScalingRollingUpdate
策略处理Auto Scaling组中的整个实例集,以响应对基础LaunchConfiguration
的更改。它不适用于对现有组中实例数的单独更改。根据{{3}}文档,
AutoScalingReplacingUpdate
和AutoScalingRollingUpdate
政策仅在您执行以下一项或多项操作时适用:
- 更改Auto Scaling组的
AWS::AutoScaling::LaunchConfiguration
。- 更改Auto Scaling组的
VPCZoneIdentifier
属性- 更新包含与当前
LaunchConfiguration
不匹配的实例的Auto Scaling组。
更改Auto Scaling组的DesiredCapacity
属性不在此列表中,因此AutoScalingRollingUpdate
策略不适用于此类更改。
据我所知,使用标准AWS CloudFormation资源无法延迟完成修改DesiredCapacity
的堆栈更新,直到添加到Auto Scaling组的任何新实例完全配置为止。
以下是一些备选方案:
DesiredCapacity
,而是同时修改LaunchConfiguration
属性。这将触发AutoScalingRollingUpdate
到期望的容量(缺点是它还将更新现有实例,实际上可能不需要修改)。cfn-signal
之外调用AWS::AutoScaling::LifecycleHook
,以指示生命周期挂钩完成。这不会延迟您的CloudFormation堆栈更新,但它将延迟各个自动缩放的实例进入InService
状态,直到收到生命周期信号。 (有关详细信息,请参阅aws autoscaling complete-lifecycle-action
文档。)DesiredCapacity
状态的InService
个实例。答案 1 :(得分:0)
滚动更新仅适用于现有实例。文档说:
滚动更新使您可以指定AWS CloudFormation是批量更新Auto Scaling组中的实例还是一次更新所有实例。
为了测试这个,请根据您的模板创建一个堆栈。而不是对启动配置进行小的修改(例如,设置睡眠120到121)并更新堆栈。现在您应该看到滚动更新。