Configure Load Balancer and Webserver Using Ansible Roles

Mohd Sabir
6 min readMar 20, 2021

What is Ansible ?

Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code. It runs on many Unix-like systems, and can configure both Unix-like systems as well as Microsoft Windows. Ansible is agentless, temporarily connecting remotely via SSH or Windows Remote Management (allowing remote PowerShell execution) to do its tasks.

What is Ansible Role ?

Writing ansible code to manage the same service for multiple environments or different products increase code redundancy. With more complexity in functionality, it becomes difficult to manage everything in one ansible playbook file. Sharing code among teams become difficult.

Ansible Role helps solve these problems. Ansible role is an independent component which allows reuse of common configuration steps. Ansible role has to be used within playbook. Ansible role is a set of tasks to configure a host to serve a certain purpose like configuring a service. Roles are defined using YAML files with a predefined directory structure.

A role directory structure contains directories: defaults, vars, tasks, files, templates, meta, handlers. Each directory must contain a main.yml file which contains relevant content. Let’s look little closer to each directory.

  1. defaults: contains default variables for the role. Variables in default have the lowest priority so they are easy to override.
  2. vars: contains variables for the role. Variables in vars have higher priority than variables in defaults directory.
  3. tasks: contains the main list of steps to be executed by the role.
  4. files: contains files which we want to be copied to the remote host. We don’t need to specify a path of resources stored in this directory.
  5. templates: contains file template which supports modifications from the role. We use the Jinja2 templating language for creating templates.
  6. meta: contains metadata of role like an author, support platforms, dependencies.
  7. handlers: contains handlers which can be invoked by “notify” directives and are associated with service.

Task Description📄

🔅Create an ansible role myapache to configure Httpd WebServer.

🔅Create another ansible role myloadbalancer to configure HAProxy LB.

🔅We need to combine both of these roles controlling webserver versions and solving challenge for host ip’s addition dynamically over each Managed Node in HAProxy.cfg file.

Let’s start doing our task:-

⚠️ Note: By Default Ansible provide some path to keep role

 /root/.ansible/roles does 
/usr/share/ansible/roles
/etc/ansible/roles

either we can keep our roles here or we can also change , if we want to keep roles in our workspace then we have to tell Ansible where our roles are available , we have to write roles path in ansible config file , I will keep roles in “/myroles” , let’s update this path to ansible config file

vim /etc/ansible/ansible.cfgroles_path=/myroles
ansible.cfg

🔅Create an ansible role myapache to configure Httpd WebServer.

Let’s create a Ansible role to configure httpd server

for creating new role

ansible-galaxy role init myapache

myapache role created successfully

when we run “ ansible-galaxy role init myapache” command they automatically create a structure for us , this structure look like this

now let’s start writing our task here,

vim task/main.yml

---
# tasks file for myapache
- package:
name: "{{ item }}"
state: present
loop:
- httpd
- php
- copy:
dest: /var/www/html
src: files/index.php
- service:
name: "{{ service_name }}"
state: started

vim vars/main.yml

---
# vars file for apache
service_name: "httpd"

vim files/index.php

<pre><?phpprint `/usr/sbin/ifconfig`;?></pre>

now our final role structure is look like this :-

This role will configure webserver for us.

Let’ s move to another step :-

🔅Create another ansible role myloadbalancer to configure HAProxy LB.

ansible-galaxy role init myloadbalancer

now let’s start writing our task detail in role-

vim tasks/main.yml

---
# tasks file for myloadbalancer
- name: Install the Haproxy package
package:
name: "{{ package_name }}"
state: present
- name: Change the config file of haproxy
template:
dest: /etc/haproxy/haproxy.cfg
src: templates/haproxy.cfg.j2
notify:
- Restart the service
- name: Start the service
service:
name: "{{ service_name }}"
state: started
enabled: yes

vim vars/main.yml

---
# vars file for myloadbalancer
#
package_name: haproxy
service_name: haproxy
fsp: 8080
bsp: 80

vim handlers/main.yml

---
# handlers file for myloadbalancer
- name: Restart the service
service:
name: "{{ service_name }}"
state: restarted

vim templates/haproxy.cfg.j2

#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:{{ fsp }}
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static 127.0.0.1:4331 check
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
{% for i in groups['Backend_servers'] %}
server app{{ loop.index }} {{ i }}:{{ bsp }} check
{% endfor %}

final structure of myloadbalancer role

This role will configure loadbalancer for us.

🔅We need to combine both of these roles controlling webserver versions and solving challenge for host ip’s addition dynamically over each Managed Node in HAProxy.cfg file.

vim setup.yml
---
- hosts: localhost
roles:
- role: "myloadbalancer"
- hosts: Backend_servers
roles:
- role: "myapache"

save this file, and run this playbook

ansible-playbook setup.yml

Playbook runs succesfully

Let’s check

paste your loadbalancer IP in your browser

http://IP_of_Loadbalancer:Portno

load balancer is working properly.

Task has been done!!

Thanks for reading.

--

--

Mohd Sabir

DevOps Enthusiastic || Kubernetes || GCP || Terraform || Jenkins || Scripting || Linux ,, Don’t hesitate to contact on : https://www.linkedin.com/in/mohdsabir