Task Automation with Ansible

Page content

Ansible provides an Open Source framework for automation. It is most well-known for managing servers and network devices, but you can use Ansible to automate almost any task.

How Ansible Works

First, set up a copy of Ansible and the required configuration files on a control machine, which can just be the workstation of an administrator.

Ansible runs tasks on either the control machine, or remote systems. Tasks are usually defined in playbooks. The tasks in a playbook are run in order, from the first task to the last. Playbooks are YAML files.

Each time that you run a task, this calls a module of code that connects to the relevant systems, and sends the appropriate commands to carry out the task. The list of available systems is known as the inventory, and individual systems are referred to as nodes.

Managing Systems with Ansible

Modules for managing UNIX-like systems connect to the target nodes with SSH and then send Python code to the nodes. The Python interpreter on each node executes the code. Both SSH and Python are installed on most Linux systems, and are part of macOS. There are also modules to execute actions with more basic methods, such as the Bash shell that is the default for both macOS and GNU/Linux distributions.

Other types of modules use the appropriate network protocols and commands for their purpose. For example, the Ansible modules for Microsoft Windows send commands to PowerShell, using the PowerShell remoting facility.

This means that you can manage almost any system with Ansible, possibly starting with tasks that use low-level modules to install the prerequisites for the more complex operations.

Ansible and API Services

Ansible modules for online services work slightly differently. These modules connect from the control machine to the relevant server or cloud, and use the API that the service provides to send commands to it.

Centralized Ansible Management

Several groups provide systems for managing your Ansible tasks and nodes in a central service. Two of these are the Red Hat Ansible Automation Platform and Ansible Semaphore.

Red Hat offer the Ansible Automation Platform for their customers. The software for this is developed as an Open Source project, called AWX. The AWX project does not provide user support or long-term maintenance for releases.

The Ansible Semaphore project provides a lightweight Web application. This offers a user interface with the essential features, but lacks integration with other services.

Setting Up a Control Machine

To set up Ansible on a macOS or Linux system, first ensure that Python 3 and the pip utility are installed. Homebrew includes pip in the python package, but some Linux distributions provide it in a separate package.

To install Ansible with pip, run this command in a terminal:

pip3 install --user ansible-core

If you use pipx to manage Python utilities, use this command to install Ansible:

pipx install ansible-core

Installing Extra Packages on the Control Machine

Some Ansible modules require additional Python packages on either the control machine or the nodes. You can use an Ansible task to install packages on nodes, but you should avoid trying to manage the Ansible installation on the control machine with Ansible itself:w .

If you installed Ansible on the control machine with pipx, use the inject subcommand to add packages. This subcommand will install the specified package into the Python virtual environment that pipx maintains for Ansible. For example, this command adds boto3 to the Ansible installation:

pipx inject ansible boto3

If you used pip to install Ansible, add the –user option to install Python packages into your home directory, rather than globally. For example, this command installs passlib into your home directory with pip:

pip install --user passlib

Ansible Configuration Files

Ansible does not require a configuration file. It does check for configuration files in several locations, so that you can customize the behavior of Ansible at the project, user or system level.

This is a simple Ansible configuration file:

[defaults]

# SSH settings
remote_user = ansibleuser
remote_port = 1234
pipelining = True

Replace ansibleuser with the name of a user account that has administrative privileges on the target systems (this means sudo for UNIX-based systems). Replace 1234 with the port number of the SSH service on the target systems.

The pipelining option significantly increases the performance of Ansible over SSH. Unfortunately, it means that commands that require root access will fail if sudo has the requiretty option enabled.

Ansible and Version Control

Store your Ansible playbooks and roles in a source code repository. Ansible files can be placed in the same repository as the other files for a project.

For convenience, you may put the Ansible playbooks in the root of your repository. You can define playbooks as single YAML files, so in some cases, you do not need to create any directories at all for Ansible code.

Always exclude *.retry files from version control. Ansible generates temporary files on the control station and the nodes, but only the retry files appear in the working directory.

If you expect to use an Ansible configuration file in the root directory of a project, consider excluding the ansible.cfg file itself from version control, and just putting an example of the expected ansible.cfg file in the repository. This enables each person that works with the repository to use their own configuration file, by copying the example file.

Use the Vault feature to encrypt any YAML file that stores password variables.

Directory Conventions for Ansible

