Launching and Configuring an AWS EC2 instance using Ansible

29 / Jul / 2016 by Mohit Dayal Gupta 5 comments

Ansible is a configuration management tool which configures and manages systems for multi-node software deployment. It is an orchestration tool which prevents an agent from running continuously on a server to fetch the desired configurations. Unlike Chef and Puppet, it uses a push mechanism to push the desired changes on the servers using ssh-agent.

Here in this blog, we will learn how to launch an AWS EC2 instance using ansible. We will write an Ansible playbook to launch the instance. The playbooks are written in “.yml” format.

Ansible EC2

First of all, we will discuss the basic requirements that need to be initialized to launch an EC2 instance. We will need the following details:

  • region => The region in which the instance needs to be launched.
  • security group => The security group to be associated with the instance.
  • image-id => The AMI id by which the instance is to be launched.
  • instance-type => The type of the instance.
  • key-pair => The Pem file to authenticate the login process.
  • count => The number of instances to be launched.
  • Role => The IAM role to be associated with the EC2 instance.
  • volume-size => The size of the EBS volumes to be attached.

After setting the variables we are good to go. The given below are the tasks of the ansible playbook which we are going to create:

1. Launching an EC2 instance

Ansible uses its ec2 module to launch the instance. The following is the task:

[js]
– name: Launching an EC2 Instance
local_action: ec2
instance_type={{ instance_type}}
image={{ ami }}
region={{ region }}
keypair={{ pem }}
count={{count}}
instance_profile_name={{ instance_profile_name }}
group={{ security_group }}
wait=true
volumes={{volumes}}
register: ec2
[/js]

The value of the variables will be passed when executing the playbook. The “{{ }}” is being used to evaluate the value of the variable. The statement wait=true” is used to let ansible wait for the instance to come. The statement “register: ec2” register the output in ec2 variable so that we can run the query to find out different properties of the instance.

2. Allocating Elastic IP to EC2 instance

[js]
– name: Associating after allocating elastic IP
eip:
in_vpc: yes
reuse_existing_ip_allowed: yes
state: present
region: "{{ region }}"
device_id: "{{ ec2.instance_id[0] }}"
register: elastic_ip

[/js]

This task is used to allocate Elastic IP to the instance. Here, the elastic IP is associated with the instance and set in the variable “elastic_ip”.

3. Waiting for the instance to come

[js]
– name: Waiting for the instance to come
local_action: wait_for
host={{ item.private_ip }}
state=started
port=22
with_items: ec2.instances
[/js]

This playbook task is used to wait for the instance to come. The instance check is done until the instance comes in the available state. Here “with_items: ec2.instances” is used to create a loop. The ansible waits for the instance to come and become available by looping at port 22.

4. Adding tags to the EC2 instance

[js]
– name: Adding tags to the EC2 Instance"
local_action: ec2_tag
region={{ region }}
resource={{ item.id }}
state=present
with_items: ec2.instances
args:
tags:
Name: "{{ name }}"
Env: "{{ Env }}"
Type: microservice
register: tag
[/js]

This task is used to add tags to the instances. The local action ec2_tag is used. The item ec2.instances is used to pick out instance id and region. The tags are added as Name: “{{ name }}”, where the value of the name will be passed from outside. The tags added will be initialized to by using “register: tag”.

By using these above tasks in the  ansible playbook the instance will be created and configured. Make sure the host from which you are running the playbook must have enough permissions to launch the EC2 instance.

The complete ansible playbook to launch instance using above tasks is as follows:

[js]


– name: Configuring the EC2 Instance
hosts: localhost
connection: local
vars:
count: {{ count }}
volumes:
– device_name: /dev/sda1
volume_size: {{ volume-size }}

– name: Launching an EC2 Instance
local_action: ec2
instance_type={{ instance_type}}
image={{ ami }}
region={{ region }}
keypair={{ pem }}
count={{count}}
instance_profile_name={{ instance_profile_name }}
group={{ security_group }}
wait=true
volumes={{volumes}}
register: ec2

– name: Associating after allocating elastic IP
eip:
in_vpc: yes
reuse_existing_ip_allowed: yes
state: present
region: "{{ region }}"
device_id: "{{ ec2.instance_id[0] }}"
register: elastic_ip

