Provisioning ec2 instance on AWS and Configuring Apache Webserver using Ansible without Dynamic Inventory

Hello guys !! Back with another article, In this article you will find how we can provision an ec2 instance on AWS and configure apache webserver at the same time without using dynamic inventory. Yes, you read right. Ansible can now also used for provision. Back when ansible as a automation tool then there was only competitor was puppet and chef. In that time ansible was only used for configuration management. But after several years, it can also be used as a provisioning tool. You can understand from the below architecture.

Architecture of configuration and provision by ansible

Ansible is a software tool that provides simple but powerful automation for cross-platform computer support. It is primarily intended for IT professionals, who use it for application deployment, updates on workstations and servers, cloud provisioning, configuration management, intra-service orchestration, and nearly anything a systems administrator does on a weekly or daily basis. Ansible doesn’t depend on agent software and has no additional security infrastructure, so it’s easy to deploy.

How Ansible works

In Ansible, there are two categories of computers: the control node and managed nodes. The control node is a computer that runs Ansible. There must be at least one control node, although a backup control node may also exist. A managed node is any device being managed by the control node.

Ansible works by connecting to nodes (clients, servers, or whatever you’re configuring) on a network, and then sending a small program called an Ansible module to that node. Ansible executes these modules over SSH and removes them when finished. The only requirement for this interaction is that your Ansible control node has login access to the managed nodes. SSH Keys are the most common way to provide access, but other forms of authentication are also supported.

Ansible playbooks

While modules provide the means of accomplishing a task, the way you use them is through an Ansible playbook. A playbook is a configuration file written in YAML that provides instructions for what needs to be done in order to bring a managed node into the desired state. Playbooks are meant to be simple, human-readable, and self-documenting. They are also idempotent, meaning that a playbook can be run on a system at any time without having a negative effect upon it. If a playbook is run on a system that’s already properly configured and in its desired state, then that system should still be properly configured after a playbook runs.

Modules in Ansible

Modules (also referred to as “task plugins” or “library plugins”) are discrete units of code that can be used from the command line or in a playbook task. Ansible executes each module, usually on the remote managed node, and collects return values.

Variables in Ansible:

Ansible uses variables to manage differences between systems. With Ansible, you can execute tasks and playbooks on multiple different systems with a single command. … You can define these variables in your playbooks, in your inventory, in re-usable files or roles, or at the command line.

Ansible Installation In Below Slides:

So, let’s start with some little bit visual explaination and playbooks.

As you can see in the above gif, there are two nodes. one is controller node and one is target node. The controller node is in Oracle VM and the other nod i.e target node will be going to launch on AWS. And after the launching of ec2 instance ansible will fetch the public IP of ec2 instance and store them inside a file named as hosts.txt. Here you can give any file name. Now, when ansible will going to do configuration it will take the IP from hosts.txt file and it will do the apache webserver configuration into that instance.

So lets start building this setup. We will require a SDK so that ansible can go to that AWS account and do the provisioning first. Boto and latest version of Boto is Boto3. we need to download this two software.

yum install python3 
pip3 install boto
pip3 install boto3
installing boto and boto3

check the ansible version

ansible  --version
checking ansible version

Ansible 2.9 and ansible 2.10 is the latest version. you can work with both. Not any such difference between these two version.
As we have installed boto and boto3 library. So, ansible will go on AWS via localhost as it will using API of AWS services.

We need to write some code inside the configuration file of ansible.

As you can see the configuration file of ansible, In the default section there is inventory which will be having the public IP after the OS get launched successfully.

As Ansible works on the ssh protocol for linux OS. So we need to disable the ssh key, as when you do ssh it asks you for yes/no. So to disable that you need to write host_key_checking=false.

To avoid some warnings given by the command we can disable that using command_warnings=false

To login in that newly launched OS we need to provide its respective key. Note: key with .pem format file will work not with the .ppk format. Also you need to give permission to that key in the read mode.

Permissions in linux
0 → No modes
1 → execute mode
2→ write mode
3 → write execute mode
4 → read mode
5 → read write mode
6 → read write mode
7 → read write and execute mode.

So, here i am giving the execute permission to that key.

chmod   400   keyname.pem

The ec2-instance Instances on AWS login firstly into the ec2-user. So we need to give the remote user. if you are launching ubuntu then then you need to provide remote-user=ubuntu, But here as i have launched ec2 instance so i need to give remote-user=ec2-user.

After that we need to give the information about from which user we will be making the configuration. If your user is not the sudoers files then you need to run using sudo command. So that’s why i used sudo as a method and user as a root. you can neglect the option of become_ask_pass=false. The Above information is known as privilege escalation in ansible.

[defaults]
inventory=location
host_key_checking=false
ask_pass=false
remote_user= ec2-user
private_key_file=/path/key.pem
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false

Now, we need to write the playbook of provisioning and configuration together with the apache web server.

Provisioning Variable Playbook Of ec2 instance on AWS

key: "ansiblekey"
instancetype: "t2.micro"
image_name: "ami-052c08d70def0ac62"
total_count: 1
name_of_instance: "aws_ansible_ec2"
subnet_id: "subnet-0f52803afe10747e7"
AZ: "ap-south-1"
security_group: "sg-09f6ca37ea9000fc8"
access_key: "type your access key here"
secret_key: "type your secret key here"
pause_time_in_minutes: 2

As you can see in the above variable playbook. we have key, instancetype, image_name, total_count, name_of_instance, subnet_id, AZ, security_group, access_key, secret_key, pause_time_in_minutes will take the respective values and this variables can be used by aws ec2 instance provisioning playbook.

Provisioning Playbook Of ec2 instance on AWS

- hosts: "localhost"
vars_files:
- aws_var.yml
tasks:
- name: "provisioning ec2 instance"
ec2:
key_name: "{{ key }}"
instance_type: "{{ instancetype }}"
image: "{{ image_name }}"
wait: yes
count: "{{ total_count }}"
instance_tags:
Name: "{{ name_of_instance }}"
vpc_subnet_id: "{{ subnet_id }}"
assign_public_ip: yes
region: "{{ AZ }}"
state: present
group_id: "{{ security_group }}"
aws_access_key: "{{ access_key }}"
aws_secret_key: "{{ secret_key }}"
register: X
- name: "copying the ipaddress to host file"
copy:
content: "{{ X.instances[0].public_ip }}"
dest: "/root/hosts.txt"
- name: "wait for 2 minutes"
pause:
minutes: "{{ pause_time_in_minutes }}"

As you can see in the above playbook, i have taken localhost as a host. Below that i have included the variables which i have written above. Now, fist task is included by ec2 module. ec2 module include the below parameters. key_name → Give your key name of os you want to launch

instance_type → Which type of Instance you want to launch eg. “t2.micro”

image → Give your Image ID name

wait → the wait parameter will helps to wait after the OS launches

count → How many OS you want to launch give that count

instance_tags → give instance some name

vpc_subnet_id → In which subnet you want to launch. give that subnet ID.

assign_public_ip → Do you want to have public IP of your OS (yes, no).

region → In which region you want to launch the OS eg. “ap-south-1a”

state → (present) This will launch the OS to terminate the OS you can give absent.

group_id → Security Group ID(which rules you want to set as the firewall of the OS)

aws_access_key → give your IAM access key. So ansible can go to your AWS account and login.

aws_secret_key → give your IAM secret key. So ansible can go to your AWS account and login.

As ansible will run above ec2 module and it’s respetive parameters it will register all the outputs in X variable. As we want Public IP of that instance so we cam extract using this regx “X.instances[0].public_ip”.

register → this module helps you to assign any output in a your respective variable.

After retrieving the public IP of the newly launched ec2 instance. we will be copying that public IP in a file named as hosts.txt. Here, i have used the copy module and in that copy module i have used the content parameter. So, i have given the above regx in that content and its respective destination.

Publib IP copied in the host.txt file

After this i have used pause module that will stop the playbook. This will helps the ec2 instance to launch the ec2 instance in sufficient time. In above playbook the pause module will stop the playbook for 2 minutes.

pause → This will stop the playbook, minutes → enter your minutes

Now let’s see the playbook of webserver for apache webserver configuration in that particular newly launched ec2 instance.

So the ec2 has launched. let see the output on the AWS dashboard.

ec2 instance launched successfully

Playbook of Configuration of Apache Webserver in ec2 instance on AWS

- hosts: all
vars:
- software_name: "httpd"
- src_loc: "/root/my.html"
- dest_loc: "/var/www/html"
tasks:
- name: "Installing httpd"
package:
name: "{{ software_name }}"
state: present
- name: "copy the webpages"
copy:
src: "{{ src_loc }}"
dest: "{{ dest_loc }}"
notify: "restarting_httpd"
- name: "Starting httpd"
service:
name: "{{ software_name }}"
state: "started"
handlers:
- name: "restarting_httpd"
service:
name: "{{ software_name }}"
state: restarted

In the above webserver configuration file i have used the host to be all. As there will one instance for webserver configuration. I have used these respective vars as software_name, src_loc, dest_loc.

The respective task is written above in the webserver playbook.

First Task → Install HTTPD apache software

Second Task → Copy the respective file at the respective document root

Third Task → Start the HTTPD service

Below i have used the handlers module. Handler is a module which will be handling the playbook. Handlers comes with the notify keyword. Which things you want to handle you to notify there with the notify keyword. Now as there some change in the content the handler will run the service of restarting httpd. Because i have used handler’s notify keyword after the copy module.

So, Now lets run the playbook. The above explanation was the output of respective playbook. Lets now run the main playbook.

Main Playbook

- name: "Provisioning ec2"
import_playbook: aws.yml
- hosts: localhost
tasks:
- pause:
minutes: 2
- name: "Configuring Webserver inside"
import_playbook: webserver.yml

The above playbook is the main playbook in which i have imported the aws.yml which is the provisioning of ec2 instance playbook and after that i have stopped the playbook 2 minutes using the pause module so that we can easily get satisfied output. After that i have imported the webserver.yml playbook which is for configuring apache webserver in that newly launched ec2 instance.

Command to run the playbook:

ansible-playbook   final_plabook.yml

The output of the above command is given below.

main playbook

After running this playbook successfully then we can see the website on aws.

Webpage Deployed Successfully

YAY !! The Webpage Deployed !!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Amit Sharma

RHCE || Aspiring MLOps-DevOps Engineer || Open to Work || MLOPS 🧠 || DEVOPS 🐳☸👩🏻‍🍳🦊 || HYBRID ☁️ || Terraform || Ansible || ML || DL || GitLab || Jenkins|