Study notes for the Ansible EX407 Exam
To help you prepare, the exam objectives highlight the task areas you can expect to see covered in the exam. Red Hat reserves the right to add, modify, and remove exam objectives. Such changes will be made public in advance.
You should be able to:
- Understand core components of Ansible
- Inventories
A list of managed nodes. An inventory file is also sometimes called a “hostfile”. Your inventory can specify information like IP address for each managed node. An inventory can also organize managed nodes, creating and nesting groups for easier scaling. To learn more about inventory, see the Working with Inventory pages.
- Modules
The units of code Ansible executes. Each module has a particular use, from administering users on a specific type of database to managing VLAN interfaces on a specific type of network device. You can invoke a single module with a task, or invoke several different modules in a playbook.
- Variables
- Facts
There are other places where variables can come from, but these are a type of variable that are discovered, not set by the user. Facts are information derived from speaking with your remote systems. You can find a complete set under the ansible_facts variable, most facts are also ‘injected’ as top level variables preserving the ansible_ prefix, but some are dropped due to conflicts. This can be disabled via the INJECT_FACTS_AS_VARS setting. An example of this might be the IP address of the remote host, or what the operating system is.
Variables discovered from systems: Facts
- Plays
A play is a logical grouping of tasks. For example a play might setup your web servers, a second could update your datanase servers, a third could update a load balancer. All these plays could be contained within a single playbook.
- Playbooks
Ordered lists of tasks, saved so you can run those tasks in that order repeatedly. Playbooks can include variables as well as tasks. Playbooks are written in YAML and are easy to read, write, share and understand.
- Configuration files
- Install and configure an Ansible control node
Any machine with Ansible installed. You can run commands and playbooks, invoking /usr/bin/ansible or /usr/bin/ansible-playbook, from any control node. You can use any computer that has Python installed on it as a control node - laptops, shared desktops, and servers can all run Ansible. However, you cannot use a Windows machine as a control node. You can have multiple control nodes.
sudo yum install ansible
sudo pip install ansible
- Install required packages
- Create a static host inventory file
A basic inventory might look like the following
[webservers]
web1
web2
web3
[dbs]
db1
db2
[linux:children]
webservers
dbs
[loadbalancers]
lb1
lb2
- Create a configuration file
- Configure Ansible managed nodes
- Create and distribute SSH keys to managed nodes
ansibleuser@host> ssh-keygen -t rsa
ansibleuser@host> ssh-copy-id ansibleuser@server1
ansibleuser@host> ssh-copy-id ansibleuser@server2
ansibleuser@host> ssh-copy-id ansibleuser@server3
ansible all -m ping
Automate ssh-copy-id with a list of hosts Automate ssh-copy-id with a numbered hostname format
- Configure privilege escalation on managed nodes
sudo useradd ansible
sudo passwd ansible
sudo visudo
Add the following line and save the file...
ansible ALL=(ALL) NOPASSWD:ALL
This method is more secure. Follow the steps above but enter this line when in visudo...
ansible ALL=(ALL) ALL
- Validate a working configuration using ad-hoc Ansible commands
- Create simple shell scripts that run ad hoc Ansible commands
- Use both static and dynamic inventories to define groups of hosts
Working with Dynamic Inventory
- Utilize an existing dynamic inventory script
Using a dynamic inventory is very similar to a static one...
ansible -i openstack_inventory.py all -m ping
Hint: The inventory script must be set to executable!
- Create Ansible plays and playbooks
- Know how to work with commonly used Ansible modules
- Use variables to retrieve the results of running commands
Using the register keyword we can save the result of a command execution into a variable for later use.
- name: test play
hosts: all
tasks:
- shell: cat /etc/motd
register: motd_contents
- shell: echo "motd contains the word hi"
when: motd_contents.stdout.find('hi') != -1
- Use conditionals to control play execution
Some examples;
when: ansible_facts['os_family'] == "Debian"
when: ansible_hostname == "cnode1"
when: order_constraint.changed == True
when:
- ansible_hostname == "cnode1"
- ansible_play_hosts | length % 2 == 0
when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
(ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
Further examples showing how to test for cmd errors...
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result is failed
# In older versions of ansible use ``success``, now both are valid but succeeded uses the correct tense.
- command: /bin/something_else
when: result is succeeded
- command: /bin/still/something_else
when: result is skipped
- Configure error handling
We can ignore failures from modules by adding the following to a task...
ignore_errors: yes
By default handlers will not be run on failed hosts. Change this in the playbook with..
force_handlers: True
Can also be set via the command-line or in the config file.
Define custom failures on tasks with...
failed_when: diff_cmd.rc == 0 or diff_cmd.rc >= 2
Or...
changed_when: False
If you want to fail the entire play if anything at all fails then include this...
any_errors_fatal: true
- Create playbooks to configure systems to a specified state
- Use Ansible modules for system administration tasks that work with:
-
Software packages and repositories yum module yum_repository module package module pip module easyinstall module
-
Services
-
Firewall rules
-
File systems
-
Storage devices
-
File content List of file modules
-
Archiving
-
Scheduled tasks
-
Security
-
Users and groups
-
- Create and use templates to create customized configuration files
The following template....
# {{ ansible_managed }}
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
# The following lines are desirable for IPv6 capable hosts.
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# Network nodes as generated through Ansible.
{% for host in play_hosts %}
{{ hostvars[host]['ansible_eth1']['ipv4']['address'] }} {{ host }}
{% endfor %}
Will produce something like this...
# Ansible managed
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
# The following lines are desirable for IPv6 capable hosts.
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# Network nodes as generated through Ansible.
192.168.44.101 cnode1
192.168.44.102 cnode2
We installed: {% for package in packages %}{{ package }}{% if not loop.last %}, {% endif %}{% endfor %}
- Work with Ansible variables and facts
ansible localhost -m setup
- Create and work with roles
ansible-galaxy init myrole
- Download roles from an Ansible Galaxy and use them
ansible-galaxy install geerlingguy.docker
ansible-galaxy install ansible-galaxy install https://github.com/rhysmeister/role/role.tar.gz
ansible-galaxy install -r requirements.yml
# from galaxy
- src: yatesr.timezone
# from GitHub
- src: https://github.com/bennojoy/nginx
# from GitHub, overriding the name and specifying a specific tag
- src: https://github.com/bennojoy/nginx
version: master
name: nginx_role
# from a webserver, where the role is packaged in a tar.gz
- src: https://some.webserver.example.com/files/master.tar.gz
name: http-role
# from Bitbucket
- src: git+http://bitbucket.org/willthames/git-ansible-galaxy
version: v1.4
# from Bitbucket, alternative syntax and caveats
- src: http://bitbucket.org/willthames/hg-ansible-galaxy
scm: hg
# from GitLab or other git-based scm
- src: [email protected]:mygroup/ansible-base.git
scm: git
version: "0.1" # quoted, so YAML doesn't parse this as a floating-point value
- Manage parallelism
See --forks option https://docs.ansible.com/ansible/latest/cli/ansible-playbook.html#cmdoption-ansible-playbook-f
- Use Ansible Vault in playbooks to protect sensitive data
ansible-vault create variables.yml
ansible-vault edit variables.yml
ansible-vault rekey variables.yml
ansible-vault encrypt variables.yml
ansible-vault decrypt variables.yml variables2.yml
ansible-vault encrypt_string --vault-id a_password_file 'foobar' --name 'the_secret'
- Use provided documentation to look up specific information about Ansible modules and commands
ansible-doc lineinfile
ansible-doc --list
ansible-doc -s firewalld
Install pip and restview
sudo yum install python-pip
sudo pip install restview
Launch a server on the specified port. Documentation can be access here..
restview /usr/share/doc/ansible-doc-2.7.5/rst/ --listen *:33333 &
Or if you're on a desktop launch a browser
restview /usr/share/doc/ansible-doc-2.7.5/rst/ --browser
As with all Red Hat performance-based exams, configurations must persist after reboot without intervention.
- If selinux is enabled install libselinux-python before using file/copy/template modules.