Working with Ansible Roles

What is Ansible

Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs.

Designed for multi-tier deployments since day one, Ansible models your IT infrastructure by describing how all of your systems inter-relate, rather than just managing one system at a time.

It uses no agents and no additional custom security infrastructure, so it’s easy to deploy — and most importantly, it uses a very simple language (YAML, in the form of Ansible Playbooks) that allow you to describe your automation jobs in a way that approaches plain English.

Ansible works by connecting to your nodes and pushing out small programs, called “Ansible modules” to them. These programs are written to be resource models of the desired state of the system. Ansible then executes these modules (over SSH by default), and removes them when finished.

Introduction to Ansible Roles

Ansible Role is a concept that deals with ideas rather than events. Its basically another level of abstraction used to organize playbooks. They provide a skeleton for an independent and reusable collection of variables, tasks, templates, files, and modules which can be automatically loaded into the playbook. Playbooks are a collection of roles. Every role has specific functionality.

The ansible-galaxy command has a sub-command that will create a directory skeleton for our role.

To create a role using the ansible-galaxy command, we can simply use the below syntax in our terminal:

ansible-galaxy init <ROLE_NAME>

And the Directory Structure would be:

├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml

These many number of files and directories may appear to be difficult to work with, but they are fairly easy to understand. Above all, we always have the freedom to write our tasks and variable into other files but we must include directives into the directory’s main.yml file. Let us look into the use of these different directories in our role.

Defaults: The defaults directory is for defining the variable defaults. The variables in default have the lowest priority thus becoming easy to override. If definition of a variable is nowhere else, the variable in defaults/main.yml will be used.

Files: We use the files directory to add files that are needed by provisioning machine, without modification. Mostly, we use copy task for referencing files in the files directory. The most interesting part about this is that Ansible does not require a path for resources stored in files directory when working in the role.

Handlers: The handlers directory is used for storing Ansible handlers. Handlers are tasks that may be flagged during a play to run at the play’s completion. We can have as many and as few handlers as we need.

Meta: We use the meta directory to store authorship information which is useful if we choose to publish our role on The metadata of an Ansible role consists of author, supported platforms, and dependencies.

Tasks: The task directory is where we write most of our roles which includes all the tasks our role will perform. We write each series of tasks in a separate file and include them into the main.yml file in the tasks directory.

Templates: We use the template directory to also add files to our machine(similar to files directory). Only difference between template and files directories is that the template directory supports alteration (modification). Jinja2 language to used to create these alteration. Most software configuration files become templates.

Tests: We can use the tests directory if we have built and automated testing process around our role. This directory contains a sample inventory and a test.yml file.

Vars: This is where we create variable files that define necessary variables for our role. The variables defined in this directory are meant for role internal use only. Also, it is a good idea to namespace our role variable names, to prevent potential naming conflicts with variables outside of our role.

Now, this is the problem statement which we are aiming to solve

  1. Create an ansible role myapache to configure Httpd WebServer.

2. Create another ansible role myloadbalancer to configure HAProxy LB.

3. 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.

For the first part of the problem statement we need create a role with the above command. Here my role name is myapache to configure httpd webserver.

Now here is the code of main.yml file inside the task folder

main.yml of vars folder

And the main.yml file of handler

And we have to put our index.html file of our webpage in templates directory.

You can omit any directories the role does not use.

Now in the second part we have to create a role for configuring haproxy.

main.yml of tasks in haproxy

main.yml of vars directory

handler of haproxy

And the haproxy configuration file in templates directory

Here the value of variable port is given in vars directory and here we have used looping with jinja so that IPs will be added dynamically in configuration file from inventory.

Now for third part we need to combine both of these roles over each Managed Node in HAProxy.cfg file. For this we have to write another playbook to run and execute these roles.

Output of the playbook:

Output of playbook

Webpage with IP of load balancer:

Hence task successfully accomplished. I would also like to thank Prithviraj Singh for his collaborative efforts.

That’s all folks. Thanks for reading :)



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