An Introduction to Ansible Roles

Michael Jonaitis
4 min readSep 28, 2020

--

In the last tutorial I introduced you to a basic example of an Ansible Playbook. We used a very simple example to show the basics of registering minions with ssh keys and adding them to your hosts file and adding tasks to a playbook.

Most use cases for Ansible are much more complex, which is most definitely the reason Ansible even exists. If you were to add all the Ansible tasks to configure servers for all of your projects to a single playbook you will eventually run into a couple of issues.

First, it is difficult to maintain. Just like in programming you want to encapsulate things into organizational units to make it easy to work with.

Second, you want to be able to reuse your roles across multiple playbooks when they have similar dependencies. For instance many Ansible users create a “common” role which installs all the base packages you would be using on all your managed servers, such as git and python. If you had two projects with similar dependencies you could assign them both the common role rather than repeating all the tasks in both playbooks.

To solve this organizational issue Ansible allows us to organize our playbooks into roles.

Roles are, at the most basic level, groups of tasks organized by their purpose. For instance you might have a role to install and configure nginx or setup supervisor configuration files for your applications. Roles, are a simple way of dividing tasks into more organized units rather than having them all in a single playbook.

Add a new server to your inventory

Since I will be demonstrating a better way of doing what we did in the last tutorial, lets start fresh. Delete the server from your [webservers] group in your inventory, create a new server in Linode, add the ipaddress to your inventory file and copy the ssh key to the server just like we did in the previous tutorial.

Once you can ping your new server with this command, you are ready to continue.

ansible webservers -m ping

Result

<ip-address-of-web-server> | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}

Lets create our first role.

Roles are combination of folders and configuration files that tell Ansible which packages, files, commands to install or run on our minion servers. Roles are applied to our minions based on how they are organized (labeled) in our inventory file.

As a first step we will create a role to install some basic packages on our minion server by creating a role well call “basic” but you could name it anything you prefer.

The following image was taken from the Official Ansible Documentation. This shows the “best practice” directory layout when using roles. We will only be creating the highlighted section but we named out role “basic” instead of “common”.

Right now we will only be using the tasks folder. We will be going through the others in the next tutorial.

Each role can have all of these folders but they do not need to have them all.

So create a role we need to create a directory in the roles folder to represent our first role. We will create a first role folder called basic.

mkdir /etc/ansible/roles/basic

As we said each role folder needs to at least have one sub-folder named tasks so lets make that as well.

mkdir /etc/ansible/roles/basic/tasks

Within tasks there must be a yaml file called main.yml. This file will contain all the tasks which tell Ansible what to install or run on our minion. These tasks are exactly the same as the ones we added to our playbook in the previous tutorial.

touch /etc/ansible/roles/basic/tasks/main.yml

Adding Tasks

In our basic role we are going to test things out by adding some basic packages we would like installed if the minion is assigned the basic role. We will be using the same basic packages as we used in the first tutorial introducing playbooks. You can find the tutorial here.

Copy and paste the following yaml into the main.yml file.

- name: "Installing Vim"
apt: pkg=vim
- name: "Installing DNS Utils"
apt: pkg=dnsutils
- name: "Installing Git"
apt: pkg=git

If you did complete the previous tutorial, notice the difference in yaml. When using roles we only need to specify a list of tasks in the main.yml file itself.

The difference is that the playbook now just simply specifies which groups of servers in your inventory file get which roles. So we will change the playbook.yml file to assign the webservers hosts group to our new basic role.

---
- hosts: webservers
roles:
- basic

Now, if we run our playbook again.

root@ansible-control:/etc/ansible# ansible-playbook playbook.ymlPLAY [webservers] ******************************TASK [Gathering Facts] ************************************************
ok: <ip-address-of-web-server>
TASK [basic : Installing Vim] ************************************************
ok: <ip-address-of-web-server>
TASK [basic : Installing DNS Utils] ************************************************
ok: <ip-address-of-web-server>
TASK [basic : Installing Git] ************************************************
ok: <ip-address-of-web-server>
PLAY RECAP *************************************
<ip-address-of-web-server> : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

If all goes well you should see the same 3 tasks applied to the server, except these are now organized into a single role.

Now you understand how to reorganize a list of tasks from a playbook into an Ansible Role. In the next tutorial we will learning how to use Ansible along with templates to easily copy and “fill in” configuration files for your minion servers depending on their purpose.

Links:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#

--

--