Provision & Configure AWS ELB to distribute traffic to backend AWS EC2 Instances using Ansible
By: Daksh Jain
Tags: Automation, AWS, Load Balancer, Redhat Ansible, Ansibe

Step 1— Main Playbook

Play 1 — Configure Localhost for Provisioning AWS Instance

Variables -

- hosts: localhost

gather_facts: no

vars_files:

- mycred.yml vars:

myport: 81

region: ap-south-1

subnet:

- subnet-c48ee588

- subnet-ca87bda2

sg: websg

type: t2.micro

number: 1

key: key1

id: []

ip: []

🔴 The main thing to note here is the subnet ID. Here you need to specify YOUR Subnet IDs in which YOU want to launch the instances. 🔴

id & ip

These 2 empty lists are created to be used later.

These 2 empty lists are created to be used later. ip list is required to configure the instances after the launch. We need to tell all the IPs present in different subnets to the second play that will configure these instances with httpd software and test code.

list is required to configure the instances after the launch. We need to tell all the IPs present in different subnets to the that will these instances with id list is created to collect all the instance IDs to provide to the third play in which a load balancer will be configured in front of these backend servers. The load balancer will require all the IDs of the instances to connect to them.

Installations -

tasks:

- name: installing python

package:

name: python36

state: present

- name: installing boto3

pip:

name: boto3

state: present

Boto3 is the Amazon Web Services (AWS) SDK for Python. It enables Python developers to create, configure, and manage AWS services.

So using these 2 tasks I am checking the presence of Python & Boto3. If not present these 2 tasks will download the same.

Security Group for EC2 Instance -

- name: create security group

ec2_group:

name: "{{ sg }}"

description: The webservers security group

region: "{{ region }}"

aws_access_key: "{{ access_key }}"

aws_secret_key: "{{ secret_key }}"

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: "{{ myport }}"

to_port: "{{ myport }}"

cidr_ip: 0.0.0.0/0

rules_egress:

- proto: all

cidr_ip: 0.0.0.0/0

Next, I have created the Security Group to be used by the AWS EC2 Instance. It picks up the values from the variables declared above.

In the security group, 2 things have to be set: Ingress and Egress.

Ingress means the traffic that is coming into our website. We need to specify this, keeping in mind what ports we want to keep open. I have kept open 2 ports: SSH, and HTTP.

SSH so that Ansible can connect to it to do the configuration.

so that Ansible can connect to it to do the configuration. HTTP so that traffic can hit on the website. The port is specified from the variable provided above.

Egress has been set to all ports so that outbound traffic originating from within a network can go outside to the Public World.

Provision EC2 Instance -

- name: launching ec2 instance

loop: "{{ subnet }}"

ec2:

key_name: "{{ key }}"

instance_type: "{{ type }}"

image: ami-0ebc1ac48dfd14136

wait: true

group: "{{ sg }}"

count: "{{ number }}"

vpc_subnet_id: "{{ item }}"

assign_public_ip: yes

region: "{{ region }}"

state: present

aws_access_key: "{{ access_key }}"

aws_secret_key: "{{ secret_key }}"

instance_tags:

Name: webserver

register: ec2

All the variables used are similar to the previous one with only one update. Since I am launching the EC2 instances in different subnets(which are specified earlier) so I am running a loop to create the required number of instances in each subnet.

The whole thing is registered in a variable “ec2” which will be used later.

Adding Instance Public IP & Instance ID to lists -

- set_fact:

id: "{{ id + item['instance_ids'] }}"

with_items:

- "{{ ec2.results }}"

- debug:

msg: "{{ id }}"

- set_fact:

ip: "{{ ip + item['instances'] }}"

with_items:

- "{{ ec2.results }}"

- debug:

msg: "{{ item.public_ip }}"

with_items: "{{ ip }}"

Using the module set_fact I am appending the lists. The IP & Instance ID is coming directly from ec2 variable which was stored while creating the instances.

Add to Inventory dynamically -

- name: Add new instance to host group

add_host:

hostname: "{{ item.public_ip }}"

groupname: webserver

loop: "{{ ec2.instances }}"

- name: Wait for SSH to come up

wait_for:

host: "{{ item.public_dns_name }}"

port: 22

state: started

loop: "{{ ec2.instances }}"

add_host is a module that helps to add IPs in the inventory file dynamically for use by Ansible. For this, I have used the concept of “for loop” because this playbook can launch as many instances as the user wants.

So in the loop, the variable is ec2.instances & in the hostname keyword, the variable used is item.public_ip. item is a pre-defined variable for the for loops in Ansible.

Since it will take some time to connect to the EC2 Instance, we have to tell Ansible to wait.

wait_for module is used where I have specified the port 22 i.e. SSH and again looped over so that it can let Ansible wait to get connected to all the instances. Once it is connected it goes on to the next task.