All HowTo's Ansible & Terraform Automation Linux Redhat, Fedora and CentOS Linux

Build an EC2 using Ansible Step By Step

This article explains step by step how to create (spin up) an EC2 instance within AWS using Ansible and a few extras. Unlike 100% of other articles out there, this one actually demonstrates how to do it. Pay attention to the date of this article because things DO change over time.

We’re using CentOS 7 as the Ansible host.

Run the following commands to install the required dependencies for Ansible and AWS. I’m running this as a normal user with SUDO access, not the root user.

sudo pip install --upgrade pip
sudo pip install boto
sudo yum install ansible

Log into your AWS account to get your “AWS_ACCESS_KEY_ID” and “AWS_SECRET_ACCESS_KEY”. Go to “Identity and Access Management”. Create a new user or select an exiting one. Go to “Security Credentials” and click “Create Access Key”. Here’s an example of what you’ll end up with:

Access Key ID: NUHKOIJFOJF9GFJDO
Secret Access Key: LSDJKFODSJF9SDJF8UH3U3HFKW

Keep those safe – download when asked. Use the above values to create environment variables. Copy and paste the following (with your values replacing mine) into your shell:

export AWS_ACCESS_KEY_ID="NUHKOIJFOJF9GFJDO" 
export AWS_SECRET_ACCESS_KEY="LSDJKFODSJF9SDJF8UH3U3HFKW"

Create the “~/hosts” file with the following contents:

[local]
localhost

[webserver]

Now we build our YML file for Ansible to run through. Here’s a sample that will create a basic EC2 with a public IP address and your public SSH key. Put the following into the file “~/ec2-basic.yml”

---
  - name: Provision an EC2 Instance
    hosts: local
    connection: local
    gather_facts: False
    tags: provisioning
    # Necessary Variables for creating/provisioning the EC2 Instance
    vars:
      instance_type: t2.micro
      security_group: ansible-webserver # Change the security group name here
      image: ami-719fb712 # This is an AMI i created myself
      keypair: agix-key # This is one of my keys that i already have in AWS
      region: ap-southeast-2 # Change the Region
      count: 1

    # Task that will be used to Launch/Create an EC2 Instance
    tasks:

      - name: Create a security group
        local_action: 
          module: ec2_group
          name: "{{ security_group }}"
          description: Security Group for webserver Servers
          region: "{{ region }}"
          rules:
            - proto: tcp
              from_port: 22
              to_port: 22
              cidr_ip: 0.0.0.0/0
            - proto: tcp
              from_port: 80
              to_port: 80
              cidr_ip: 0.0.0.0/0
            - proto: tcp
              from_port: 443
              to_port: 443
              cidr_ip: 0.0.0.0/0
          rules_egress:
            - proto: all
              cidr_ip: 0.0.0.0/0
        register: basic_firewall

      - name: Launch the new EC2 Instance
        local_action: ec2 
                      group={{ security_group }} 
                      instance_type={{ instance_type}} 
                      image={{ image }} 
                      wait=true 
                      region={{ region }} 
                      keypair={{ keypair }}
                      count={{count}}
        register: ec2

      - name: Add the newly created EC2 instance(s) to the local host group (located inside the directory)
        local_action: lineinfile 
                      dest="./hosts" 
                      regexp={{ item.public_ip }} 
                      insertafter="[webserver]" line={{ item.public_ip }}
        with_items: ec2.instances


      - name: Wait for SSH to come up
        local_action: wait_for 
                      host={{ item.public_ip }} 
                      port=22 
                      state=started
        with_items: ec2.instances

      - name: Add tag to Instance(s)
        local_action: ec2_tag resource={{ item.id }} region={{ region }} state=present
        with_items: ec2.instances
        args:
          tags:
            Name: webserver

Being the provisioning (spin it up):

ansible-playbook -i ./hosts ec2-basic.yml

And finally log into your new ec2 instance:

ssh -l centos 54.1.2.3 -i Downloads/agix-key.pem

Resources:

https://pypi.python.org/pypi/boto#downloads
http://www.tivix.com/blog/using-ansible-create-aws-instances/
http://stackoverflow.com/questions/30227140/best-way-to-launch-aws-ec2-instances-with-ansible

