Leveraging Ansible to automate AWS instance management
Ansible is an open-source software automation tool suited for instance configuration and provisioning, enabling an Infrastructure as Code approach to the Cloud. In this page we provide a set of ansible-playbooks templates to perform the most common task to tune EC2 instance types with Akamas, such as:
EC2 instance creation
EC2 instance termination
EC2 instance resizing
Refer to the Ansible documentation and to the Ansible ec2 module for more details, and make sure to check the concepts behind inventory management to build a robust automation.
The orchestrator requires access to an account or role linked to the correct policies; this requires managing AWS Policies and having access to the required security groups.
Instance Creation
The following example playbook provisions an EC2 instance using the latest Ubuntu 18-04 LTS image and then waits for it to be available. The playbook requires the following set of arguments:
key: the name of the SSH key pair to use
Name: the instance name
security_group: the name of the AWS security group
region: the selected AWS region
You can update the ec2_ami_info
task to query for a different AMI family or specify directly the id under ec2.image
.
When executing the script we must assign the following arguments as extra-vars:
intance_type: type of instance to provision
volume_size: size of the attached volume
# Launch an ubuntu instance and wait for ssh
- name: Create an instance request
hosts: localhost
gather_facts: False
tasks:
- name: query api
ec2_ami_info:
filters:
name: "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"
owner-id: "099720109477" # Canonical Group Limited
register: amis
- name: sort by creation date
set_fact:
sorted_amis: "{{ amis.images | sort(attribute='creation_date') }}"
- name: get latest
set_fact:
latest_ami: "{{ sorted_amis | last }}"
- name: Launch instance
ec2:
key_name: "{{ key }}"
instance_type: "{{ instance_type | default('m5.xlarge') }}"
group:
- <your-security-groups>
image: "{{ latest_ami.image_id }}"
count: "{{ count | default('1') }}"
wait: yes
wait_timeout: 500
region: "{{ region }}"
spot_wait_timeout: 600
instance_initiated_shutdown_behavior: terminate
ebs_optimized: yes
volumes:
- device_name: /dev/sda1
volume_type: gp2
volume_size: "{{ volume_size | default('20') }}"
delete_on_termination: yes
instance_tags:
Name: "{{ Name }}"
CNAME: "{{ Name }}.<your-domain>"
register: ec2
- name: Wait for SSH to come up
wait_for:
host: "{{ item.public_dns_name }}"
port: 22
delay: 60
timeout: 320
state: started
with_items: "{{ ec2.instances }}"
To apply the EC2 parameters from the AWS Optimization Pack selected by the Akamas engine you can generate the playbook arguments through a template like the following one, where ec2
is the name of the component:
ansible-playbook -i inventory --extra-vars "instance_type=${ec2.aws_ec2_instance_type}.${ec2.aws_ec2_instance_size}" provision.yaml
Instance Termination
The following playbook terminates all instances with the specified name (or any other tag). It requires the following arguments:
instance_name: the name instances name
region: the selected AWS region
# Terminate an aws instance
- name: Terminate instance
hosts: localhost
gather_facts: False
tasks:
- name: retrieve instance info
ec2_instance_info:
filters:
"tag:Name": "{{ instance_name }}"
register: ec2
- name: terminate the instance
ec2:
state: absent
instance_ids:
- "{{ item.instance_id }}"
region: "{{ region }}"
with_items: "{{ ec2.instances }}"
Instance Resizing
Instance resizing is a little trickier to deploy as it requires you to install AWS CLI and setup the required credentials. The following playbook provides a simple way to stop, update and restart your instance: it is intended as a building block for more elaborate workflows.
It makes use of a list of arguments:
instance_name: your instance name
region: the selected AWS region
For a successful workflow it requires:
The instance to exist
The instance to be unique
# Change instance type, requires AWS CLI
- name: Resize the instance
hosts: localhost
gather_facts: no
connection: local
tasks:
- name: save instance info
ec2_instance_info:
filters:
"tag:Name": "{{ instance_name }}"
register: ec2
- name: stop the instance
ec2:
region: "{{ region | default('us-east-2') }}"
state: stopped
instance_ids:
- "{{ ec2.instances[0].instance_id }}"
instance_type: "{{ ec2.instances[0].instance_type }}"
wait: True
- name: Change the instances ec2 type
shell: >
aws ec2 modify-instance-attribute --instance-id "{{ ec2.instances[0].instance_id }}"
--instance-type "{{ new_instance_type }}"
delegate_to: localhost
- name: restart the instance
ec2:
region: "{{ region }}"
state: running
instance_ids:
- "{{ ec2.instances[0].instance_id }}"
wait: True
register: ec2
- name: wait for SSH to come up
wait_for:
host: "{{ item.public_dns_name }}"
port: 22
delay: 60
timeout: 500
state: started
with_items: "{{ ec2.instances }}"
To apply the EC2 parameters from the AWS Optimization Pack selected by the Akamas engine you can generate the playbook arguments through a template like the following, where ec2
is the name of the component:
ansible-playbook -i inventory --extra-vars "new_instance_type=${ec2.aws_ec2_instance_type}.${ec2.aws_ec2_instance_size}" resize.yaml
Last updated
Was this helpful?