AMI Backing: Using Ansible to Provision with Packer

Immutable Infrastructure in on the heart of DevOps. Today Backing is a very popular idea. AWS allow you to create AMI(AMI is amazon specific image is kinda of a ISO on the OS) this image can be backed in a automated fashion. To perform this task we can use Packer but Packer will take care on the AMI and publishing to AWS but you still need to install things on this linux image lets say Ubuntu or CentOS for instance. For provision you can use Ansible.

In this post i will show how to install Ansible, Packer and build an AMI image with Packer and have the full provisioning using Ansible. 



Installing Ansible on AWS

sudo su
yum update
yum install -y git
cd /usr/local/src
yum -y install git python-jinja2 python-paramiko PyYAML make MySQL-python
git clone git://github.com/ansible/ansible.git
cd ansible
git submodule update --init --recursive
make install
CTRL + D
sudo echo "[localhost]" > ~/ansible_hosts
sudo echo "localhost ansible_connection=local" >> ~/ansible_hosts
export ANSIBLE_INVENTORY=~/ansible_hosts
sudo vim /etc/ansible/hosts 
[127.0.0.1]
127.0.0.1 ansible_connection=local

[localhost]
127.0.0.1 ansible_connection=local
export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'

[test.yml]

---
- name: implicit localhost test...
  hosts: localhost
  tasks:
  - debug: msg="hello world" 
ansible-playbook test.yml
view raw ansible-aws.md hosted with ❤ by GitHub
Installing Packer

sudo yum update -y
sudo wget https://releases.hashicorp.com/packer/0.8.6/packer_0.8.6_linux_amd64.zip
sudo unzip packer_0.8.6_linux_amd64.zip
view raw packer.md hosted with ❤ by GitHub

Baking AMI with Packer and Provision with Ansible

So first you need define the packer configuration. You will need create a file, let's called config.json. In this file you will provide custom variable you want yo put on the backed image, whats is the target you are building, for this case will be AMI but you can use packer to build other things like Docker containers. For last you need have the provision configuration. This config will make Packer download and install Ansible and then provision with Ansible, as you can see I'm calling a ansible playbook called Apache.yml to install Apache inside this AMI.  You also need provide a base AMI ID, you can use any AMI ID i used a very basic one with just linux on it but you can use this to create more complex and layered solutions.

{
"variables":{
"hvm_amiid":"",
"region":"",
"application_name":"",
"application_version":""
},
"builders":[
{
"name":"hvm_builder",
"type": "amazon-chroot",
"access_key": "YOUR_KEY_HERE",
"secret_key": "YOUR_SECRET_HERE",
"ami_virtualization_type": "hvm",
"source_ami": "{{user `hvm_amiid`}}",
"ami_name": "{{user `application_name`|clean_ami_name}}-v{{user `application_version`|clean_ami_name}}-{{user `release`}}-b{{user `build`}}_Source-{{user `hvm_amiid`}}_Built-{{user `date`}}",
"region":"{{user `region`}}",
"tags": {
"Name":"{{user `application_name`}}-{{user `application_version`}}",
"virtualization_type":"hvm",
"application_version":"{{user `application_version`}}",
"application":"{{user `application_name`}}"
},
"ami_users":[
"369874303498"
]
}
],
"provisioners":[
{
"type":"shell",
"inline_shebang":"/bin/bash",
"inline":[
"sudo yum -y update",
"sudo yum -y install git python-jinja2 python-paramiko PyYAML make MySQL-python",
"sudo pip install ansible",
"sudo mkdir -p /tmp/packer-provisioner-ansible-local/roles",
"sudo chmod 777 /tmp/packer-provisioner-ansible-local/roles"
]
},
{
"type": "file",
"source":"./",
"destination": "/tmp/packer-provisioner-ansible-local"
},
{
"type":"shell",
"inline_shebang":"/bin/bash",
"inline":[
"/usr/local/src/ansible/bin/ansible-playbook /tmp/packer-provisioner-ansible-local/apache.yml"
]
}
]
}
view raw config.json hosted with ❤ by GitHub
Now let's check the Ansible Apache Playbook.

---
- hosts: localhost
become: root
tasks:
- name: install apache2
yum: name=httpd update_cache=yes state=latest
view raw apache.yml hosted with ❤ by GitHub
For last we need call Packer with all this configs, so did a simple bash script that will do the work, then you can just run $ sudo ./packer-build.sh and that's it. Have Fun. IF you do everything right you will get a AMI ID in the end of the build, then you can go to the AWS console and launch a EC2 instance based on this AMI ID and will work :-)
#!/bin/bash
PACKER_FILE=config.json
AMI_ID="ami-858694e4"
APPLICATION_NAME=apache
APPLICATION_VERSION=1.0
ANSIBLE_PLAYBOOKS_PATH="$(pwd)"
REGION=us-west-2
sudo PACKER_LOG=INFO ./packer build -debug \
-machine-readable \
-var hvm_amiid=$AMI_ID \
-var application_name=$APPLICATION_NAME \
-var application_version=$APPLICATION_VERSION \
-var region=$REGION \
-var ansible_playbooks_path=$ANSIBLE_PLAYBOOKS_PATH \
$PACKER_FILE \
view raw packer-build.sh hosted with ❤ by GitHub
Cheers,
Diego Pacheco

Popular posts from this blog

Having fun with Zig Language

C Unit Testing with Check

Cool Retro Terminal