Automates creating custom AMIs using Ansible for provisioning.
- Create a temporary EC2 instance
- Upload and run a pre-provisioning script
- Run Ansible against the instance
- Create AMI
- Terminate instance
Each of these steps can be run individually to allow for debugging and fine-tuning your instance before creating the final AMI.
$ ami-creator help
NAME
ami-creator
DESCRIPTION
ami-creator is a command line tool to build custom AMIs using Ansible for provisioning.
OPTIONS
--version Display the version of this tool.
AVAILABLE COMMANDS
init Create a new project
create Create a custom AMI start to finish
pre-ansible Run a script on the instance before running Ansible
ansible Run Ansible on the instance
ssh SSH to the currently running instance
finalize Create AMI from currently running instance
terminate Terminate the currently running instance
list-amis List AMIs created on a per-session, per-project or global basis
list-instances List any instances that are running on a per-session, per-roject or global basis
Performing actions in your AWS account requires several resources to exist prior to creating custom AMIs. Specifically:
- AWS CLI profile
- EC2 SSH Key
- EC2 SSH File, e.g.
~/.ssh/ami-creator.pem
- EC2 Security Groups, e.g
sg-baf872c8
- EC2 Subnet, e.g
subnet-7a742b20
- EC2 IAM Instance Profile
You will be prompted for these values when creating a new project, so it is a good idea to set them up first.
You basically have three options for creating these resources:
-
Use existing resources.
-
Create new ones.
-
Use cloudformation.json to create a separate
ami-creator
stack for you.cloudformation.json has the added benefit of being completely separate from your existing resources. Don't like
ami-creator
? Just delete the stack, and there will be no traces of it in your AWS account.
Pre-requisites:
-
I suggest a creating separate profile reserved for
ami-creator
to use. The cloudformation.json will create a separate user with all the permissions you need. You'll need to manually create the access key andaws
profile for this user.Alternatively, you can attach the
ami-creator-user
policy created by cloudformation.json to an existing user or group.
# checkout the git repo
$ git clone git@github.com:crucialwebstudio/ami-creator.git
# symlink ami-creator.sh to somewhere on your $PATH
$ ln -s /path/to/ami-creator.sh /usr/local/bin/ami-creator
Now you can call ami-creator
from anywhere.
$ cd /path/to/ansible
$ mkdir ami-creator
Call ami-creator init
from within the ami-creator
directory.
$ cd /path/to/ansible/ami-creator
$ ami-creator init
This will prompt you for several project variables and save several files to a new project folder.
$ cd /path/to/ansible/ami-creator/name-of-project
$ ami-creator create
This should start a new 'session' and a custom AMI from start to finish. If any of the steps fail,
the instance will still be running so you can debug and tweak your instance. ami-creator
includes several commands
to help with debugging a 'session'.
$ ami-creator ssh
$ ami-creator pre-ansible
$ ami-creator ansible
$ ami-creator finalize
$ ami-creator terminate
Instances and AMIs are tagged so they are easily discoverable by ami-creator
. These commands will show you what
resources are associated with ami-creator
,
$ ami-creator list-instances
AMI creator prompts you to terminate the temporary instance after a new AMI is successfully created. If you
answered no or some other step of the process fails such that the instance is not terminated, this command will list
any instances that were created by ami-creator
.
You can manually terminate any running instances with
$ ami-creator terminate
$ ami-creator list-amis
AMIs are tagged so they are easily discoverable on a per-session, per-project, or global basis. This command will list them for you.
The ami-creator
folder lives inside your Ansible directory structure. AMI Creator
projects live in folders below that.
ami-creator/
project-name/
ansible.sh
inventory.ini
playbook.yml
pre-ansible.sh
project.cfg
session.lock
ssh.cfg
group_vars/
host_vars/
roles/
someproject.playbook.yml
-
ansible.sh
This is a wrapper around
ansible-playbook
.- Feel free to modify, but be careful to retain the existing parameters.
-
inventory.ini
This is an Ansible inventory file that represents the temporary EC2 instance.
- Feel free to modify, but be careful to retain the
ami-creator
hostname.
- Feel free to modify, but be careful to retain the
-
playbook.yml
This playbook is copied from your existing Ansible directory. The main difference is the
hosts
variable is set toami-creator
, e.g.hosts: ami-creator
, so that AMI Creator can run the playbook against the temporary EC2 instance.AMI Creator does not touch your existing playbooks. You can modify your current playbooks at-will and AMI Creator will copy the changes to this file.
- Do not modify
-
pre-ansible.sh
This script is copied to and executed on the temporary EC2 instance prior to running Ansible.
- Feel free to modify.
-
project.cfg
The contains project configuration variables set during
ami-creator init
- Feel free to modify values. Do not add or modify variable names.
-
session.lock
This holds variables saved during a session such as the Instance ID and the AMI ID.
- Do not modify.
-
ssh.cfg
This is an SSH config file to help with SSH-ing to the temporary EC2 instance.- Do not modify.
-
Why did you create this tool?
Creating custom AMIs is tedious. This started as an internal tool to help me automate the process and it currently "works for me". I'd love to have you try it out and let me know if you find it useful.
-
Why does the
ami-creator
folder have to exist within my Ansible folder?Technically, it doesn't, but this convention makes it easy for
ami-creator
to locate your playbooks, roles, etc. Additionally, your playbooks are (hopefully) already under source control. I believe if you are using a tool such asami-creator
to create custom AMIs, the files it uses and creates are important enough to have under source control as well. This enables code review, sharing with a team, etc. -
Pure Bash, eh?
This may get rewritten in Python at some point. For now it works pretty well and there are no dependencies.