Understanding roles in Ansible

As easy as Ansible is to get started with, and as readable as a playbook is when it is short, it does get more complex, as do the requirements. In addition, there are certain functions that may well be needed repeatedly in different scenarios. For example, you might need to deploy a MariaDB database server as a common task in your environment. A module called apt is used for managing packages on Ubuntu servers, and so, if we wanted to install the mariadb-server package on our test system, the playbook to perform this task could look like this:

---
- name: Install MariaDB Server
hosts: localhost
become: true

tasks:
- name: Install mariadb-server package
apt:
name: mariadb-server
update_cache: yes

Note that this time, we have set become to true, as we need root privileges to install packages. This is, of course, a very simple example, as installing a database server normally requires a great deal more configuration work, but it serves as a starting point. We could run this on our test system, and yield the desired result, as follows:

So far, so good. If you had to do this on a routine basis, though, in different playbooks for different hosts, would you really want to be writing (or, indeed, copying and pasting) that tasks block from this example over and over again? Also, this example is simplistic, and in reality, the database deployment code would be far more complex. If someone makes a fix or improvement in the code, how do you ensure that this new revision of code is propagated into all the right places?

This is where roles come in, and an Ansible role, while in essence nothing more than a structured set of directories and YAML, enables efficient and effective reuse of code. It also makes the initial playbook easier to read, as we shall see shortly. Once roles are created, they can be stored in a central location, such as a version control repository (for example, GitHub), and then, the latest version can always be accessed whenever a playbook needs to install MariaDB.

Roles are (by default) run from a subdirectory called roles/in the same directory as your playbook. Throughout this book, we will use this convention, though it must be stated that Ansible will also search for roles in /etc/ansible/roles and the paths specified by the roles_path parameter in the Ansible configuration file (which, by default, can be found in /etc/ansible/ansible.cfg, though there are ways to override this). Each role then has its own subdirectory under this, and that directory name forms the name of the role. Let's explore this through a simple example, as follows:

  1. We will get started by creating a roles/ directory, and an install-mariadb/ directory under this, for our first role:
$ mkdir -p roles/install-mariadb
  1. Each role has a fixed directory structure under it; however, for our simple example, we are only interested in one: tasks/. The tasks/ subdirectory of a role contains the main list of tasks that will be run when the role is called, in a file called main.yml. Let's create that directory now, as follows:
$ cd roles/install-mariadb
$ mkdir tasks
$ vi tasks/main.yml

  1. Naturally, you can use your preferred editor in place of vi. In the main.yml file, enter the following code—note that it is essentially the tasks block from the original playbook, but the indentation level has now changed:
---
- name: Install mariadb-server package
apt:
name: mariadb-server
update_cache: yes
  1. Once we have created this file, we then edit our original install-db.yml playbook so that it looks like this:
---
- name: Install MariaDB Server
hosts: localhost
become: true

roles:
- install-mariadb

Notice how much more compact the playbook is now! It is also a great deal easier to read, and yet if we run it, we can see that it performs the same function. Note how the state of the MariaDB server installation task was changed last time we ran it but is now ok. This means that Ansible detected that the mariadb-server package was already installed, and hence no further action was required. This is an example of the previously mentioned idempotent change in action, as can be seen in the following screenshot:

Well done! You have created and executed your first role. If you want to read more about roles and the required directory structure, please refer to https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html.

There's even more to roles than this—not only are they invaluable in structuring your playbooks and enabling reuse of code; there is also a central repository for community-contributed roles, called Ansible Galaxy. If you search Ansible Galaxy for MariaDB-related roles, you will find (at the time of writing) 277 different roles, all designed to perform various database installation tasks. This means that you don't even have to write your own roles for common tasks—you can either make use of community-contributed ones or fork them, and modify them to your own ends. Most common server automation tasks have already been solved somewhere along the way by the Ansible community, and so it is very likely you will find exactly what you are looking for.

Let's test this now, as follows:

  1. First, install a role from Ansible Galaxy that installs MariaDB server on Ubuntu:
$ ansible-galaxy install -p roles/ mrlesmithjr.mariadb-mysql
  1. Now, we will modify our playbook to reference this role instead:
---
- name: Install MariaDB Server
hosts: localhost
become: true

roles:
- mrlesmithjr.mariadb-mysql
  1. That's all that is required—if we run it, we can see that this playbook performs many more tasks than our simple one, including a lot of the security setup that is good practice when installing a new database, as can be seen in the following screenshot:

The end result, however, is that the mariadb-server package is installed on our test system—and this time, we barely even had to write any code! It is advisable, of course, to check what a role from Ansible Galaxy is going to do before blindly running it on your systems, in case it makes changes that you hadn't expected (or wanted!). Nonetheless, roles, in conjunction with Ansible Galaxy, form a powerful addition to the value that Ansible has to offer.

With an understanding of roles under our belts, in the next section, we will look at an important concept to help you get the most out of your playbooks and roles by making their content dynamic: Ansible variables.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset