Ansible - Roles 1/2

Let's do Ansible, they said. Writing simple playbooks is easy, they said. But, should one really write playbooks over and over again? Repeat yourself? Not at all, for sure. Automation is about avoiding repetition, and Ansible has some concepts to address this.

Ansible - Roles 1/2

Let's do Ansible, they said. Writing simple playbooks is easy, they said. But, should one really write playbooks over and over again? Repeat yourself? Not at all, for sure. Automation is about avoiding repetition, and Ansible has some concepts to address this.

Let's talk about roles and how they will address repetition. In the first part, I want to show how roles work. In the second part, we will develop our own role from scratch.

Ansible Roles

If you think of Ansible Modules as a hammer and Ansible Playbooks as the complete plan for your house, Ansible Roles are the construction plan for single furniture and inventories are the layout of rooms.

Roles are useful if you want to generalize the setup of a single service or a repeatable structure. Good examples for a role are "setup of a web server" or "deployment of a service to a cloud provider" and even "basic configuration of a firewall". But in the end, you will decide how you can use and develop roles.

Ansible Roles provide a simple format and structure, to share default behaviors and event driven task execution. Therefore, Roles can be seen as some kind of deliverable. You can provide Ansible Roles on their own or as part of an Ansible Collection. If you want, you can compare Ansible Roles to Container Images or an automated "How To".

Using Roles

The first part will be about using roles. You can consume roles, that are made and published from other users. This can have some benefits, if you want to prototype a setup or just get it done. Even if you consider writing your own roles, you can challenge your own ideas and see what others have done and how they solved a problem.

Let's use some roles. Shall we?

Find Roles

The very first thing, that needs to be done? Finding a role that suites your demand. This can be done in multiple ways.

Ansible Galaxy

The major "marketplace" for Ansible content is the Ansible Galaxy. It can be accessed in the browser and via command line. It's pretty easy to do this.

# Search for mariadb role
$ ansible-galaxy role search mariadb

...
 bodsch.mariadb                                 MariaDB Server for debian (Ubuntu), RedHat (CentOS) and Arch Linux.
...

Getting additional information about the role can be done without installing it.

# Get information about a role
$ ansible-galaxy role info bodsch.mariadb

Role: bodsch.mariadb
        description: MariaDB Server for debian (Ubuntu), RedHat (CentOS) and Arch Linux.
        active: True
        commit: 6409940c0df3e5d5b4f3d212583ed311f7ea4059
        commit_message: update requirements
        commit_url: https://api.github.com/repos/bodsch/ansible-mariadb/git/commits/6409940c0df3e5d5b4f3d212583ed311f7ea4059
        company: 
        created: 2021-12-30T08:52:07.716895Z
        download_count: 7
        forks_count: 1
        github_branch: main
        github_repo: ansible-mariadb
        github_user: bodsch
        id: 57397
        imported: 2022-04-08T00:31:35.548766-04:00
        is_valid: True
        issue_tracker_url: https://github.com/bodsch/ansible-mariadb/issues
        license: Apache
        min_ansible_version: 2.9
        modified: 2022-04-08T04:31:35.553964Z
        open_issues_count: 1
        path: ('/home/dschier/.ansible/roles', '/usr/share/ansible/roles', '/etc/ansible/roles')
        role_type: ANS
        stargazers_count: 1
        travis_status_url: 

Searching the Ansible Galaxy in the browser even easier and provides more details at a glance.

Screenshot - Ansible Galaxy

Projects / Repositories

Some projects and developers are providing roles withing their install documentation, but do not provide the role on Ansible Galaxy. You can also find playbooks and more in the documentation and repositories.

Searching the web and checking the documentation is promising to find these roles and repositories. Even if they don't apply 100% to your use case, you might get a good idea where to start.

Install Roles

If you have found a role, you can install it in various ways. The easiest one is via Ansible Galaxy.

Ansible Galaxy

So, let's use some command line tools to install and manage Ansible Roles.

# Install a role from ansible galaxy
$ ansible-galaxy role install bodsch.mariadb

Starting galaxy role install process
- downloading role 'mariadb', owned by bodsch
- downloading role from https://github.com/bodsch/ansible-mariadb/archive/2.2.10.tar.gz
- extracting bodsch.mariadb to /home/dschier/.ansible/roles/bodsch.mariadb
- bodsch.mariadb (2.2.10) was installed successfully

Listing installed roles is possible, too.

# List all roles
$ ansible-galaxy role list

# /home/dschier/.ansible/roles
- bodsch.mariadb, 2.2.10
# /usr/share/ansible/roles
# /etc/ansible/roles

