Ansible: From Introduction to Abandonment (Part 20)

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

Leave a Comment