– name: Waiting for the instance to come
local_action: wait_for
host={{ item.private_ip }}
state=started
port=22
with_items: ec2.instance

– name: Adding tags to the EC2 Instance"
local_action: ec2_tag
region={{ region }}
resource={{ item.id }}
state=present
with_items: ec2.instances
args:
tags:
Name: "{{ name }}"
Env: "{{ Env }}"
Type: microservice
register: tag

[/js]

The playbook has been created. Now, for example, the playbook should be run as:

ansible-playbook playbook_name.yml –extra-vars volume-size=10 -e instance_type=t2.micro -e region=us=east-1 -e keypair=sample.pem -e count=1 

The EC2 instance is now created. I will write more blogs on configuring AWS services using Ansible.

FOUND THIS USEFUL? SHARE IT

comments (5)

  1. Ishanya


    – name: Configuring the EC2 Instance
    hosts: localhost
    connection: local
    vars:
    count: “{{count}}”
    volumes:
    – device_name: /dev/sda1
    volume_size: “{{volume-size}}”

    – name: Launching an EC2 Instance
    local_action: ec2
    instance_type: “{{ instance_type}}”
    image: “{{ami}}”
    region: “{{region}}”
    keypair: “{{pem}}”
    group_id: “{{security_group}}”
    wait: true
    register: ec2

    – name: Waiting for the instance to come
    local_action: wait_for
    host={{ item.private_ip }}
    state=started
    port=22
    with_items: ec2.instance

    – name: Adding tags to the EC2 Instance
    local_action: ec2_tag
    region={{ region }}
    resource={{ item.id }}
    state=present
    with_items: ec2.instances
    args:
    tags:
    Name: “{{name}}”
    Env: “{{Env}}”
    register: tag

    Above is my yml content and the error I am getting is as below

    ERROR! ‘image’ is not a valid attribute for a Play

    The error appears to have been in ‘/…./ec2.yml’: line 11, column 3, but may
    be elsewhere in the file depending on the exact syntax problem.

    The offending line appears to be:

    – name: Launching an EC2 Instance
    ^ here

    Command Used for executing the playbook

    ansible-playbook ec2.yml –extra-vars volume-size=1 -e instance_type=t2.micro -e region=us-east-2 -e keypair=ec2launchkey.pem -e count=1 -e ami=ami-916f59f4 -e pem=ec2launchkey.pem -e security_group=sg-4a477f21

    1. Firstly it forced me to put double quotes and removing the space from all like {{ instance_type }} to “{{ instance_type}}”
    2. Always getting
    ERROR! ‘image’ is not a valid attribute for a Play for all the attributes like for group and count so i removed them but ami is the required thing

    Please suggest.

    Reply
  2. Abhishek Somani

    what should be the value of volumes variable and where should be the pem file to be kept for use?

    Reply
  3. shivaji

    This is playbook i want to run
    – name: Launching an EC2 Instance
    local_action: ec2
    instance_type: t2.micro
    image: ami-a861ea98
    region: us-west
    keypair: EC2-Test
    count: 1
    group: wideopen
    wait: true
    register: ec2

    Reply
  4. shivaji

    when i try your playbook but instead of variables here i hot code the play book like this
    – name: Launching an EC2 Instance
    local_action: ec2
    instance_type: t2.micro
    image: ami-a861ea98
    region: us-west
    keypair: EC2-Test.pem
    count: 1
    group: wideopen
    wait=true
    register: ec2
    when i run playbook shows the following error

    ERROR! Syntax Error while loading YAML.
    The error appears to have been in ‘/etc/ansible/ec2.yml’: line 3, column 20, but may
    be elsewhere in the file depending on the exact syntax problem.

    The offending line appears to be:

    local_action: ec2
    instance_type: t2.micro
    ^ here

    Reply
    1. Mohit Dayal Gupta

      Hello Shivaji,

      You should pass the instance_type as parameters and then call like this:
      – name: Launching an EC2 Instance
      local_action: ec2
      instance_type={{ instance_type}}

      Or, you can also set them in variables and then use this syntax.

      Reply

Leave a Reply to Ishanya Cancel reply

Your email address will not be published. Required fields are marked *