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 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.
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 pathroles/
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.
Docs & Links
There is so much more to learn about the usage of roles. Below, you can find a couple of useful links.
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?