How to run ec2 UserData script on cloudformation update

2.7k views Asked by At

I have ec2 userData script that doing docker-compose pull and up.

I want to run "aws cloudformation update-stack" and load new docker images. Each time ${imageTag} property changes.

This is my cloudformation instance 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}

I tried to add "docker-compose down", remove old images in the UserData script, and add cloud_final_modules to run UserData each startup:

 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}

But after "aws cloudformation update-stack" the script does not run again dispite the imageTag changed. it runs only if I change some value under runcmd.

How can I run the UserData script each time "aws cloudformation update-stack" running (each time imageTag changes)?

How can I run some UserData commands only on first startup, other commands on each reboot and other commands on stop instance?

for example: I want to run "docker-compose down" only on instance stop but other commands command: 'docker-compose pull/up' on each instance reboot or "aws cloudformation update-stack" and some initial commands only on first setup.

1

There are 1 answers

0
Marcin On BEST ANSWER

How can I run some UserData commands only on first startup, other commands on each reboot and other commands on stop instance?

You can't. UserData is meant to run only at instance launch, not reboots, starts or stops (one exception mentioned below). In order to do so, you have to implement all this functionality yourself.

This is commonly done though definition of custom systemd unit files. Thus you would have to create such unit files for your docker-compose.

The only exception is, a rather hackish way, of running userdata at instance start described in recent AWS blog post: