Day 3- Ansible Roles: From Chaos To Order

Akash SutarAkash Sutar
6 min read

Introduction

An Ansible Role is an important feature of the Ansible tool that provides a structured way to organize plays, files, templates, variables, handlers, etc. This helps us to simplify complex Configuration Management and Automation as the tasks are attributed to a specific role. Unlike usual Ansible playbooks where all the tasks are written in a single file which makes it look complex, Ansible roles come into the picture by bifurcating the Playbook into different specified YAML files under various sections such as files, vars, tasks, and handlers.

Importance of roles in managing playbooks

  • Better organization and scalability.

  • Ansible Roles improve playbook readability and collaboration.

  • Ansible Roles allow us to reuse common configuration steps between different types of servers

Understanding Ansible Roles

Structure of an Ansible Role

Ansible Role has the following important components

  1. Tasks

    Contains the main list of tasks to be executed by the role

    Default File: main.yml

  2. Handlers

    Handlers are the special tasks that are triggered by the actions of the other tasks.

    Usually used to restart or reload the services when a task changes the state of the system

    Default File: main.yml

  3. Files

    Contains the static files to be transferred to target nodes/hosts.

    The files can be referenced using the copy and template module in the tasks

  4. Templates

    Contains Jinja2 templates, which can include variables that are dynamically replaced when the role is executed.

    Templates are used for configuration files where values are substituted dynamically from variables.

  5. Vars

    Stores variables with a higher priority than the Default Variables. Difficult to override.

  6. Defaults

    Stores the default variables for the role

    Default File: main.yml

  7. Meta

    Contains metadata about the role, including dependencies on other roles.

    Default File: main.yml

  8. Tests

    Contains test files for verifying that the role works as expected.

    • inventory is the test inventory file.

    • test.yml is a playbook to test the role.

  9. README.md

    Provides an overview of what the role does, how to use it, and any specific requirements or configurations needed.

Creating Ansible Roles

Let us understand the Ansible Roles by practically working on a problem statement.

Problem statement:

An ansible cluster having a test node and a prod node with a control/master node is set up. On test, Nginx and on prod Apache webserver needs to be installed using Ansible roles nginx and apache respectively. The default webpage hosted on the server should be updated with a custom webpage

  1. Setting up the ansible environment

We already have the environment set up with a master Ansible server and cluster of test and prod servers.

The ansible installation steps can be accessed here.

The host inventory has the following hosts mentioned

  1. Setting up a role directory

Creating two roles ‘nginx’ and ‘apache’ using the below galaxy command

cd /etc/ansible/roles

sudo ansible-galaxy init <rolename>

To visualize the role directory structure, we need to install the tree package

sudo apt install tree

tree <rolename>

More about Ansible Galaxy for role structure

Ansible Galaxy is a community-driven hub where we can find, share, and download Ansible roles and collections. It simplifies role management by providing a central platform to access reusable content, so we don’t have to start from scratch. Whether we need to set up a web server, manage databases, or automate other tasks, Galaxy offers ready-made roles to speed up our workflow. Plus, we can share our roles with others, contributing to the community and benefiting from the work of others.

https://docs.ansible.com/ansible/latest/cli/ansible-galaxy.html

  1. Nginx Role Configurations

    Navigate to tasks dir and edit main.yml file to include the below yaml files

    install.yml, configure.yml, service.yml

    sudo touch install.yml configure.yml service.yml

    sudo vi main.yml

    The install.yml will have steps to install nginx

    The configure.yml will contain yaml command to copy a custom webpage code to be configured on a remote host. We will keep it blank for now.

    The service.yml will have the steps to start the services.

  2. Apache Role Configuration

    Similar to the Nginx role, we will configure the details for Apache2 as well.

    service.yml

    install.yml

    service.yml

  1. Creating the main playbook: roles.yml

Navigate to playbooks dir inside /etc/ansible/playbooks

and create a roles.yml file as follows

Let’s check the syntax before running the playbook

ansible-playbook —syntax-check roles.yml

Encountered an error stating role is not a valid attribute for play.

Rectifying the error by updating role to roles

The roles.yml file’s syntax is ok with a warning that the configure.yml file is empty which is ok.

Running the playbook

The playbook has failed at task of service restart for nginx.

TASK [nginx : nginx service start and enbale] ******************************************************************************************************************** fatal: [test1]: FAILED! => {"changed": false, "msg": "Unable to start service nginx: Job for nginx.service failed because the control process exited with error code.\nSee "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.\n"}

Troubleshooting the issue:

This error has occurred because the port 80 to which nginx listens is already in use

Another website is already hosted on the port 80 :

The webpage was hosted on apache as a part of earlier project

I have purged the apache on test server

sudo apt purge apache2

Rerunning the Playbook

Playbook ran successfully!

The test and prod have successfully hosted the nginx and Apache websites

nginx on test

apache on prod

Now, let us update the webpage by updating configure.yml

We will update the Nginx webpage with a static webpage placed inside the Files folder.

Updating the configure.yml file

Here, we have used notify that triggers the handler’s task to restart Nginx

Now, let us update the configure.yml and other dependencies for the Prod server update

We will define a variable, which will be used in the custom template of the webpage

cd /etc/ansible/roles/apache/vars

vi main.yml

We will create a template named index.html.j2 - a Jinja2 file that will get updated on the remote Prod server.

Here, the variable defined inside the vars folder is used in the file. Jinja2 replaces

{{ custom_hostname }} with the actual hostname at the time of playbook execution.

Creating a configure.yml file

/etc/ansible/roles/apache/tasks

Updating the Handlers

/etc/ansible/roles/apache/handlers/main.yml

Running the roles.yml playbook

cd /etc/ansible/playbooks

ansible-playbook --check roles.yml

It failed due to incorrect indentation in handlers of nginx role

Rerunning the playbook

ansible-playbook roles.yml

Webpage updated as well

Nginx:

Apache2:

Conclusion

Ansible roles enforce the structure and reusability of all our automation tasks so that we can work comfortably with configurations across different environments. With its power, complex processes become more scalable and reduce redundancy in the playbooks. From deploying web servers to managing the infrastructures, Ansible roles represent clean and efficient ways to deliver precision towards our automation goals. As we continue on to hone our automation abilities, mastering roles will become one of the bedrocks in our arsenal of DevOps, smoothing the deployment process and making for more robust systems!!

0
Subscribe to my newsletter

Read articles from Akash Sutar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Akash Sutar
Akash Sutar