Ansible Roles
Ansible Role is a collection of playbooks. For example, combining the playbook for configuring nginx, the playbook for configuring php, and the playbook for configuring mysql can create a role for configuring lnmp.
There are three common types of roles:
- • The roles that come with RHEL, which can be installed via
<span>yum install rhel-system-roles</span>. - • Roles downloaded from the role repository at https://galaxy.ansible.com/ui/
- • Red Hat also offers paid roles, which I have not used.
The system roles that come with RHEL can be found in
<span>/usr/share/ansible/roles/</span>after installation.
Using Roles
Roles are used through Playbooks. Below is a Playbook that uses roles:
---
- name: use roles
hosts: servera
roles:
- role1
- role2
This Playbook indicates the invocation of <span>role1</span> and <span>role2</span>.
The priority of roles is higher than that of <span>tasks</span>. For example:
---
- name: use roles
hosts: servera
tasks:
- name: debug
ansible.builtin.debug:
msg: "Hello World!"
roles:
- role1
- role2
In this YAML, the <span>tasks</span> section appears before <span>roles</span>, but <span>roles</span> will be executed before <span>tasks</span>.
Creating a Custom Role and Using It
Initializing a Role
A role can be initialized using <span>ansible-galaxy role init</span>.
[root@awx-1 ansible]# ansible-galaxy role init roles/test-role
- Role roles/test-role was created successfully
[root@awx-1 ansible]# ls roles
test-role
[root@awx-1 ansible]# tree roles/test-role/
roles/test-role/
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
8 directories, 8 files
- • defaults
- • Function: Stores default variables (lowest priority).
- • Files: Usually contains a
<span>main.yml</span>file. - • Usage Scenario: Defines some default variable values that can be overridden.
- • vars
- • Function: Defines variables used internally by the role (higher priority than
<span>defaults</span>). - • Files: Usually also
<span>main.yml</span>. - • Note: These variables are not easily overridden externally and are generally used for important values relied upon by the internal logic of the role.
- • files
- • Function: Stores static files to be distributed to target hosts via the
<span>copy</span>or<span>script</span>modules. - • templates
- • Function: Stores Jinja2 template files (usually ending with
<span>.j2</span>). - • Purpose: Dynamically generates configuration files, rendered using variables.
- • Used with Module: Used with the
<span>template</span>module. - • tasks
- • Function: Defines the main tasks of the role.
- • Files: Must include
<span>main.yml</span>, and can include other task files via<span>include</span>. - • Usage: The role execution starts from
<span>tasks/main.yml</span>. - • handlers
- • Function: Defines tasks that respond to
<span>notify</span>calls, such as restarting services. - • Files: Also
<span>main.yml</span>, where you write<span>name:</span>in conjunction with<span>notify</span>. - • meta
- • Function: Defines metadata for the role, such as dependencies on other roles, authors, licenses, etc.
- • Files: Commonly is
<span>main.yml</span>. - • tests
- • Function: Used for testing the role’s use cases.
- • Usually Contains:
- •
<span>inventory</span>: Test host inventory - •
<span>test.yml</span>: Playbook for invoking the role - • README.md
- • Function: Documentation explaining the role’s purpose, variables, usage, etc.
Here is a brief summary of the functions of these directories:
| Directory | Function Overview |
<span>defaults/</span> |
Defines default variables (lowest priority, easily overridden) |
<span>vars/</span> |
Defines internal variables (higher priority, not easily overridden) |
<span>files/</span> |
Stores static files, used with <span>copy/script</span> modules |
<span>templates/</span> |
Stores Jinja2 templates, used with <span>template</span> module |
<span>tasks/</span> |
Defines the main task entry point, must have <span>main.yml</span> |
<span>handlers/</span> |
Defines handlers called by <span>notify</span> (e.g., restart services) |
<span>meta/</span> |
Defines role dependencies and metadata |
<span>tests/</span> |
Stores test playbooks and inventory |
<span>README.md</span> |
Role documentation |
Having explained these directories, let’s do a simple configuration for them.
Configuring Roles
tasks
<span>tasks</span> directory is the most important directory because it defines the tasks of the role. In <span>tasks</span>, defining tasks is somewhat different from Playbooks; <span>tasks</span> does not need to declare the managed hosts, and tasks need to be written in <span>main.yml</span>. Below is the content of a file in the <span>tasks</span> directory:
[root@awx-1 ansible]# cat roles/test-role/tasks/main.yml
---
# tasks file for roles/test-role
- name: Print the role information
ansible.builtin.debug:
msg: "{{ ROLE_INFORMATION }}"
- name: Print default address
ansible.builtin.debug:
msg: "{{ ansible_facts[DEFAULT_NETCARD].ipv4.address }}"
- name: Print hostname
ansible.builtin.debug:
var: ansible_hostname
- name: Print system version
ansible.builtin.debug:
msg: System version is {{ ansible_distribution }} {{ ansible_distribution_version }}!
- name: Set hosts
ansible.builtin.template:
src: templates/hosts.j2
dest: /etc/hosts
mode: 0644
owner: root
group: root
- name: Copy motd to master node
ansible.builtin.copy:
src: files/motd
dest: /etc/motd
mode: 0644
owner: root
group: root
when: MASTER_NODE | default('') != ''
- name: Copy motd to worker node
ansible.builtin.copy:
content: "Worker Node"
dest: /etc/motd
mode: 0644
owner: root
group: root
when: MASTER_NODE is not defined or not MASTER_NODE
- name: Set PermitRootLogin
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regex: "[(# )|#]PermitRootLogin|^PermitRootLogin"
line: "PermitRootLogin yes"
notify: restart sshd
Tasks from other files can be imported using
<span>ansible.builtin.include_task</span>and<span>ansible.builtin.import_task</span>.
handlers
[root@awx-1 ansible]# cat roles/test-role/handlers/main.yml
---
# handlers file for roles/test-role
- name: restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
listen: restart sshd
Like <span>tasks</span>, it is also written in <span>main.yml</span>.
templates
This directory is empty and requires creating files. Here, we create a <span>hosts.j2</span> file.
[root@awx-1 ansible]# cat roles/test-role/templates/hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['all'] %}
{{ hostvars[host].ansible_facts.default_ipv4.address }} {{ hostvars[host].ansible_facts.fqdn }} {{ hostvars[host].ansible_facts.hostname }}
{% endfor %}
files
Similar to <span>templates</span>, files need to be created manually.
[root@awx-1 ansible]# cat roles/test-role/files/motd
Master Node!
vars
Defines variables, which are fixed in <span>main.yml</span>.
[root@awx-1 ansible]# cat roles/test-role/vars/main.yml
---
# vars file for roles/test-role
ROLE_INFORMATION: "Test the Ansible role"
Used to define variables that do not require modification.
defaults
Defines default variables, which are fixed in <span>main.yml</span>.
[root@awx-1 ansible]# cat roles/test-role/defaults/main.yml
---
# defaults file for roles/test-role
DEFAULT_NETCARD: "eth0"
Used to define variables that need to be modified.
Here, a variable
<span>DEFAULT_NETCARD</span>is set to the network card name, used to print the network card address. The default is eth0, and if the managed server’s network card name is different, such as ens18, it can be overridden by assigning a new value to the variable elsewhere.
meta
Used to define the role’s description information, which comes with a <span>main.yml</span> file that can be modified according to the template.
tests
Used for testing; you can refer to existing files.
Invoking Roles
# Set role path
[root@awx-1 ansible]# grep roles_path ansible.cfg
roles_path=./roles
# Configure host inventory
[root@awx-1 ansible]# cat inventory
[k8s]
base-k8s-master-1 MASTER_NODE=true
base-k8s-worker-1
base-k8s-worker-2
[all:vars]
ansible_ssh_user = root
ansible_ssh_password = redhat
ansible_become = false
ROLE_INFORMATION = "test ansible inventory"
# Configure Playbook
[root@awx-1 ansible]# cat roles.yml
---
- name: Use roles
hosts: k8s
roles:
- test-role
# Execute Playbook, reassign DEFAULT_NETCARD to override default variable
[root@awx-1 ansible]# ansible-playbook -e DEFAULT_NETCARD=ens18 roles.yml