Como executar o script ec2 UserData na atualização do cloudformation

Oct 01 2020

Eu tenho o script ec2 userData que faz docker-compose pull and up.

Quero executar "aws cloudformation update-stack" e carregar novas imagens do docker. Cada vez que a propriedade $ {imageTag} muda.

Esta é minha instância de cloudformation yml:

 myInstance:
    Type: 'AWS::EC2::Instance'
    Metadata:
      'AWS::CloudFormation::Init':
        configSets:
          configs:
            - "configDockers"
            - "configOther"
        configDocker:
          commands:
            a:
              command: 'echo -e IMAGE_TAG=${imageTag} >> .env'
            b:
              command: 'docker-compose pull'
            c:
              command: 'docker-compose up'
    Properties:
      UserData:
        Fn::Base64:
          !Sub |
          runcmd:
           - /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource myInstance --region ${AWS::Region} -c configs
           - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource myInstance --region ${AWS::Region}

Tentei adicionar "docker-compose down", remover imagens antigas no script UserData e adicionar cloud_final_modules para executar UserData a cada inicialização:

 myInstance:
    Type: 'AWS::EC2::Instance'
    Metadata:
      'AWS::CloudFormation::Init':
        configSets:
          configs:
            - "configDockers"
            - "configOther"
        configDocker:
          commands:
            a:
              command: 'echo -e IMAGE_TAG=${imageTag} >> .env'
            b:
              command: 'docker-compose down'
            c:
              command: 'docker images -q | xargs -r sudo docker rmi'
            d:
              command: 'docker-compose pull'
            e:
              command: 'docker-compose up'
    Properties:
      UserData:
        Fn::Base64:
          !Sub |
          #cloud-config
          cloud_final_modules:
           - [scripts-user, always]
          runcmd:
           - /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource myInstance --region ${AWS::Region} -c configs
           - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource myInstance --region ${AWS::Region}

Mas depois de "aws cloudformation update-stack", o script não é executado novamente, apesar da imageTag ser alterada. ele é executado apenas se eu alterar algum valor em runcmd.

Como posso executar o script UserData cada vez que "aws cloudformation update-stack" é executado (cada vez que imageTag muda)?

Como posso executar alguns comandos UserData apenas na primeira inicialização, outros comandos em cada reinicialização e outros comandos na instância de parada?

por exemplo: desejo executar "docker-compose down" apenas na parada da instância, mas outros comandos de comando: 'docker-compose pull / up' em cada reinicialização da instância ou "aws cloudformation update-stack" e alguns comandos iniciais apenas na primeira configuração .

Respostas

1 Marcin Oct 01 2020 at 07:14

Como posso executar alguns comandos UserData apenas na primeira inicialização, outros comandos em cada reinicialização e outros comandos na instância de parada?

Você não pode. UserDatadestina-se a ser executado apenas na inicialização da instância, não reinicializa, inicia ou pára (uma exceção mencionada abaixo). Para fazer isso, você deve implementar todas essas funcionalidades sozinho.

Isso normalmente é feito por meio da definição de arquivos de unidade systemd personalizados . Portanto, você teria que criar esses arquivos de unidade para o docker-compose.

A única exceção é, uma maneira bastante hackeada, de executar userdata no início da instância descrita na postagem recente do blog da AWS:

  • Como posso utilizar os dados do usuário para executar um script automaticamente a cada reinicialização da minha instância do Amazon EC2?