How to Create EC2 Instance Using Ansible Playbook in 5 minutes

In this article, let’s see how we can create EC2 instance using the Ansible Playbook.

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 to rsa, 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 to true.
  • tags: Specifies tags to be applied to the instance, in this case, setting the Environment tag to Testing.
  • wait: Specifies whether Ansible should wait for the instance to reach the desired state before proceeding. In this case, it’s set to true.
  • register: ec2_result: Registers the output of the task to a variable named ec2_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.

Scroll to Top