updated: 7th of April 2019
published: 17th of August 2017
Ansible is a 'radically simple', open source, IT automation platform.
Control Node
The Ansible control node is the central point of management for managed nodes. Configuration
is pushed to the managed nodes from the control node.
Managed Node
A managed node is a device that will be configured by an ansible control node. Ansible
supports many types of operating systems including network operating systems from Juniper
and linux distributions such as RedHat.
Playbook
A playbook is a list of 'plays' that will be executed on the managed nodes. Plays are a list
tasks that will be performed such as a yum update or copying a file.
Inventory
The inventory is a list of managed nodes that playbooks will be run against. Managed nodes in
the inventory can be combined into groups, for example; Sydney and Melbourne.
Requirements
Linux managed nodes require python 2.4 or later. If the python version is less than 2.5
python-simplejson is required.
Control Node
The Control node requires python 2.4 or later. Ansible is only required to be installed
on the control node. Neither ansible or any agents are required on the managed nodes.
Python
Ansible can be installed via pip, python 3 support is in beta as of Ansible version 2.2.
I prefer to install ansible within a
virtual environment.
mkdir ~/envs
virtualenv ~/envs/ansible-env
source ~/envs/ansible-env/bin/activate
pip install ansible
Yum
RPM's are available in the EPEL release
for Yum based systems such as RedHat and Centos.
Apt
Apt based systems such as Ubuntu and Debian can install via a
PPA.
More details can be found in the ansible installation documentation.
Ansible configuration can be defined in multiple locations. The following search paths will be checked for an ansible.cfg file from highest to lowest preference.
When a playbook is run the first file found will be the configuration that is used, configuration files will not be merged. The ansible.cfg file uses the .ini format. Sections are defined with square brackets [defaults]. Variables are defined like so inventory=/etc/ansible/hosts.
The ansible configuration documentation has details regarding all configuration options.
Ansible inventory files define managed nodes that playbooks can be run against. Inventories can be statically created or dynamically built from another inventory system such as CMDB.
Static Inventory
Static inventory files are similar to .ini file format. There are three types
of host definitions.
Example static inventory
test.lab.local
[sydney]
host1.lab.sydney
host2.lab.sydney
[melbourne]
host1.lab.melbourne
host2.lab.melbourne
[australia:children]
sydney
melbourne
Dynamic Inventory
A dynamic inventory script can be written in any language as long as it returns valid JSON.
The script must support two arguments: --list and --host and
must be executable.
The --list argument must return a key/value pair of group to host mappings.
[user@control-node ~]$ ./inventoryscript --list
{
"sydney" : [ "host1.lab.sydney", "host2.lab.sydney" ],
"melbourne" : [ "host1.lab.melbourne", "host2.lab.melbourne" ]
}
The --host argument must return a key/value pair of host to variable mappings or an empty dictionary.
[user@control-node ~]$ ./inventoryscript --host host1.lab.sydney
{
"ntp_server" : "ntp.lab.sydney",
"syslog_server" : "syslog.lab.sydney"
}
Inventory Usage
The inventory that will be used can be defined in the following two ways from highest to
lowest preference.
Multiple inventory files can be used if the parameter used with the -i argument or the inventory variable defined in the ansible.cfg file is a directory.
If using a directory the files will be read in alphabetical order. The order of files is important if a group of groups in one file refers to a group in another file.
See the ansible inventory documentation for more details.
Playbooks can describe a desired configuration state and/or the steps to implement change on a managed host.
A playbook defines a list of 'plays' that will be executed against managed nodes. Each play contains one or more tasks which will be executed against the defined hosts group. Task utilise modules to perform the actions on the managed nodes.
Playbooks are writen in YAML which is an easy to read and write key/value data serialization language.
Playbooks have four sections
Example Playbook
---
- hosts: sydney
vars:
ssh_port: 22
tasks:
- name: ensure openssh is at the latest version
yum: name=openssh-server state=latest
- name: write the openssh config file
template: src=~/playbooks/templates/sshd.j2 dest=/etc/ssh/sshd_config
notify:
- restart sshd
handlers:
- name: restart sshd
service: name=sshd state=restarted
Find out more about ansible playbooks in the official documentation.
Modules are where the magic happens in ansible. Modules are invoked with tasks in playbooks or with the ansible ad hoc command -m argument.
There are three types of modules in ansible.
Example yum module usage in playbook
tasks:
- name: ensure openssh is at the latest version
yum: name=openssh-server state=latest
When utilizing the ansible ad hoc command the -m module_name [-a module_args] i used to specify a module. Note the [-a module_args] is an optional parameter.
The setup module which is used to collect facts about a device is automatically run on hosts during playbook execution.
Refer to the ansible modules documention for more details.
Variables are technique for managing dynamic values throughout your code. Ansible variable names must start with a letter and only contain letters, numbers or underscores.
Variables in ansible have three scopes
Variable Precedence
If a variable with the same name is defined in multiple places, the variable with the higher
precedence will be used.
From ansible 2.x the variable precedence is as follows from most to least preferred
More on variable precedence can be found in the official documentation.
Facts
When a playbook is run against a host, there is an implicit module named the setup
module that gathers facts about a device. Fact gathering can be disabled by setting the
gather_facts: false argument.
Example facts variables
"ansible_all_ipv4_addresses": [
"REDACTED IP ADDRESS"
],
"ansible_all_ipv6_addresses": [
"REDACTED IPV6 ADDRESS"
],
...
long list of values
...
"ansible_virtualization_role": "guest",
"ansible_virtualization_type": "VMware"
Variable Usage
Depending on where a variable is being defined determines the format to set the variable.
Below are some examples of how to define a variable.
When a variable is defined in a playbook with the {{ ... }} syntax and it starts an argument, it must be enclosed in quotes. For example: template: src='{{ base_path }}/motd.j2'
More information regarding variables can be found in the documentation.
Templates in ansible utilize the Jinja2 template language. Templates allow for the re-use of files in a DRY (dont repeat yourself) fashion. For example a template can be written for a MOTD banner that has variables that will be substituted for the inventory hostname.
Jinja2 templates are basically text files that have control structures and variables that get manipulated by the templating engine on rendering. By convention jinja2 files should end with a .j2 extension, but this is not required.
Delimiters
Example template
This is a MOTD file for {{ inventory_hostname }}
{% if ansible_all_ipv4_addresses %}
{% for ip in ansible_all_ipv4_addresses %}
{{ ip }}
{% endfor %}
{% endif %}
Example template usage in playbook
tasks:
- template: src=templates/motd.j2
dest=/etc/motd
owner=root
group=root
mode="0600"
See the official Jinja2 docs for the full gamut of options available. More about the template module can be found in the official ansible docs.
Ansible roles allow for the abstraction of tasks, making them more portable and re-usable. Rather than having a playbook that builds out a web app, you could seperate the tasks into roles, for example, a role to install and configure the database, another role to install and configure the web server. You could then potentially use these roles to build out any kind of application.
Roles can be uploaded to ansible galaxy and shared with the community. To create a role there is a nice helper command anisble-galaxy init role_name which will build out the directory structure required for a role.
Example Role Directory Structure
roles/example_role/
|-- README.md
|-- defaults
| `-- main.yml
|-- files
|-- handlers
| `-- main.yml
|-- meta
| `-- main.yml
|-- tasks
| `-- main.yml
|-- templates
|-- tests
| |-- inventory
| `-- test.yml
`-- vars
`-- main.yml
3rd party modules can be uploaded to ansible galaxy for re-use by others. Ansible galaxy roles are tied to a github account. Starting at ansible version 1.8 it is possible to use git sources other than ansible galaxy.
ansible-galaxy command line toolThe ansible-galaxy args cli command can be used to search, list, initialize, install and remove ansbile roles.
ansible-galaxy --help
Usage: ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...
ansible-galaxy search junos
Found 2 roles matching your search:
Name Description
---- -----------
Juniper.junos Network build automation of Junos devices.
reloadzhang.junos-stdlib Network build automation of Junos devices.
A comprehensive guide to getting started with ansible galay can be found at the ansible galaxy about page.
Ansible provides a 'vault' to securely stores secrets. The ansible-vault args command is used to create, edit, encrypt and decrypt vault files. Ansible uses a python library to symetrically encrypt a file with AES 256 bit encryption using a password as the key. The default editor for ansible vault is vi, this can be changed by exporting the $EDITOR environment variable. Ansible vault files use YAML syntax for key:value pairs.
ansible-vault command line toolansible-vault --help
Usage: ansible-vault [create|decrypt|edit|encrypt|rekey|view] [--help] [options] vaultfile.yml
It is recommended to name the ansible vault file vault and store it under the group_vars/ directory. Vault variable names should be prefixed withvault_.
Access ansible-vaultThere are three methods to tell ansible to access the vault during playbook execution:
More on ansible vault can be found in the official docs.
Ansible tower provides a nice web interface for controlling ansible managed nodes with enterprise features.
Anisble tower is build on a Django web stack with a postgres backend. An ansible playbook is used to install ansible tower after an initial wizard is used to define the configuration variables.
InstallationThere are three installation methods for ansible tower
More on ansible tower can be found in the official documentation.