In this article, let’s see how we can create EC2 instance using the Ansible Playbook.
Table of Contents
Prerequisite
Let’s start with setting up a virtual environment for Ansible. So we do not disturb our existing environment.
Create a virtual environment named aws
with the following command.
python3 -m venv aws
activate the virtual environment by running below command
source aws/bin/activate
Upgrade pip and install ansible and boto, boto3 library
pip install --upgrade pip
pip install boto boto3 ansible
Install amazon.aws collection
ansible-galaxy collection install amazon.aws
Setting up AWS Credentials
We will need to create a user in IAM and then generate a key/token for the user. We will need to set these two environment variables on the controller node.
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
Please set up this from aws console.
Creating EC2 Instance using Ansible Playbook
We will be creating three roles. I am assuming this folder structure in this example.
Ansible Role for Generating authentication key for EC2
File Name: aws_ec2_demo/create_ec2_key/tasks/main.yml
- name: create a new EC2 key pair, returns generated private key
amazon.aws.ec2_key:
region: "{{ region }}"
name: "{{ key_name }}"
key_type: rsa
file_name: "{{ key_file_name }}"
register: aws_ec2_key_pair
Explanation
- name: create a new EC2 key pair, returns generated private key
This line is a comment indicating the purpose of the task. It’s a descriptive name for the task.
amazon.aws.ec2_key:
region: "{{ region }}"
name: "{{ key_name }}"
key_type: rsa
file_name: "{{ key_file_name }}"
This is the task itself, using the amazon.aws.ec2_key
Ansible module. It’s responsible for creating a new EC2 key pair. Here’s what each parameter means:
region
: Specifies the AWS region where the key pair will be created. It’s typically defined elsewhere in the playbook as a variable ({{ region }}
).name
: Specifies the name for the new key pair. It’s typically defined elsewhere in the playbook as a variable ({{ key_name }}
).key_type
: Specifies the type of key to be generated. In this case, it’s set torsa
, indicating that an RSA key pair will be generated.file_name
: Specifies the name of the file to which the private key will be saved. It’s typically defined elsewhere in the playbook as a variable ({{ key_file_name }}
).
register: aws_ec2_key_pair
This line registers the output of the task to a variable named aws_ec2_key_pair
. This allows you to access the output of this task later in the playbook, such as printing it or using it in subsequent tasks.
Ansible Role for Creating EC2 Instance
File Name: aws_ec2_demo/create_ec2/tasks/main.yml
- name: start an instance with a public IP address
amazon.aws.ec2_instance:
region: "{{ region }}"
name: "public-compute-instance"
key_name: "{{ key_name }}"
instance_type: t2.micro
security_group: sg-0e894f1e765cb75a9
image_id: "{{ image_id }}"
state: running
network:
assign_public_ip: true
tags:
Environment: Testing
wait: true
register: ec2_result
- name: show private ip address of ec2
debug:
msg: "{{ ec2_result.instances[0].private_ip_address}}"
- name: set ec2 private ip address in a fact
set_fact:
ec2_private_ip_address: "{{ ec2_result.instances[0].private_ip_address}}"
ec2_public_ip_address: "{{ ec2_result.instances[0].public_ip_address}}"
- name: Add a host alias that we reach through a tunnel (Ansible 1.9 and older)
ansible.builtin.add_host:
hostname: '{{ ec2_public_ip_address }}'
ansible_user: ec2-user
ansible_ssh_private_key_file: "{{ key_file_name }}"
Explanation:
- name: start an instance with a public IP address
amazon.aws.ec2_instance:
region: "{{ region }}"
name: "public-compute-instance"
key_name: "{{ key_name }}"
instance_type: t2.micro
security_group: sg-0e894f1e765cb75a9
image_id: "{{ image_id }}"
state: running
network:
assign_public_ip: true
tags:
Environment: Testing
wait: true
register: ec2_result
This task starts an EC2 instance with the following specifications:
region
: Specifies the AWS region where the instance will be launched. It’s typically defined elsewhere in the playbook as a variable ({{ region }}
).name
: Specifies the name tag for the new instance.key_name
: Specifies the name of the key pair to be used for SSH access to the instance.instance_type
: Specifies the instance type, in this case,t2.micro
.security_group
: Specifies the security group to associate with the instance.image_id
: Specifies the ID of the Amazon Machine Image (AMI) to use for launching the instance. It’s typically defined elsewhere in the playbook as a variable ({{ image_id }}
).state
: Specifies the desired state of the instance, in this case,running
.network.assign_public_ip
: Specifies whether to assign a public IP address to the instance. In this case, it’s set totrue
.tags
: Specifies tags to be applied to the instance, in this case, setting theEnvironment
tag toTesting
.wait
: Specifies whether Ansible should wait for the instance to reach the desired state before proceeding. In this case, it’s set totrue
.register: ec2_result
: Registers the output of the task to a variable namedec2_result
, which can be used later in the playbook.
The subsequent tasks:
- name: show private ip address of ec2
debug:
msg: "{{ ec2_result.instances[0].private_ip_address}}"
This task prints the private IP address of the launched EC2 instance.
- name: set ec2 private ip address in a fact
set_fact:
ec2_private_ip_address: "{{ ec2_result.instances[0].private_ip_address}}"
ec2_public_ip_address: "{{ ec2_result.instances[0].public_ip_address}}"
This task sets facts ec2_private_ip_address
and ec2_public_ip_address
with the private and public IP addresses of the launched EC2 instance, respectively.
- name: Add a host alias that we reach through a tunnel (Ansible 1.9 and older)
ansible.builtin.add_host:
hostname: '{{ ec2_public_ip_address }}'
ansible_user: ec2-user
ansible_ssh_private_key_file: "{{ key_file_name }}"
This task adds the EC2 instance as a host alias in Ansible’s in-memory inventory. It sets the public IP address as the hostname, specifies the SSH user as ec2-user
, and provides the path to the SSH private key file using the variable {{ key_file_name }}
. This allows subsequent tasks in the playbook to target this EC2 instance.
Creating main playbook
File Name: aws_ec2_demo/create_ec2.yml
---
- name: create EC2 instance
hosts: localhost
connection: local
gather_facts: false
environment:
AWS_ACCESS_KEY_ID: "{{ AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "{{ AWS_SECRET_ACCESS_KEY }}"
ANSIBLE_HOST_KEY_CHECKING: false
vars:
region: us-east-1
image_id: ami-05c13eab67c5d8861
key_name: "my_keypair_1"
key_file_name: /tmp/aws_ssh_rsa
roles:
- create_ec2_key
- create_ec2
- name: ping EC2
hosts: "{{ hostvars['localhost']['ec2_public_ip_address'] }}"
roles:
- ping_ec2
Run the playbook
We can now run the playbook and it should create an ec2 instance.
ansible-playbook create_ec2.yml
Conclusion
We can create EC2 instances using Ansible playbook successfully. If there is any issue or clarification required, please let me know in the comment box and I will be more than happy to answer it.
Master Ansible Course on Udemy
You can purchase my ansible course on Udemy at a special price for a limited period.