If you want to update a role, you need to install it and pass the --force argument.

# Update role
$ ansible-galaxy role install bodsch.mariadb --force

Starting galaxy role install process
- changing role bodsch.mariadb from 2.2.10 to unspecified
- downloading role 'mariadb', owned by bodsch
- downloading role from https://github.com/bodsch/ansible-mariadb/archive/2.2.10.tar.gz
- extracting bodsch.mariadb to /home/dschier/.ansible/roles/bodsch.mariadb
- bodsch.mariadb (2.2.10) was installed successfully

Removing a role can be done with the below command.

# Remove role
$ ansible-galaxy role remove bodsch.mariadb

- successfully removed bodsch.mariadb

Download

In addition to the installation via Ansible Galaxy, you can just download a role. So, if you found something online, you can copy or clone it, and you are good to go.

There are three major locations where you need to download a role to.

  • /etc/ansible/roles is the global roles path for all users
  • ~/.ansible/roles is the user's roles path
  • roles/ to provide roles next to a playbook

If your project structure looks something like the below, you can create a subdirectory and put your downloaded role there.

- Project/
  |- playbook.yml
  |- inventory.yml
  |- requirements.yml
  |- roles/
      |- DOWNLOADED_ROLE/
      |- MYOWN_ROLE/

Afterwards, you can use the roles as if they are installed via Ansible Galaxy.

Requirements.yml

It may happen, that you want to share your repository and also provide a way to install the required roles. You can either document the installation in a step-by-step instructions, or you can maintain a requirements.yml file.

A requirements.yml can contain roles from Ansible Galaxy or other sources. The below example should demonstrate this.

---
roles:
  # from galaxy
  - src: yatesr.timezone

  # from github
  - src: https://github.com/bennojoy/nginx

  # from a webserver, where the role is packaged in a tar.gz
  - src: https://some.webserver.example.com/files/master.tar.gz
    name: http-role

Afterwards, you can install all roles from this file with a single command.

# Install roles from requirements.yml
$ ansible-galaxy role install -r requirements.yml

If you want to know more about this functionality, you can head over to the upstream documentation.

Use Roles

Installing roles was a piece of cake. Now I want to have a look at using roles in a playbook. The below examples are a simplified variant of the upstream documentation about roles.

Roles Statement

The roles statement was already shown in the "Ansible - Playbooks" article. It was the standard way to use roles in the past and is really easy to use.

- hosts: "all"

  roles:
  
    - role: "examplerole"
  
  tasks:
  
    - name: "Sometask"
      ...

In this example, all roles will be used before any task will be executed. Since this variant is not as flexible as the others, it is not very widely used.

Include Roles Task

The include_role module allows to dynamically include roles. The role will be parsed at runtime of the playbook. It is very often used to loop over a set of variables or a list.

- hosts: "all"

  tasks:

    - ansible.builtin.debug:
        msg: "this task runs before the example role"

    - name: "Include the example role"
      ansible.builtin.include_role:
        name: "examplerole"
      loop: "{{ somevariable }}"

    - ansible.builtin.debug:
        msg: "this task runs after the example role"

The benefit here is, that the role can be used as a task and will be executed before and after other tasks.

Import Roles Task

Another option to use roles alongside tasks is the import_role module. This will statically import a role during parsing of the playbook. You can think of "replacing import_role with all tasks from the imported role".

---
- hosts: "all"

  tasks:

    - ansible.builtin.debug:
        msg: "before we run our role"

    - name: "Import the example role"
      ansible.builtin.import_role:
        name: "examplerole"

    - ansible.builtin.debug:
        msg: "after we ran our role"

The major difference between include and import is, that one is included at runtime, the other at parsing time. This does not sound like a lot, but introduces some different behavior as explained here.

There is so much more to learn about the usage of roles. Below, you can find a couple of useful links.

Re-using Ansible artifacts — Ansible Documentation
Roles — Ansible Documentation
A brief introduction to Ansible roles for Linux system administration
In this part one of two articles, learn to use rhel-system-roles with your Ansible deployment to better manage functionality such as network, firewall, SELinux, and more on your Red Hat Enterprise Linux servers.
Home | Linux System Roles
Welcome to the Linux System Roles project homepage!

Conclusion

This was only the first part of two. Using roles seems a nice idea, but developing roles is even more useful and will be part of the next article.

Furthermore, I will address Ansible Collections, in the article afterwards, which will bring some cool advancements, too.

For now, how do you use roles? Which roles do you recommend? Is there a role you developed?