CommsCentral

My Technology Adventures

AWS CloudFormation helper scripts on Ubuntu - aws-cfn-bootstrap

Posted at: 2015-07-01 @ 15:45:42

AWS CloudFormation provides a set of Python helper scripts that you can use to install software and start services on an Amazon EC2 instance that you create as part of your stack.
If you'd used CloudFormation at all you'll probably have used this already.

The services contained within the bundle are used to deploy software, files and also runs a service that monitors for updates to the stack and determines if any action is required.

If deploying an Amazon Linux AMI this will already be installed and you'd kick this off with a fairly standard UserData script pushed to the instance via cloudformation as per below.

"UserData": {
"Fn::Base64": {
"Fn::Join": ["", [
"#!/bin/bash -xe\n",
"yum update -y aws-cfn-bootstrap\n",

"/opt/aws/bin/cfn-init -v ",
" --stack ", {
"Ref": "AWS::StackName"
},
" --resource Server ",
" --configsets install_init ",
" --region ", {
"Ref": "AWS::Region"
}, "\n",

"/opt/aws/bin/cfn-signal -e $? ",
" --stack ", {
"Ref": "AWS::StackName"
},
" --resource Server ",
" --region ", {
"Ref": "AWS::Region"
}, "\n"
]]
}
}
You'll find example like this in all the AWS supplied cloudformation templates which makes life simple.

However what if your using Ubuntu you'll find that there is no such package by the name of aws-cfn-bootstrap.
So here is the UserData code that we need use instead for Ubuntu
"UserData": {
"Fn::Base64": {
"Fn::Join": ["", [
"#!/bin/bash -xe\n",
"apt-get update\n",
"apt-get -y install python-pip\n",
"pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
"cp /usr/local/init/ubuntu/cfn-hup /etc/init.d/cfn-hup \n",
"chmod +x /etc/init.d/cfn-hup \n",
"update-rc.d cfn-hup defaults \n ",
"service cfn-hup start \n",


"cfn-init -v ",
" --stack ", {
"Ref": "AWS::StackName"
},
" --resource Server ",
" --configsets install_init ",
" --region ", {
"Ref": "AWS::Region"
}, "\n",

"cfn-signal -e $? ",
" --stack ", {
"Ref": "AWS::StackName"
},
" --resource Server ",
" --region ", {
"Ref": "AWS::Region"
}, "\n"
]]
}
}
Whats this all doing?

Firstly we do a standard apt-get update to make sure we get all the newest information for available packages.

Then we run apt-get -y install python-pip, which installs python-pip and says yes to the confirmation prompt. Python-pip is a package manager/installer for python
tools.
Next we copy over the cfn-hup service init.d file and update the permissions to allow execution. This effectively creates the linux service for the cfn-hup deamon.
We update all the runlevel configuration with update-rc.d to ensure our service will run correctly are all the various linux runlevels
Lastly we start the cfn-hup service.


There are otherways to do this which are shorter, however they have some catches.
For example instead of python-pip you can use easy_install and I've seen a few examples for that.
When you use the easy_install you don't seem get a full install or the init.d files in /usr/local/init/

This means you create the cfn-hup service which means stack updates won't update the instance on a stack update https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-hup.html.

Using the AWS sample template at https://s3-us-west-2.amazonaws.com/cloudformation-templates-us-west-2/VPC_AutoScaling_and_ElasticLoadBalancer.template

you can see they have two sections which specifically setup cfn-auto-relader and cfn-hup configurations. If you have these in your template, or want to use them. You need to install the aws-cfn-bootstrap service as was specified above! Otherwise you'll have problems!

"files" :{
"/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
"content": { "Fn::Join" : ["", [
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -v ",
" --stack ", { "Ref" : "AWS::StackName" },
" --resource LaunchConfig ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"runas=root\n"
]]}
}
},

"services" : {
"sysvinit" : {
"httpd" : { "enabled" : "true", "ensureRunning" : "true" },
"cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
"files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
}
}


I hope this helps someone else out who has the same issue. I found resources on the internet very limited and lacking detail for this item specifically. Hence the post!

Enjoy!




© 2015 CommsCentral