15 comments

  1. Instance creation is done but after that it throws below error . Can you have a look and let me know the resolution.

    task path: /etc/ansible/ec2-basic.yaml:54
    fatal: [localhost]: FAILED! => {“msg”: “The task includes an option with an undefined variable. The error was: ‘ansible.utils.unsafe_proxy.AnsibleUnsafeText object’ has no attribute ‘public_ip’\n\nThe error appears to have been in ‘/etc/ansible/ec2-basic.yaml’: line 54, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n – name: Add the newly created EC2 instance(s) to the local host group (located inside the directory)\n ^ here\n\nexception type: \nexception: ‘ansible.utils.unsafe_proxy.AnsibleUnsafeText object’ has no attribute ‘public_ip'”}

  2. Got the issue …. Now it’s working fine.

    with_items: ec2.instances
    It should be:

    with_items: ‘{{ ec2.instances }}’

  3. Hi

    I am getting following message and EC2 is not getting launched.

    root@ip-172-31-39-198:/home/ubuntu# vim ~/hosts
    root@ip-172-31-39-198:/home/ubuntu# ansible-playbook -i ./hosts ec2-basic.yml
    [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [Provision an EC2 Instance] ***********************************************
    skipping: no hosts matched

    PLAY RECAP *********************************************************************

    root@ip-172-31-39-198:/home/ubuntu#

    I changed region, key details before running yml script

    [local]
    54.173.108.250

    [webserver]

    ~ ~ ~ ~ ~ ~ ~ ~ “~/hosts” 5L, 37C

    Can you please help

    1. Hi,

      It was my mistake . I had not changed your default parameters.

      It worked now. Thanks for the exact example and steps in detail

      Best regards

      1. Please kindly elaborate on the solution here as I get the same issue (named my file aws.yml).
        [root@localhost home]# ansible-playbook -i ./hosts aws.yml
        [WARNING]: Unable to parse /home/hosts as an inventory source

        [WARNING]: No inventory was parsed, only implicit localhost is available

        [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match ‘all’

        [WARNING]: Could not match supplied host pattern, ignoring: local

        PLAY [Provision an EC2 Instance] *******************************************************************************************************
        skipping: no hosts matched

        PLAY RECAP *******************************************************************************************************

  4. Hi Marudi,

    Make sure the “hosts” file exists in that location. It looks like you’re in “/home” (although that’s not clear) but you probably should be in “/home/myuser”.

    To check, try something like this:
    ansible-playbook -i ~/hosts aws.yml

    Notice the “~” indicating your home directory. It’s a guess but i think it’s what you want.

    Thanks.
    Andrew Galdes

  5. Hi All,

    I followed the exact steps but getting below exception

    An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NoCredentialsError: Unable to locate credentials
    fatal: [localhost -> localhost]: FAILED! => {“boto3_version”: “1.7.72”, “botocore_version”: “1.10.73”, “changed”: false, “msg”: “Error in describe_security_groups: Unable to locate credentials”}

  6. When i execute i am getting below error
    PLAY [Provision an EC2 Instance] ***************************************************************************************************************************************************************

    TASK [Create a security group] *****************************************************************************************************************************************************************
    An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NoCredentialsError: Unable to locate credentials
    fatal: [localhost -> localhost]: FAILED! => {“boto3_version”: “1.7.72”, “botocore_version”: “1.10.73”, “changed”: false, “msg”: “Error in describe_security_groups: Unable to locate credentials”}
    to retry, use: –limit @/root/ec2-basic.retry

    PLAY RECAP *************************************************************************************************************************************************************************************
    localhost : ok=0 changed=0 unreachable=0 failed=1

    1. I am able fix my issues and i am able to launch EC2 instances. When i tried to stop them they are not working.

      Issues are : make sure host files should be there

  7. PLAY [Provision an EC2 Instance] ***************************************************************************************************************************************************************************

    TASK [Create a security group] *****************************************************************************************************************************************************************************
    ok: [localhost -> localhost]

    TASK [Launch the new EC2 Instance] *************************************************************************************************************************************************************************
    fatal: [localhost -> localhost]: FAILED! => {“changed”: false, “msg”: “Instance creation failed => InvalidAMIID.NotFound: The image id ‘[ami-719fb712]’ does not exist”}
    to retry, use: –limit @/home/jagadish/ec2-basic.retry

    PLAY RECAP *************************************************************************************************************************************************************************************************
    localhost : ok=1 changed=0 unreachable=0 failed=1

    can anyone please help me with this error

  8. JAGADISH, change the ami ID for another one which is valid, I am using:

    image: ami-04681a1dbd79675a5

    hope this helps.

  9. Why do you know that IP is `54.1.2.3`? It is listed in the console, or you checked it on AWS website? Is any command to get this IP?

Leave a Reply

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