Ansible Roles
Work with roles and Create roles
Using Ansible Roles
- Ready-to-use playbook-based Ansible solutions that you can easily include in your own playbooks.
- Community roles are provided through Ansible Galaxy
- Also possible to create your own roles.
- Red Hat provides RHEL System Roles.
- Roles make it possible to provide Ansible code in a reusable way.
- You can easily define a specific task in a role, and after defining it in a role, you can easily redistribute that and ensure that tasks are handled the same way, no matter where they are executed.
- Roles can be custom-made for specific environments, or default roles provided from Ansible Galaxy can be used.
Understanding Ansible Roles
- work with include files.
- All the different components that you may use in a playbook are used in roles and stored in separate directories.
- While defining the role, you don’t need to tell the role that it should look in some of these specific directories; it does that automatically.
- The only thing you need to do is tell your Ansible playbook that it should include a role.
- Different components of the role are stored in different subdirectories.
Roles Sample Directory Structure:
[ansible@control roles]$ tree testrole/
testrole/
|-- defaults
| `-- main.yml
|-- files
|-- handlers
| `-- main.yml
|-- meta
| `-- main.yml
|-- README.md
|-- tasks
| `-- main.yml
|-- templates
|-- tests
| |-- inventory
| `-- test.yml
`-- vars
`-- main.ymlRole Directory Structure defaults
-
Default variables that may be overwritten by other variables files
-
Static files that are needed by role tasks handlers
-
Handlers for use in this role meta
-
metadata, such as dependencies, plus license and maintainer information tasks
-
Role task definitions templates
-
Jinja2 templates tests
-
Optional inventory and a test.yml file to test the role vars
-
Variables that are not meant to be overwritten
-
Most of the role directories have a main.yml file.
-
This is the entry-point YAML file that is used to define components in the role.
Understanding Role Location
Roles can be stored in different locations:
./roles
- store roles in the current project directory.
- highest precedence.
~/.ansible/roles
- exists in the current user home directory and makes the role available to the current user only.
- second-highest precedence.
/etc/ansible/roles
- Where roles are stored to make them accessible to any user.
/usr/share/ansible/roles
- Where roles are stored after they are installed from RPM files.
- lowest precedence
- should not be used for storing custom-made roles.
ansible-galaxy init { newrolename }
- create a custom role
- creates the default role directory structure with a main.yml file
- includes sample files
Using Roles from Playbooks
- Call roles in a playbook the same way you call a task
- Roles are included as a list.
---
- name: include some roles
roles:
- role1
- role2- Roles are executed before the tasks.
- In specific cases you might have to execute tasks before the roles. To do so, you can specify these tasks in a pre_tasks section.
- Also, it’s possible to use the post_tasks section to include tasks that will be executed after the roles, but also after tasks specified in the playbook as well as the handlers they call.
Creating Custom Roles
- Use
mkdir rolesto create a roles subdirectory in the current directory, and usecd rolesto get into that subdirectory. - Use
ansible-galaxy init motdto create the motd role structure. - Add contents to motd/tasks/main.yml
- Add contents to motd/templates/motd.j2
- Add contents to motd/defaults/main.yml
- Add contents to motd/meta/main.yml
- Create the playbook exercise91.yaml to run the role
- Run the playbook by using
ansible-playbook exercise91.yaml - Verify that modifications have been applied correctly by using the ad hoc command
ansible ansible2 -a "cat /etc/motd"
Sample role all under roles/motd/:
defaults/main.yml
---
# defaults file for motd
system_manager: anna@example.commeta/main.yml
galaxy_info:
author: Sander van V
description: your description
company: your company (optional)
license: license (GPLv2, CC-BY, etc)
min_ansible_version: 2.5tasks/main.yml
---
tasks file for motd
- name: copy motd file
template:
src: templates/motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0444templates/motd.j2
Welcome to {{ ansible_hostname }}
This file was created on {{ ansible_date_time.date }}
Disconnect if you have no business being here
Contact {{ system_manager }} if anything is wrongPlaybook motd.yml:
---
- name: use the motd role playbook
hosts: ansible2
roles:
- role: motd
system_manager: bob@example.comhandlers/main.yml example:
---
# handlers file for base-config
- name: source profile
command: source /etc/profile
- name: source bash
command: source /etc/bash.bashrc Managing Role Dependencies
- Roles may use other roles as a dependency.
- You can put role dependencies in meta/main.yml
- Dependent roles are always executed before the roles that depend on them.
- Dependent roles are executed once.
- When two roles that are used in a playbook call the same dependency, the dependent role is executed once only.
- When calling dependent roles, it is possible to pass variables to the dependent role.
- You can define a when statement to ensure that the dependent role is executed only in specific situations.
Defining dependencies in meta/main.yml
dependencies:
- role: apache
port: 8080
- role: mariabd
when: environment == ’production’Understanding File Organization Best Practices
-
Working with roles splits the contents of the role off the tasks that are run through the playbook.
-
Splitting files to store them in a location that makes sense is common in Ansible
-
When you’re working with Ansible, it’s a good idea to work with project directories in bigger environments.
-
Working with project directories makes it easier to delegate tasks and have the right people responsible for the right things.
-
Each project directory may have its own ansible.cfg file, inventory file, and playbooks.
-
If the project grows bigger, variable files and other include files may be used, and they are normally stored in subdirectories.
-
At the top-level directory, create the main playbook from which other playbooks are included. The suggested name for the main playbook is site.yml.
-
Use group_vars/ and host_vars/ to set host-related variables and do not define them in inventory.
-
Consider using different inventory files to differentiate between production and staging phases.
-
Use roles to standardize common tasks.
When you are working with roles, some additional recommendations apply:
-
Use a version control repository to maintain roles in a consistent way. Git is commonly used for this purpose.
-
Sensitive information should never be included in roles. Use Ansible Vault to store sensitive information in an encrypted way.
-
Use
ansible-galaxy initto create the role base structure. Remove files and directories you don’t use. -
Don’t forget to provide additional information in the role’s README.md and meta/main.yml files.
-
Keep roles focused on a specific function. It is better to use multiple roles to perform multiple tasks.
-
Try to develop roles in a generic way, such that they can be used for multiple purposes.
Lab 9-1
Create a playbook that starts the Nginx web server on ansible1, according to the following requirements: • A requirements file must be used to install the Nginx web server. Do NOT use the latest version of the Galaxy role, but instead use the version before that. • The same requirements file must also be used to install the latest version of postgresql. • The playbook needs to ensure that neither httpd nor mysql is currently installed.
Lab 9-2
Use the RHEL SELinux System Role to manage SELinux properties according to the following requirements:
• A Boolean is set to allow SELinux relabeling to be automated using
cron.
• The directory /var/ftp/uploads is created, permissions are set to 777,
and the context label is set to public_content_rw_t.
• SELinux should allow web servers to use port 82 instead of port 80.
• SELinux is in enforcing state.
Subjects:
ansible-playbook timesync.yaml to run the playbook. Observe its output. Notice that some messages in red are shown, but these can safely be ignored.
5. Use ansible ansible2 -a "timedatectl show" and notice that the timezone variable is set to UTC.
Lab 9-1
Create a playbook that starts the Nginx web server on ansible1, according to the following requirements:
• A requirements file must be used to install the Nginx web server. Do NOT use the latest version of the Galaxy role, but instead use the version before that.
• The same requirements file must also be used to install the latest version of postgresql.
ansible-galaxy install -r roles/requirements.yml
cat roles/requirements.yml
- src: geerlingguy.nginx
version: "3.1.4"
- src: geerlingguy.postgresql• The playbook needs to ensure that neither httpd nor mysql is currently installed.
---
- name: ensure conflicting packages are not installed
hosts: web1
tasks:
- name: remove packages
yum:
name:
- mysql
- httpd
state: absent
- name: nginx web server
hosts: web1
roles:
- geerlingguy.nginx
- geerlingguy.postgresql(Had to add a variable file for redhat 10 into the role. )
Lab 9-2
Use the RHEL SELinux System Role to manage SELinux properties according to the following requirements:
• A Boolean is set to allow SELinux relabeling to be automated using cron. • The directory /var/ftp/uploads is created, permissions are set to 777, and the context label is set to public_content_rw_t. • SELinux should allow web servers to use port 82 instead of port 80. • SELinux is in enforcing state.
vim lab92.yml
---
- name: manage ftp selinux properties
hosts: ftp1
vars:
selinux_booleans:
- name: cron_can_relabel
state: true
persistent: true
selinux_state: enforcing
selinux_ports:
- ports: 82
proto: tcp
setype: http_port_t
state: present
local: true
tasks:
- name: create /var/ftp/uploads/
file:
path: /var/ftp/uploads
state: directory
mode: 777
- name: set selinux context
sefcontext:
target: '/var/ftp/uploads(/.*)?'
setype: public_content_rw_t
ftype: d
state: present
notify: run restorecon
- name: Execute the role and reboot in a rescue block
block:
- name: Include selinux role
include_role:
name: rhel-system-roles.selinux
rescue:
- name: >-
Fail if failed for a different reason than selinux_reboot_required
fail:
msg: "role failed"
when: not selinux_reboot_required
- name: Restart managed host
reboot:
- name: Wait for managed host to come back
wait_for_connection:
delay: 10
timeout: 300
- name: Reapply the role
include_role:
name: rhel-system-roles.selinux
handlers:
- name: run restorecon
command: restorecon -v /var/ftp/uploads