CloudFormation AutoScalingGroup no espera señal en la actualización / escalado

Estoy trabajando con una plantilla de CloudFormation que muestra tantas instancias como solicito, y quiero esperar a que finalicen la inicialización (a través de los Datos del usuario) antes de que la creación / actualización de la pila se considere completa.

La expectativa

La creación o actualización de la pila debe esperar las señales de todas las instancias recién creadas, para garantizar que se complete su inicialización.

No quiero que la creación o actualización de la pila se considere exitosa si alguna de las instancias creadas no se inicializa.

La realidad

CloudFormation solo parece esperar señales de instancias cuando se crea la pila por primera vez. Actualizar la pila y aumentar el número de instancias parece ignorar la señalización. La operación de actualización finaliza con éxito muy rápidamente, mientras que las instancias todavía se están inicializando.

Las instancias creadas como resultado de la actualización de la pila pueden fallar al inicializarse, pero la acción de actualización ya se habría considerado un éxito.

La pregunta

Usando CloudFormation, ¿cómo puedo hacer que la realidad cumpla con las expectativas?

Quiero el mismo comportamiento que se aplica cuando se crea la pila, cuando se actualiza la pila.

Preguntas similares

Solo he encontrado la siguiente pregunta que coincide con mi problema:UpdatePolicy en el grupo de escalado automático no funciona correctamente para la actualización de AWS CloudFormation

Ha estado abierto durante un año y no ha recibido una respuesta.

Estoy creando otra pregunta ya que tengo más información para agregar, y no estoy seguro de si estos detalles coincidirán con los del autor en esa pregunta.

Reproducción

Para demostrar el problema, he creado una plantilla basada en el ejemplo debajo deEncabezado de Auto Scaling Group en esta página de documentación de AWS, que incluye señalización.

La plantilla creada se ha adaptado así:

Utiliza un Ubuntu AMI (en la regiónap-northeast-1) loscfn-signal El comando se ha inicializado y se ha llamado según sea necesario teniendo en cuenta este cambio.Un nuevo parámetro dicta cuántas instancias lanzar en el grupo de escalado automático.Se ha agregado un tiempo de reposo de 2 minutos antes de la señalización, para simular el tiempo empleado durante la inicialización.

Aquí está la plantilla, guardada entemplate.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}

Ahora creo la pila con una sola instancia, a través de:

$ aws cloudformation create-stack \
  --region=ap-northeast-1 \
  --stack-name=asg-test \
  --template-body=file://template.yml \
  --parameters ParameterKey=DesiredCapacity,ParameterValue=1

Después de esperar unos minutos a que se complete la creación, veamos algunos eventos de la pila de claves:

$ 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",
        ...
    }
    ...

Puede ver que el grupo de escalado automático comenzó a iniciarse a las 05:33:33. A las 05:36:42 (3 minutos después del inicio), recibió una señal de éxito. Esto permitió que el grupo de escalado automático alcanzara su propio estado de éxito solo unos momentos después, a las 05:36:45.

Eso es increíble, trabajar como un encanto.

Ahora intentemos aumentar el número de instancias en este grupo de escalado automático a 2 actualizando la pila:

$ aws cloudformation update-stack \
  --region=ap-northeast-1 \
  --stack-name=asg-test \
  --template-body=file://template.yml \
  --parameters ParameterKey=DesiredCapacity,ParameterValue=2

Después de esperar un tiempo mucho más corto para que se complete la actualización, veamos algunos de los nuevos eventos de pila:

$ 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"
    },
    ....

Ahora puede ver que si bien el grupo de autoescalado comenzó a actualizarse a las 05:44:20, se completó a las 05:45:43, eso es menos de un minuto y medio para completarse, lo que no debería ser posible considerando un tiempo de sueño de 120 segundos en los datos del usuario.

La actualización de la pila continúa hasta su finalización sin que el grupo de escalado automático haya recibido ninguna señal.

La nueva instancia sí existe.

En mi caso de uso real, he introducido SSH en una de estas nuevas instancias para descubrir que todavía estaba en proceso de inicialización incluso después de que se completara la actualización de la pila.

Lo que he probado

He leído y releído la documentación que rodeaCreationPolicy yUpdatePolicy, pero no he podido identificar lo que me falta.

Echando un vistazo a la política de actualización en uso anterior, no entiendo lo que realmente está haciendo. Por que esWaitOnResourceSignals cierto, pero no está esperando? ¿Tiene algún otro propósito?

¿O estas nuevas instancias no están incluidas en la política de "actualización continua"? Si no pertenecen allí, entonces esperaría que cayeran bajo la política de creación, pero eso tampoco parece aplicarse.

Como tal, no sé qué más probar.

Tengo la sensación de que está funcionando según lo diseñado / esperado, pero si es así, ¿cuál es el punto de eso?WaitOnResourceSignals propiedad y cómo puedo cumplir con las expectativas establecidas anteriormente?

Respuestas a la pregunta(2)

Su respuesta a la pregunta