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
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'”}
Got the issue …. Now it’s working fine.
with_items: ec2.instances
It should be:
with_items: ‘{{ ec2.instances }}’
Yes – that works NOW –
I appreciate the time you take to share this – very helpful. Thank you
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
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
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 *******************************************************************************************************
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
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”}
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
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
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
JAGADISH, change the ami ID for another one which is valid, I am using:
image: ami-04681a1dbd79675a5
hope this helps.
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?