These are standard directories for Ansible projects:

  • filter_plugins/ - Custom filter plugins
  • host_vars/ - Variables for individual host systems
  • inventory/ - Lists of nodes
  • group_vars/ - Variables for groups of systems
  • library/ - Custom Ansible modules
  • roles/ - Custom roles used by the Ansible playbooks

Using Ansible

The Ansible Tools

Ansible provides three main tools:

  • ansible-playbook - Execute an Ansible playbook on the specified systems
  • ansible - Executes an individual shell command or Ansible module on the specified systems
  • ansible-console - Provides an interactive shell for working with Ansible

You should also make use of these commands:

  • ansible-galaxy - Manages Ansible roles that are provided from shared repositories
  • ansible-vault - Encrypts and decrypts any individual YAML file that Ansible uses.

Ansible includes several other specialized tools. For example, ansible-pull configures a system to pull Ansible playbooks from a source code repository and run them on a schedule.

Specifying The Target Nodes

Use -i to specify the inventory that has the target nodes. If you do not provide an inventory, Ansible will run, as if you had specified an inventory that only contains localhost, and print a warning.

Optionally, you can also specify a pattern, to limit the targets to the nodes that are either in a particular group, or whose names match the specified pattern.

TOOL PATTERN -i INVENTORY OPTIONS

The tool will connect to each of the specified nodes and execute the required commands. If a command fails on one or more of the nodes, a retry file is created to enable you to run the commands again on only the failed nodes.

The all group is a built-in group that automatically includes all of the systems in the specified inventory.

The ansible Tool

Use the ansible command with the -a option to execute a shell command:

ansible PATTERN -i INVENTORY -a /usr/bin/uptime

Use -m to execute an Ansible module:

ansible PATTERN -i INVENTORY -m ping
ansible PATTERN -i INVENTORY -m setup

The ping module checks that Ansible can connect to the remote system. The setup module returns information about the remote system.

To specify the arguments to use with the module, add the -a option. For example, this command uses the get_url module to download the file that is specified by the url argument to the directory that is specified by the dest argument:

ansible PATTERN -i INVENTORY -m get_url -a "url='https://github.com/restic/restic/releases/download/v0.9.4/restic_0.9.4_linux_amd64.bz2' dest='/tmp'"

Use this feature to copy files between the control station and the nodes. The copy module transfers files from the control station over an SSH connection, the fetch module downloads files from the nodes to the control station, and the synchronize module uses rsync for synchronization.

This example copies the ~/Downloads/example.txt file to the nodes:

ansible PATTERN -i INVENTORY -m copy -a "src=~/Downloads/example.txt dest=/tmp/example.txt"

The ansible-playbook Tool

To run a playbook:

ansible-playbook -K -i INVENTORY MY_PLAYBOOK.YML

The -K option means that Ansible will prompt you for the password of your account on the remote system in order to use sudo.

Add –syntax-check to test the Ansible playbook without running it:

ansible-playbook --syntax-check -K -i INVENTORY MY_PLAYBOOK.YML

Add –check to simulate the effect without making changes to the target systems:

ansible-playbook --check -K -i INVENTORY MY_PLAYBOOK.YML

If the playbook requires data from a file that has been encrypted with ansible-vault, add –ask-vault-pass:

ansible-playbook --ask-vault-pass -K -i INVENTORY MY_PLAYBOOK.YML

Enter the password for the encrypted files when prompted.

Managing Microsoft Windows Systems

Ansible 2.1 and above support managing Windows systems. This means that they may communicate with Windows nodes using the WinRM and PowerShell Remoting facilities that are built-in to current versions of Windows, and also include specific modules for Windows features.

Each Windows node must meet these requirements to be managed with Ansible:

  • PowerShell 3.0 or above must be installed
  • PowerShell Remoting with WinRM must be enabled
  • The firewall must allow remote TCP connections to port 5986 (WinRM over HTTPS)

The Ansible documentation on Windows includes a PowerShell script to set up remote access for you.

A Note on Generating Passwords

You must specify the SHA512 hashed version of a user password when you set it through Ansible. By default, macOS does not generate the same hashes as Linux, so you should install the Python module passlib to provide a hash generator that behaves consistently across operating systems. To generate a valid hash with passlib enter this command in a terminal window:

python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

Enter the password that you would like to use at the prompt.

Any YAML file that stores password variables should be encrypted using the Vault feature of Ansible.

Third-Party Tools

Additional Ansible Roles

  • Ansible Lockdown - Project to maintain roles that configure systems to meet security standards
  • Linux System Roles - Project to provide a standard set of Ansible roles for configuring Linux systems

Resources