Infrastructure as Code is getting all attention it deserves and everyone is trying to find their way to the `Completely automated Infrastructure Provisioning & Management`
While there are a lot of tools available now in the market starting from Terraform, AWS CloudFormation, Chef, Puppet, Salt Stack
There are some differences between each tool. Some of them are configuration management tools (Ansible, Chef, Saltstack) and Some of them are purely provisioning tools (terraform, cloud formation). You have to choose your judgement based on various factors like Easy to learn, easy to adopt.
Though Terraform is a wonderful cross-platform provisioning tool I feel it has a steep learning curve. while Ansible is not that complex to start with an easy to learn and adopt.
So this post is for those ( including me ) who love ansible's simplicity and structure and want to see how it works with AWS.
This is going to be a quick introduction to Ansible AWS Ec2 module.
How Ansible works with AWS EC2 - Setup Boto for Ansible
Ansible AWS combo is more like Hobbs and Shah ( Sorry! I am Fast & Furious Fan) while both of em have their own individual stardom they join together to create magic.
Stupid analogy right.!!!
Jokes Apart, But Ansible is a leader in configuration management tools and AWS is a leader in Cloud solutions and no doubt that they give best results as combined for the Infrastructure automation and management.
In Ansible Parlance, Everything is a module and Yes ansible provides ample amount of modules to work with AWS resource. As I am typing this post, Ansible has 194 officially listed modules for aws. here is a list
All these modules are helping us to accomplish a various level of tasks in AWS cloud resources creation, deletion, management, assessment etc
Our objective is precise, we want to create an EC2 Instance using Ansible and Ansible has a module for that named ec2
Before we jump right into the playbooks and stuff. we need to do some environment setup.
Environment Setup for Ansible to work with AWS EC2 module
As we all know Ansible is pythonic and their modules are written in python as well. So for AWS modules to work you need to have Certain prerequisite elements installed on your Ansible Control machine ( where you have installed ansible )
- boto
- boto3
- botocore
- python version >= 2.6
You can install python easily but what is this boto. boto is one of the Amazon supported SDK. Boto3 is the latest version of boto.
to make sure you have boto installed in your python. Just Launch your Python interactive terminal and type import boto
and import boto3
if it works fine ( shows no error) you are good.
to install boto and boto3 you must have pip3
as well. If you are having python 2.7
there are chances you might have this bundled in.
Some times when you have two versions of python installed in your system you have to try them out both and make sure which one has the boto installed. by performing the `import boto` command so that you can avoid some exceptions like this
If you take my MAC, for example, I have two python version installed, One is at /usr/local/bin/python
another one is at /usr/bin/python
One comes as built-in with OS another one is installed by `homebrew` , I had to lauch them both and check the if the boto package is present in there like shown below.
You could see that my /usr/local/bin/python3
all necessary modules installed,
Note:
It is known that Python3 may not work properly with Ansible old versions. In that case, you can choose to install your boto libraries in
python 2.7.*
version and it use it as your primary version inansible_python_interpreter
This is just a method to find the right python package to use it with ansible
The path and everything could be different for you. Before executing these commands, update the paths based on your local installation.
Now I presume that you have a python with these necessary modules installed.
Ansible Playbook to create a new EC2 instance
Here is the playbook to create EC2 instances and also to get the list of in your AWS Cloud account.
We have used two blocks here (a block is just a group of tasks )
- The first block is to just get the instances information
- The second block is to create the instance
For security reasons, we made the Second block to run only when it is being explicitly called with --tags
this has been done by using the tag never
in the block
--- - name: Create Ec2 instances hosts: localhost gather_facts: false tasks: # Block is a Group of Tasks combined together - name: Get Info Block block: - name: Get Running instance Info ec2_instance_info: register: ec2info - name: Print info debug: var="ec2info.instances" # By specifying always on the tag, # I let this block to run all the time by module_default # this is for security to net create ec2 instances accidentally tags: ['always', 'getinfoonly'] - name: Create EC2 Block block: - name: Launch ec2 instances tags: create_ec2 ec2: region: us-east-1 key_name: SaravAK-PrivateKey group: app_sec_group instance_type: t2.medium image: ami-2051294a wait: yes wait_timeout: 500 count: 2 instance_tags: name: appservers os: ubuntu monitoring: no vpc_subnet_id: subnet-3d3ef270 assign_public_ip: yes register: ec2 delegate_to: localhost - name : Add instance to host group add_host: hostname: "{{ item.public_ip }}" groupname: launched loop: "{{ ec2.instances }}" - name: Wait for SSH to come up local_action: module: wait_for host: "{{ item.public_ip }}" port: 22 delay: 10 timeout: 120 loop: "{{ ec2.instances }}" # By specifying never on the tag of this block, # I let this block to run only when explicitely being called tags: ['never', 'ec2-create']
You might wonder where is my AWS Key and SECRET mentioned. How would I be able to login to my AWS account? How the authentication will be done.
I hear ya.
Setup AWS Authentication Before Running the Playbook with Ansible EC2
To make this article precise, I just assume that you know how to create programmatic access for your AWS account and get your AWS_ACCESS_KEY
and AWS_SECRET
Once you have the keys, the easiest but an unsecured way is to save it as Environment Variables like this and we are all set.
Getting ready to execute the playbook - Ansible AWS EC2
Before executing the playbook you must be sure which python interpreter you are going to use which has `boto` libraries installed.
When it comes to using EC2 modules, It is always better to tell ansible explicitly which python interpreter it has to use.
In my case, as I have said before my /usr/local/bin/python3
has the necessary boto libraries and I have to tell ansible to use that python.
to do that, I can use ansible.cfg
file or ansible inventory file
but I prefer to do it in a command line as a runtime variable
Here is the command I supposed to use
ansible-playbook ec2-creation.yml \ --connection=local \ -e "ansible_python_interpreter=/usr/local/bin/python3"
Here
--connection tells Ansible to run this task locally and not look for any remote server or hosts file
--e extra args or variables where we gave the python interpreter by setting the python full location to ansible_python_interpreter
variable
when I run this, I would get only the info of existing instances. it would not create the instances yet. as we have the info as the default block
Now to create the ec2 instance or to run that block, I need to call the tag of that block using --tags
like shown below.
ansible-playbook ec2-creation.yml \ --connection=local \ --tags=ec2-create \ -e "ansible_python_interpreter=/usr/local/bin/python3"
Execution Part - Run the playbook with Ansible EC2
Here is the execution and the result of this playbook.
A Playbook with Ansible EC2 & Ansible Vault - Secure Approach
to use the Ansible vault to securely store your AWS Keys, You might need one more file on the same directory where you can save your credentials as variables and encrypt it with the vault.
The file can be imported later within the playbook.
Here is the modified playbook with a secure approach, Ansible Vault
--- - name: Create Ec2 instances hosts: localhost # import the secret file vars_files: - secrets.yml gather_facts: false tasks: # Block is a Group of Tasks combined together - name: Get Info Block block: - name: Get Running instance Info ec2_instance_info: register: ec2info - name: Print info debug: var="ec2info.instances" # By specifying always on the tag, # I let this block to run all the time by module_default # this is for security to net create ec2 instances accidentally tags: ['always', 'getinfoonly'] - name: Create EC2 Block block: - name: Launch ec2 instances tags: create_ec2 ec2: region: us-east-1 key_name: SaravAK-PrivateKey group: app_sec_group instance_type: t2.medium image: ami-2051294a wait: yes wait_timeout: 500 count: 2 instance_tags: name: appservers os: ubuntu monitoring: no vpc_subnet_id: subnet-3d3ef270 assign_public_ip: yes register: ec2 delegate_to: localhost - name : Add instance to host group add_host: hostname: "{{ item.public_ip }}" groupname: launched loop: "{{ ec2.instances }}" - name: Wait for SSH to come up local_action: module: wait_for host: "{{ item.public_ip }}" port: 22 delay: 10 timeout: 120 loop: "{{ ec2.instances }}" # By specifying never on the tag of this block, # I let this block to run only when explicitely being called tags: ['never', 'ec2-create']
Saving the AWS Secrets
As we have included the secrets.yml
file inside our playbook, Now we need to save our AWS KEY
and SECRET
This is the content of the secret.yml
file
➜ cat secrets.yml AWS_ACCESS_KEY_ID: AKIATQ7Q7SGKYB4TT3DX AWS_SECRET_ACCESS_KEY: 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
It is saved as clear text info within the file so whoever opens it can see what is inside.
So Encrypt it
➜ ansible-vault encrypt secrets.yml New Vault password: Confirm New Vault password: Encryption successful
Now you have to remember this password and use it while you are starting the playbook.
For Ansible to ask you the password you should use a startup argument named --ask-vault-pass
ansible-playbook ec2-creation.yml \ --connection=local \ --tags=ec2-create \ -e "ansible_python_interpreter=/usr/local/bin/python3" \ --ask-vault-pass
It would prompt you for the password as it runs.
See the following Screen record if you want to see how it works in realtime.
Execution of Ansible AWS Playbook example
I know this is just a first step, Now you have got better things to do with that newly created server and install and configure it. you might have further questions on how to use these servers and configure them properly on the same playbook.
Please stay connected and Lookup for my next article. I am already drafting it.
hope this helps.
Rate this article [ratings] if you would like to
Cheers
Sarav AK
Follow me on Linkedin My Profile Follow DevopsJunction onFacebook orTwitter For more practical videos and tutorials. Subscribe to our channel
Signup for Exclusive "Subscriber-only" Content