In a serie of blog articles I’ll take a closer look at AWS CloudFormation. Read more about what AWS CloudFormation is and how to design templates in my previous blog articles AWS CloudFormation – Templates, stacks and change sets and AWS CloudFormation – Designing Templates.
In this blog article I’ll get more into detail about customizing the OS of your instance during the deployment of a template and how this is all managed by CloudFormation helper scripts.
Bootstrapping an EC2 instance with User data
The cloud-init package is an open-source application built by Canonical that is used to bootstrap Linux images in a cloud computing environment. EC2 instances contains a customized version of cloud-init. It enables you to specify actions that should happen to your instance at boot time. You can pass desired actions to cloud-init through the user data fields when launching an instance.
You can use AWS CloudFormation to automatically install, configure, and start applications on Amazon EC2 instances. Doing so enables you to easily duplicate deployments and update existing installations without connecting directly to the instance, which can save you a lot of time and effort. User Data is a property of the EC2 instance resource type.
EC2Instance: Type: AWS::EC2::Instance Properties: UserData: !Base64 | #!/bin/bash yum -y update ..
A basic bootstrap script runs only on the first boot of the instance and is specifically useful to make sure your freshly installed instance has the latest updates, required packages or configurations etc. The UserData properties needs to be Base64 encoded and starts with #! and the interpreter. It’s basically shell scripting with some limitations. It’s not interactive so there is no direct feedback. You can redirect your output to an file like this.
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
This line has to be at the top of your UserData section. This way you have your debug logging available on the instance you just deployed.
Another drawback of this approach is that the UserData section can become a little messy after a while. To solve this CloudFormation provides a meta data section where you can describe any implementation details regarding your resource. Additionally, Python based helper scripts helps you interact with CloudFormation and access the specific meta data of a resource declared in the template.
CloudFormation helper scripts
CloudFormation includes a set of helper scripts (cfn-init, cfn-signal, cfn-get-metadata, and cfn-hup) that are based on cloud-init. You call these helper scripts from your AWS CloudFormation templates to install, configure, and update applications on Amazon EC2 instances that are in the same template.
Reads and interprets Metadata to execute AWS::CloudFormation::Init. This script is called in your User Data section.
The cfn-signal helper script signals AWS CloudFormation to indicate whether Amazon EC2 instances have been successfully created or updated. If you install and configure software applications on instances, you can signal AWS CloudFormation when those software applications are ready.
Can be used to retrieve Metadata based on a specific key.
The cfn-hup helper is a daemon that detects changes in resource Metadata and runs user-specified actions when a change is detected. This allows you to make configuration updates on your running Amazon EC2 instances through the UpdateStack API action. We’ve already seen this helper script in action in Elastic beanstalk.
As already mentioned the User Data can become a bit messy. This can be solved by using metadata in the resource section where you already declared the EC2 instance. This will be explored in more depth next time. Read the next blog here.
Vincent Lamers, Linux-consultant @ AT Computing