CloudFormation AutoScalingGroup不等待更新/扩展时的信号

Bil*_*kil 8 amazon-web-services aws-cloudformation autoscaling

我正在使用CloudFormation模板,该模板会根据我的请求调出尽可能多的实例,并希望等到它们完成初始化(通过用户数据),然后才能认为堆栈创建/更新已完成.

期望

创建或更新堆栈应等待来自所有新创建的实例的信号,以确保其初始化完成.

如果任何创建的实例无法初始化,我不希望将堆栈创建或更新视为成功.

现实

CloudFormation似乎只在等待首次创建堆栈时的实例信号.更新堆栈并增加实例数似乎忽略了信令.更新操作非常快速地成功完成,而实例仍在初始化.

由于更新堆栈而创建的实例可能无法初始化,但更新操作已经被认为是成功的.

问题

使用CloudFormation,我如何才能使现实符合预期?

我想要在创建堆栈时,以及更新堆栈时应用的相同行为.

类似的问题

我发现只有以下问题符合我的问题:Autoscaling组中的UpdatePolicy无法正常用于AWS CloudFormation更新

它已经开放一年,但没有得到答案.

我正在创建另一个问题,因为我需要添加更多信息,而且我不确定这些细节是否与该问题中的作者相匹配.

再现

为了演示此问题,我在此AWS文档页面上Auto Scaling Group标题下创建了一个模板,其中包括信令.

创建的模板已经过调整,如下所示:

  • 它使用Ubuntu AMI(在区域内ap-northeast-1).该cfn-signal命令已经过引导,并在考虑到此更改时根据需要进行调用.
  • 新参数指示在自动缩放组中启动的实例数.
  • 在发信号之前添加了2分钟的睡眠时间,以模拟初始化时花费的时间.

这是模板,保存到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}
Run Code Online (Sandbox Code Playgroud)

现在我用一个实例创建堆栈,通过:

$ aws cloudformation create-stack \
  --region=ap-northeast-1 \
  --stack-name=asg-test \
  --template-body=file://template.yml \
  --parameters ParameterKey=DesiredCapacity,ParameterValue=1
Run Code Online (Sandbox Code Playgroud)

在等待几分钟完成创建之后,让我们看看一些关键的堆栈事件:

$ aws cloudformation describe-stack-events \
  --region=ap-northeast-1 \
  --stack-name=asg-test
Run Code Online (Sandbox Code Playgroud)

 

    ...
    {
        "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",
        ...
    }
    ...
Run Code Online (Sandbox Code Playgroud)

你可以看到自动缩放组在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
Run Code Online (Sandbox Code Playgroud)

在等待更短的时间完成更新之后,让我们看看一些新的堆栈事件:

$ aws cloudformation describe-stack-events \
  --region=ap-northeast-1 \
  --stack-name=asg-test
Run Code Online (Sandbox Code Playgroud)

 

    {
        "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"
    },
    ....
Run Code Online (Sandbox Code Playgroud)

现在你可以看到,虽然自动缩放组在05:44:20开始更新,但它在05:45:43完成 - 完成时间不到一分半钟,考虑到睡眠时间不可能用户数据120秒.

然后堆栈更新进行到完成,而自动缩放组没有接收到任何信号.

新实例确实存在.

在我的实际用例中,我已经连接到其中一个新实例,发现即使在堆栈更新完成后它仍处于初始化过程中.

我试过的

我已阅读并重新读取周围的文件CreationPolicyUpdatePolicy,但未能确定什么我失踪.

看一下上面使用的更新策略,我不明白它实际上在做什么.为什么是WaitOnResourceSignals真的,但它不是在等待?它是否有其他用途?

或者这些新实例是否属于"滚动更新"政策?如果他们不属于那里,那么我希望他们属于创作政策,但这似乎也不适用.

因此,我真的不知道还有什么可以尝试.

我有一种偷偷摸摸的感觉,它的设计/预期功能正在发挥作用,但如果它是那个WaitOnResourceSignals属性的重点是什么,我怎样才能达到上述期望?

wjo*_*dan 5

AutoScalingRollingUpdate政策处理响应于改变底层旋转出整个集的自动缩放组中实例的LaunchConfiguration.它不适用于对现有组中实例数的单独更改.根据UpdatePolicy属性文档,

仅当您执行以下一项或多项操作时,AutoScalingReplacingUpdateAutoScalingRollingUpdate策略才适用:

  • 更改Auto Scaling组AWS::AutoScaling::LaunchConfiguration.
  • 更改Auto Scaling组的VPCZoneIdentifier属性
  • 更新包含与当前实例不匹配的实例的Auto Scaling组LaunchConfiguration.

更改Auto Scaling组的DesiredCapacity属性不在此列表中,因此该AutoScalingRollingUpdate策略不适用于此类更改.

据我所知,无法(使用标准的AWS CloudFormation资源)延迟完成堆栈更新修改,DesiredCapacity直到完全配置添加到Auto Scaling组的任何新实例.

以下是一些备选方案:

  1. 而不是仅DesiredCapacity修改,同时修改LaunchConfiguration属性.这将触发AutoScalingRollingUpdate到所需的容量(缺点是它还将更新现有实例,实际上可能不需要修改).
  2. 在添加AWS::AutoScaling::LifecycleHook资源到您的自动缩放集团,并呼吁aws autoscaling complete-lifecycle-actioncfn-signal,信号周期挂机完成.这不会延迟您的CloudFormation堆栈更新,但它延迟各个自动缩放的实例进入InService状态,直到收到生命周期信号.(有关详细信息,请参阅Lifecycle Hooks文档.)
  3. 作为#2的扩展,应该可以向Auto Scaling组添加Lifecycle Hook,以及轮询Auto Scaling组的自定义资源,并且仅在Auto Scaling组包含DesiredCapacity所有实例的数量时完成InService州.