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

时间:2017-02-03 05:57:37

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

我正在使用CloudFormation模板,该模板会根据我的要求调出尽可能多的实例,并且希望等待它们在完成堆栈创建/更新之前完成初始化(通过用户数据)。

期望

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

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

现实

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

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

问题

使用CloudFormation,我怎样才能让现实符合预期?

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

类似问题

我发现只有以下问题符合我的问题:UpdatePolicy in Autoscaling group not working correctly for AWS CloudFormation update

已开放一年,但未收到答案。

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

再生

为了证明这个问题,我根据Auto Scaling Group header on this AWS documentation page下面的示例创建了一个模板,其中包括信令。

创建的模板已经过调整:

  • 它使用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}

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

$ 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秒。

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

新实例确实存在。

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

我尝试过什么

我已阅读并重新阅读围绕CreationPolicyUpdatePolicy的文档,但未能确定我遗漏的内容。

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

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

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

我有一种偷偷摸摸的感觉,它的运作符合设计/预期,但如果是那么WaitOnResourceSignals属性的重点是什么,我怎样才能达到上述期望?

2 个答案:

答案 0 :(得分:5)

AutoScalingRollingUpdate策略处理Auto Scaling组中的整个实例集,以响应对基础LaunchConfiguration的更改。它不适用于对现有组中实例数的单独更改。根据{{​​3}}文档,

  

AutoScalingReplacingUpdateAutoScalingRollingUpdate政策仅在您执行以下一项或多项操作时适用:

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

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

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

以下是一些备选方案:

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

答案 1 :(得分:0)

滚动更新仅适用于现有实例。文档说:

  

滚动更新使您可以指定AWS CloudFormation是批量更新Auto Scaling组中的实例还是一次更新所有实例。

为了测试这个,请根据您的模板创建一个堆栈。而不是对启动配置进行小的修改(例如,设置睡眠120到121)并更新堆栈。现在您应该看到滚动更新。