Introduction
Ansible is a server provisioning tool, written in Python, which allows you to manage several servers in an automated fashion. This makes the process of configuring and managing servers far simpler and more efficient. Moreover, it reduces the likelihood of making mistakes.
For example, Ansible can be used to:
- Install, configure and deploy software
- Configure systems (with users, packages etc)
- Perform application deployment and system updates.
There are a few key points about Ansible to understand.
- Ansible uses OpenSSH to connect to each server
- Ansible uses playbooks configured in YAML which act as code to provision the system
- Ansible uses the control and managed node architecture
This means only OpenSSH must be installed and configured on each target node (server). However, the control node must have Ansible installed.
Configuring Ansible
To use Ansible, and allow the control node to connect to each server, you'll need to set up a secure public/private key pair.
This can be done like so:ssh-keygen -t ed25519 -C "ansible-keypair"
Next, add the public key to all target nodes. This can be done using the ssh-copy-id
command.ssh-copy-id -i ~/.ssh/ansible.pub SERVERIP
Using the private key, you can now use this command to log in.ssh -i ~/.ssh/ansiblekey SERVERIP
To test that Ansible is working, you can send a ping to all servers using the ping module. This checks the connection of all servers, described in the inventory file.
The inventory file simply lists all the servers (via IP addresses or domain names that Ansible should connect to). For example:
[all-hosts]
192.168.0.11
192.168.0.12
Checking connections
We can check the remote connection using the ping module in Ansible. We specify the private key, the inventory file and which hosts to conduct the ping:ansible all --key-file ~/.ssh/ansiblekey -i inventory -m ping
However, this command is a little long. We can reduce this by creating an ansible.cfg
file within our working directory. Within this file, we can specify where our inventory file is located, add our (server list) and private SSH key file, like so:
touch ansible.cfg
# Within ansible.cfg
[defaults]
inventory = inventory
private_key_file = ~/.ssh/ansiblekey
Now we can simply use:
ansible all -m ping
We can also get a list of all the hosts:
ansible --list-hosts all
# Output
hosts (2):
192.168.56.11
192.168.56.12
Gathering facts
Before each playbook is run, Ansible will typically 'gather facts'. This simply means that Ansible is gathering information about each server. This information can be used later in playbooks.
To gather information about each server, we can use the gather-facts
module:
# For all machines
ansible all -m gather_facts
# For a particular machine
ansible IP -m gather_facts
# OR
ansible all -m gather_facts --limit IP
The --limit
option allows you to only gather information about a certain node.
Automation
Let's imagine we wanted to update the cache for all our Debian servers. Doing this manually would mean logging into each server and performing the same commands. This is simply impractical - imagine if we had hundreds of servers!
Ansible has a few package management modules, one of them is the apt
module.
For example, we can update the apt cache repository. However, this command requires sudo privileges.
To get around this, we can use the --become
& --ask-become-pass
flags.
These flags allow an unprivileged user to 'become' root; the second option simply asks for the root password.
For example, we can:
- Update the apt package cache
ansible all -m apt -a update_cache=true --become --ask-become-pass
- Install a package via the apt module
ansible all -m apt -a name=PACKAGENAME --become --ask-become-pass
- Ensure a specified package is on the latest update
ansible all -m apt -a "name=PACKAGENAME state=latest --become --ask-become-pass
- Perform an upgrade on apt systems
ansible all -m apt -a "upgrade=CHOICE" --become --ask-become-pass
Here, the-a
flags allows us to perform ad-hoc commands; simply issuing commands as you would if logged onto a Linux system. This however is not the intended way to use Ansible. This is where playbooks come in.
Playbook
Ansible uses playbooks to automate tasks. Each playbook has a play, which in turn has tasks. Multiple tasks can be run within a play.
Below is an example playbook to install apache2 on all nodes.
---
- hosts: all
become: true
tasks:
- name: update repository
apt:
update_cache: yes
when: ansible_distribution = "Ubuntu"
- name: install apache2 server
apt:
name: apache2
when ansible_distribution = "Ubuntu"
Here, we are specifying which hosts (nodes) in the inventory file to run this playbook on and whether we should 'become' root. Next are the listed tasks to conduct on each server.
We set a name for the tasks, and include the appropriate module name. In this case, apt
as we want to update the repository cache on all the Debian-based machines. We set the option update_cache
to yes
and set a conditional.
This is where gathering_facts
comes into play. Ansible will procure the distribution for each node and store it. So when this playbook is executed, we can use a conditional to determine whether or not to execute a task.
We can also add multiple distributions using a Python list in the when
condition
Let's say we had Ubuntu & Debian machines to manage (which both use apt). We can do:
- name: update repo
apt:
update_cache: yes
when: ansible_distribution in ["Debian", "Ubuntu"]
Executing playbooks
To execute a playbook, we can use the following command:
ansible-playbook
For example, to run our apache2 playbook, we can issue this command:
ansible-playbook --become --ask-become-pass apache2.yml
The name of the playbook can be any arbitrary value; however, it must be a YAML (.yml) file. If no errors occur, Ansible will gather facts and run the tasks on the machines specified within the playbook.
Conclusion
This post describes and explains very basic usage of Ansible, and how it works. Advanced usage of Ansible will be shown in further blog posts.
However, to re-iterate:
- Ansible is a server provisioning tool
- Ansible uses OpenSSH
- Ansible uses playbooks, plays and tasks to perform automated server configuration and management.
Infrastructure-as-code (IaC) provisioning tools like Terraform and Ansible allow administrators and engineers to automate mundane tasks; saving time and increasing productivity. Ansible is a great skill to have not only in a work environment, but also in a homelab setting too.