User data is an initialization script supplied to an EC2 instance and executed during startup. On Amazon Linux 2, cloud-init runs it while the instance boots, making it useful for first-boot configuration. section 5.2
Common startup tasks include:
- Installing all available packages with `yum -y update`, or installing only security updates with `yum -y --security update`. section 5.2
- Installing dependencies, fetching application source, creating configuration, and starting an application. section 15.2
- Reading `/var/log/cloud-init-output.log` when diagnosing startup-script behavior. section 15.2
CloudFormation places the script in an EC2 launch template under `UserData`, commonly Base64-encodes it, and can substitute stack values. A script can signal success or failure to CloudFormation after provisioning. section 15.2
Rolling deployment
A CloudFormation update changes a launch template. An Auto Scaling group starts a new instance, which fetches and executes the user data script, configures Etherpad, and starts it; the old instance is then terminated. This supports rolling updates without downtime when instances are disposable and application data is not stored locally. section 15.2
Listing 15.4 Adding a bash script to the user data
# [...] LaunchTemplate: #1 Type: 'AWS::EC2::LaunchTemplate' Properties: LaunchTemplateData: # [...] ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI] #2 InstanceType: 't2.micro' #3 UserData: #4 'Fn::Base64': !Sub | #!/bin/bash -ex #5 trap '/opt/aws/bin/cfn-signal -e 1 --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region}' ERR #6 # Install nodejs and git curl -fsSL https:/ /rpm.nodesource.com/setup_14.x | bash - yum install -y nodejs git # Fetch, configure, and start Etherpad as non-root user su ec2-user -c ' cd /home/ec2-user/ git clone --depth 1 --branch ${EtherpadVersion} https:/ /github.com/AWSinAction/etherpad-lite.git #7 cd etherpad-lite/ echo " { \"title\": \"Etherpad\", \"dbType\": \"mysql\", \"dbSettings\": { \"host\": \"${Database.Endpoint.Address}\", \"port\": \"3306\", \"database\": \"etherpad\", \"user\": \"etherpad\", \"password\": \"etherpad\" }, \"exposeVersion\": true } " > settings.json #8 ./src/bin/run.sh &' #9 /opt/aws/bin/cfn-signal -e 0 --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region} #10 # [...] #1 The Auto Scaling group uses the launch template as a blueprint when launching EC2 instances. #2 Picks the Amazon Linux 2 AMI dependent on the current region #3 Selects the instance type applicable for the Free Tier #4 Here is where the magic happens: the user data defined here is accessible by the EC2 instance during runtime. #5 The operating system will execute this bash script at the end of the boot process. #6 If any step fails, the script will abort and notify CloudFormation by calling cfn-signal. #7 Fetches Etherpad from the GitHub repository #8 Creates a settings file for Etherpad containing the database host name #9 Starts Etherpad #10 Notifies CloudFormation about a successful deployment
Shows a CloudFormation launch template embedding a Bash deployment script in EC2 user data. section 15.2
Instance:
Type: 'AWS::EC2::Instance'
Properties:
# [...]
UserData: !Base64 |
#!/bin/bash -ex
yum -y update #1
Shows the minimal CloudFormation form for running a complete package update during instance startup. section 5.2
Startup patching is not a complete maintenance strategy: some updates require a reboot, and newly running instances will not receive later updates. AWS Systems Manager Patch Manager provides scheduled, continuous patching capabilities instead. section 5.2
