Sunday 9 October 2016

Dynamic Inventory with Ansible

How to setup dynamic inventory with Ansible
Using dynamic inventory for Ansible


Video Tutorial

Initial Setup

Prerequisites:

  • Install and setup Ansible
  • Install boto (version>=2.24.0)
Get the ec2.ini and ec2.py file.

Make sure the ec2.py you are using should have --profile option . Use the latest ec2.py and boto with version>=2.24.0

Make the script executable by command chmod +x ec2.py



Configure the file ec2.ini file to work for particular region as shown below. this would decrease the execution time as the search for the resource would get limited to a particular region.


regions = us-east-1

Change ansible configuration file, ansible.cfg, to point to ec2.py as a host file


[defaults]
remote_user = root
host_key_checking = False
inventory = ./inventory/ec2.py


Now test the setup by running ./ec2.py --list. This should give the list of resources in the region we have se specified. If you get an error like below

region name: ap-south-1 likely not supported, or AWS is down.

Add the ap-south-1 region in the regions_exclude in ec2.ini file.


regions_exclude = us-gov-west-1,cn-north-1,ap-south-1

This will  remove the error and will list the resources as expected.

Writing  Playbook

First, define some default variable in a file all.yml in group_vars directory

mkdir group_vars
vi group_vars.all.yml

Add the following variables


---
# group_vars/all.yml
 
image: ami-7243e611
subnet: subnet-417fff25
region: ap-southeast-1
zone: ap-southeast-1a # zone that the master AMI will be configured in
keypair: mykey
security_groups: sample_subnet
instance_type: t2.micro

volumes:
  - device_name: /dev/xvda
    device_type: gp2
    volume_size: 8 # size of the root disk
    delete_on_termination: true

Let's create a role to launch an ec2 instance

mkdir -p roles/launch/tasks
vi roles/launch/tasks/main.yml


# roles/launch/tasks/main.yml

- name: Launch new instance
  ec2:
    region: "{{ region }}"
    vpc_subnet_id: "{{ subnet }}"
    keypair: "{{ keypair }}"
    zone: "{{ zone }}"
    group: "{{ security_groups }}"
    image: "{{ image }}"
    instance_type: "{{ instance_type }}"
    instance_tags:
      Name: "{{ name }}"
    volumes: "{{ volumes }}"
    wait: yes
    assign_public_ip: yes
  register: ec2
 
- name: Add new instances to host group
  add_host:
    name: "{{ item.public_dns_name }}"
    groups: "{{ name }}"
    ec2_id: "{{ item.id }}"
  with_items: "{{ ec2.instances }}"

- name: Wait for instance to boot
  wait_for:
    host: "{{ item.public_dns_name }}"
    port: 22
    delay: 30
    timeout: 300
    state: started
  with_items: "{{ ec2.instances }}"

vi launch_instance.yml


---
# launch_instance.yml
  - hosts: localhost
    connection: local
    gather_facts: no
    roles:
      - role: launch
        name: "{{ group_name }}-role-name"


Now simply run the playbook launch_instance.yml with the following command.


AWS_PROFILE=personal ansible-playbook -i hosts -e group_name=example launch_instance.yml -vvvv

This will launch the instance and you can also verify if the resources in the list of dynamic inventory got updated or not by running the following command

./ec2.py --list --profile personal --refresh-cache

3 comments:

  1. Hats off to you Sir , I was looking for this badly !!

    ReplyDelete
  2. hey where you get ~/.aws/credential file ?!!! please mail me on kiransoanawane.nmims@gmail.com.
    I'm not able to ssh by anyways.

    ReplyDelete
  3. Receiving following error, could you please help:
    fatal: [localhost]: FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'name' is undefined\n\nThe error appears to have been in '/etc/ansible/roles/launch/tasks/main.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Launch new instance\n ^ here\n"

    ReplyDelete

 

Copyright @ 2013 Appychip.

Designed by Appychip & YouTube Channel