sudo subscription-manager refresh
sudo subscription-manager repos --list | grep ansible
RHEL System Roles, announced with the launch of RHEL 8, are a collection of Ansible roles and modules that provide a stable and consistent configuration interface for remote management of Red Hat Enterprise Linux. They address many commmon configuration, security and workload uses on RHEL systems. These roles can manage systems running RHEL 7 and above, easing management of 3 generations of RHEL. The effort is based on development of the Linux System Roles project (link: https://linux-system-roles.github.io/upstream). These roles are fully supported by Red Hat, so make use of them and avoid duplication of effort in your automation endeavors.
There are a number of roles available, including:
selinux
ssh & sshd
crypto_policy
kdump (kernel crash dump)
network
vpn
timesync
logging
storage
postfix
ha_cluster
The full list and compatibility matrix can be found here: Red Hat Enterprise Linux (RHEL) System Roles
For further information on Ansible, see the Ansible Quick-Start Guide for Sysadmins (https://www.redhat.com/en/blog/system-administrators-guide-getting-started-ansible-fast) or Quick Start Video (https://www.ansible.com/resources/videos/quick-start-video) for help learning how to use Ansible.
We need to install two packages RPM packages to use system roles: ansible
and rhel-system-roles
. Use subscription-manager to list the Ansible Engine repositories available. Note that the generic "2" repository will always provide the latest release of the 2.X stream as opposed to configuring a more specific version such as 2.8.
sudo subscription-manager refresh
sudo subscription-manager repos --list | grep ansible
Now persistently enable the Ansible Engine repository for RHEL 8 using Red Hat Subscription Manager:
sudo subscription-manager repos --enable ansible-2-for-rhel-8-x86_64-rpms
And install the required packages:
sudo yum -y module install python36
sudo yum -y install rhel-system-roles ansible
The rhel-system-roles
package will install by default to the following locations where SUBSYSTEM
is the name of the subsystem that contains the individual role manages. Examples may include network, timesync, or other subsystems as they become supported. Each subsystem role will include a README file which documents how to use the role and supported parameter values, as well as the matching README in the linux-system-roles Ansible Galaxy landing space (link: https://galaxy.ansible.com/linux-system-roles/network)
/usr/share/doc/rhel-system-roles/SUBSYSTEM/
/usr/share/ansible/roles/rhel-system-roles.SUBSYSTEM/
This example assumes the following:
Generally, Ansible is not installed on every system, but rather on a single system designated as the Ansible management or control node who’s purpose is to manage other systems via Ansible.
Since we’re running Ansible on the same instance we’re changing, the target of the Ansible playbook is localhost
.
We’ve added a 2nd network interface to our test system, eth1
.
Take a look at the networking playbook that we have provided:
cat example-network-playbook.yml
--- - hosts: localhost become: yes vars: network_connections: - name: DBnic state: up type: ethernet interface_name: eth1 autoconnect: yes ip: dhcp4: no auto6: no address: - "10.10.10.{{ 254 | random( start=2) }}/24" roles: - role: rhel-system-roles.network
As you can probably tell, this playbook creates a network interface called DBnic
, with an IPv4 address of 10.10.10.<something>
, and brings it up. This is just a simple example of what can be done with the system network role.
Now let’s test access to our localhost
using the Ansible ad-hoc command:
ansible localhost -m ping
localhost | SUCCESS => { "changed": false, "ping": "pong" }
Query the Ansible Facts for this system to see the network configuration:
ansible localhost -m setup -a 'gather_subset=network filter=ansible_interfaces'
localhost | SUCCESS => { "ansible_facts": { "ansible_interfaces": [ "lo", "eth1", "eth0" ] }, "changed": false }
Examine the current configuration of eth1
using the ip
and nmcli
commands:
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000 link/ether 06:62:b5:81:e3:65 brd ff:ff:ff:ff:ff:ff inet 10.10.0.63/24 brd 10.10.0.255 scope global dynamic noprefixroute eth0 valid_lft 2055sec preferred_lft 2055sec inet6 fe80::462:b5ff:fe81:e365/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000 link/ether 06:7d:2c:e9:2f:01 brd ff:ff:ff:ff:ff:ff inet 10.10.0.135/24 brd 10.10.0.255 scope global dynamic noprefixroute eth1 valid_lft 3588sec preferred_lft 3588sec inet6 fe80::6cb5:e657:5c52:e6d1/64 scope link noprefixroute valid_lft forever preferred_lft forever
nmcli con
NAME UUID TYPE DEVICE System eth0 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03 ethernet eth0 Wired connection 1 9738a5c6-39dd-3515-aa1c-895f763851a6 ethernet eth1 ens3 50e9a523-3280-4238-a07b-dbfd7d335273 ethernet --
Now let’s run our playbook to create a new connection profile called DBnic, turn off DHCP, and assign a static ip address:
ansible-playbook --extra-vars "ansible_python_interpreter=/usr/bin/python3.6" example-network-playbook.yml
Starting in RHEL 8.7, Python 3.9 is the default Python3 interpreter. |
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [localhost] ****************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************ ok: [localhost] TASK [rhel-system-roles.network : Check which services are running] *************************************************** ok: [localhost] TASK [rhel-system-roles.network : Check which packages are installed] ************************************************* ok: [localhost] TASK [rhel-system-roles.network : Print network provider] ************************************************************* ok: [localhost] => { "msg": "Using network provider: nm" } TASK [rhel-system-roles.network : Install packages] ******************************************************************* skipping: [localhost] TASK [rhel-system-roles.network : Enable and start NetworkManager] **************************************************** ok: [localhost] TASK [rhel-system-roles.network : Enable network service] ************************************************************* skipping: [localhost] TASK [rhel-system-roles.network : Ensure initscripts network file dependency is present] ****************************** skipping: [localhost] TASK [rhel-system-roles.network : Configure networking connection profiles] ******************************************* [WARNING]: [003] <info> #0, state:up persistent_state:present, 'DBnic': connection DBnic, 3b54603b-c603-46b9-9bd9-e6fc295e7a11 already up to date [WARNING]: [004] <info> #0, state:up persistent_state:present, 'DBnic': up connection DBnic, 3b54603b-c603-46b9-9bd9-e6fc295e7a11 (not-active) changed: [localhost] TASK [rhel-system-roles.network : Re-test connectivity] *************************************************************** ok: [localhost] PLAY RECAP ************************************************************************************************************ localhost : ok=7 changed=1 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
Now let’s see how the Ansible playbook changed our network configuration:
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000 link/ether 06:62:b5:81:e3:65 brd ff:ff:ff:ff:ff:ff inet 10.10.0.63/24 brd 10.10.0.255 scope global dynamic noprefixroute eth0 valid_lft 3522sec preferred_lft 3522sec inet6 fe80::462:b5ff:fe81:e365/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 06:7d:2c:e9:2f:01 brd ff:ff:ff:ff:ff:ff inet 10.10.10.10/24 brd 10.10.10.255 scope global noprefixroute eth1 valid_lft forever preferred_lft forever inet6 fe80::2bcc:cea2:c7fb:6bba/64 scope link noprefixroute valid_lft forever preferred_lft forever
nmcli con
NAME UUID TYPE DEVICE System eth0 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03 ethernet eth0 DBnic 3b54603b-c603-46b9-9bd9-e6fc295e7a11 ethernet eth1 ens3 50e9a523-3280-4238-a07b-dbfd7d335273 ethernet -- Wired connection 1 9738a5c6-39dd-3515-aa1c-895f763851a6 ethernet --
Linux System Roles based on Ansible playbooks make it easy and consistent to enable specific services and configurations on your RHEL hosts, and across many versions. We experimented with the network system role in this exercise, but storage, kdump (kernel crash dump), selinux, and timesync are also available.
Domain |
![]() |
|
Workshop | ||
Student ID |