Ansible Roles¶
See roles in Ansible.
Roles are used to organize and reuse playbook content.
Roles are essentially a collection of tasks and their associated resources (variables,
templates, handlers, etc.) packaged together for a specific purpose.
The purpose can be something like configuring a web server or setting up a database.
They're somewhat similar to classes in object-oriented programming.
Table of Contents¶
Role Directory Structure¶
A role has a predefined structure with specific directories for different types of content.
This is what a typical role looks like:
roles/
└── myrole/
├── tasks/ # Contains the main list of tasks to execute
│ └── main.yml # Entry point for tasks
├── handlers/ # Contains handlers (triggered by tasks)
│ └── main.yml
├── templates/ # Contains Jinja2 template files
├── files/ # Contains static files to copy to remote machines
├── vars/ # Contains variable definitions (static)
│ └── main.yml
├── defaults/ # Contains default variable definitions (can be overridden)
│ └── main.yml
├── meta/ # Contains metadata about the role (dependencies, etc.)
│ └── main.yml
└── tasks/main.yml # Main entry point for the role
tasks/: Where you define the main tasks for the role.handlers/: Define handlers that are triggered bynotifydirective intasks.templates/: StoreJinja2templates for dynamically generating files.files/: Store static files that can be copied to remote hosts.vars/: Define variables that are specific to the role.defaults/: Define default values for variables (lowest precedence).meta/: Include metadata about the role (like depenencies).
Creating and Using a Role¶
Creating a Role¶
You can manually create the directory structure.
You can also use the ansible-galaxy command:
myrole under the
roles directory.
Defining Role Tasks¶
The file roles/myrole/tasks/main.yml is used to define tasks for the role.
- name: Install NGINX
apt:
name: nginx
state: present
update_cache: yes
- name: Enxure NGINX is started
service:
name: nginx
state: started
enabled: yes
Using a Role in a Playbook¶
Use the name of the role in a playbook using the roles key.
myrole role.This runs the tasks and resources defined in the role (
roles/myrole).
NOTE: If you have a playbook that you're inheriting roles in (as above), any tasks in that playbook will always happen after roles are executed.
If you need tasks to happen before roles, usepre_tasksinstead oftasks.
Where you can Use Roles¶
-
Playbooks
-
Role dependencies
- Roles can depend on other roles. Define dependencies in
roles/myrole/meta/main.yml
- Roles can depend on other roles. Define dependencies in
-
In the
include_roletask. You can include roles dynamically in a task.
-
In collections. Roles can be part of an Ansible collection.
- This can make them easy to distribute and reuse.
Example of Using a Role in Ansible¶
Directory Structure¶
This is the directory structure for the example:
myproject/
├── roles/
│ └── nginx/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── templates/
│ │ └── nginx.conf.j2
│ ├── files/
│ ├── vars/
│ │ └── main.yml
│ ├── defaults/
│ │ └── main.yml
│ ├── meta/
│ │ └── main.yml
├── inventory
└── site.yml
Playbook: site.yml¶
-Indicates the start of the play.- This will inherit and run all the
tasksin thenginxrole. - All tasks will be run on the
webservershosts defined in theinventory.yml
Role tasks: roles/nginx/tasks/main.yml¶
- name: Install NGINX
apt:
name: nginx
state: present
- name: Deploy NGINX configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: 0644
- name: Start and Enable NGINX
service:
name: nginx
state: started
enabled: yes
Basic Role Usage¶
-
Create a directory called
roles:
-
Then initialize a role:
Then a bunch of directories are created.
This can be overwhelming at first but if you just need to run tasks then you only need look at thetasksdirectory. -
Look in the
<role_name>/tasks/directory for a file calledmain.yml.
Put any tasks you want to run in that file. -
Then, in your playbook:
All the tasks in thatmain.ymlfile should be run.
If you need to use variables, templates, etc., there are other directories where you put those (like <role_name>/vars for variables).
Using Variables to Assign Roles Dynamically¶
If you want to assign roles dynamically based on host variables, you can do:
Then, in your inventory:
[web_servers]
web1 ansible_host=192.168.1.10 assigned_roles=["webserver_role"]
web2 ansible_host=192.168.1.11 assigned_roles=["webserver_role"]
[db_servers]
db1 ansible_host=192.168.1.20 assigned_roles=["database_role"]
db2 ansible_host=192.168.1.21 assigned_roles=["database_role"]
- The
assigned_rolesvariable will be used to determine which roles to run on each given host.
Variables with Roles¶
Specify variables to use inside roles in the role-name/vars/main.yml file.
When defining variables inside a role (roles/role_name/vars/main.yml), those
variables will only be available inside the role itself. They will not be
accesible in a playbook that calls that roll.
If you need to access variables inside the main playbook, use set_fact or define
the variable in either the inventory, the playbook vars section, or a role default.
Example vars/main.yml:
These vars will then be available anywhere inside the role role-name:
tasks/handlers/templates/files/meta/
Conditionally Calling Roles¶
You can set up conditions for roles in playbooks.
To do this, you specify a dictionary inline in the roles section.
role4.The
role4 role will only be run when the variable myvar is true. We're using
a jinja2 filter to make it default to false if it's not defined.
Alternatively, use YAML syntax:
These are functionally equivalent. The YAML syntax is more in line with traditional Ansible.Running Roles Multiple Times¶
By default, Ansible only allows you to execute roles a single time per play.
This is a safeguard to prevent duplication.
If a role is needed to run multiple times, there are a few ways to enable that behavior.
-
Set the
allow_duplicatesvalue in the role'smeta/main.ymlfile.- This will allow the role to be executed multiple times within the same play.
-
Another way is to pass in different parameters to the role on each invocation.
This will also allow the role to be executed multiple times.
Needing a role to run multiple times is a case that can happen when trying to run a role against localhost without localhost being part of the inventory or target group of the play.
For example, if a nodejs_setup role needs to be run on the Ansible control
node for building purposes, as well as the remote host that the Node
application will be running on, but localhost not in the inventory.
- name: Install nodejs on both servers
hosts: all
gather_facts: true
become: true
roles:
- role: nodejs_setup
delegate_to: localhost
vars:
hosttype: local
- role: nodejs_setup
vars:
hosttype: remote
Here, simply setting the hosttype var to a different value will allow
multiple executions. This variable can be anything, and isn't required to
actually be used in the role itself, it only needs to be specified on
invocation when trying to run multiple times.