This tutorial is a basic view into the ansible package. Ansible is to big to incorporate in a single tutorial so we’ll only touch the outer layers.
In this tutorial we’ll use one of the nodes, later on known as the Master node, to control the other nodes in out network. Note that you don’t need a cluster to use ansible.
Requirements
Any raspberry Pi Cluster with 2 or more nodes.
Or multiple Linux servers/machines.
Setting up the software
Before we install any software we’ll set up the link between the nodes. For the cluster to work, each Slave node needs to be able to talk to the Master node without needing a password to log in. To do this, we use SSH keys. This can be a little laborious, but only needs to be done once. On each node, run the following:
ssh-keygen -t rsa
This creates a unique digital ‘identity’ (and key pairs) for the computer. You’ll be asked a few questions; just press RETURN for each one and do not create a passphrase when asked. Next, tell the master (Server1, 192.168.1.11 in our setup) about the keys by running the following on every other node:
ssh-copy-id 192.168.1.11
Finally, do the same on the Master node and copy its key to every other node in the cluster.
Installing Ansible
Now that there is a link between our nodes with the SSH-Key we can look into the software ans what we do with it.
The magic software we use is Ansible.
Ansible is an IT automation tool used to manage servers and clients. It can handle application deployment, ad-hoc task execution, network automation and much more.
sudo apt install ansible -y
Installing Ansible takes some time on a Pi. There are a lot of dependencies required that are not yet installed on a Lite system.
Using Ansible
There are two ways of using Ansible, Ad-Hoc and Playbooks. But before we get to using ansible we’ll need to configure it.
Configuring Ansible
The main configuration happens in the ansible.cfg file. In this file you’ll see that there is a lot commented out, these are all the default settings and only need the be uncommented when you wish to change them.
We’ll go over a few of the configs, but first lets open it up.
sudo nano /etc/ansible/ansible.cfg
Inventory
The first config is the inventory file. The default inventory file is the ansible hosts file located here: /etc/ansible/hosts. In the inventory we define the hosts we wish to use, group them or even give them an alias.
sudo nano /etc/ansible/hosts
Other then comments and examples this file is empty.
There are 3 ways of addressing a host and we’ll see 2 of them.
The first one is using the hosts IP address, eg 192.168.1.1. The second is using the host addres, eg Server1.Pitronica.GDT. On most networks the IP address would be he easiest way to go.
But wait there is the option to give a host an alias. How does that work?
Like the Linux hosts file ansible links the hostname and alias together. Here is an example:
Server-1 ansible_host=192.168.1.11
Server-2 ansible_host=192.168.1.12
Server-3 ansible_host=192.168.1.13
Server-4 ansible_host=192.168.1.14
Server-5 ansible_host=192.168.1.15
TestPi ansible_host=192.168.1.21
Webserver ansible_host=192.168.0.11
[Cluster-S]
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14
192.168.1.15
[Raspberry-Pi]
192.168.1.[11:15]
192.168.1.21
192.168.0.11
You can see that in my hosts file I have an alias from almost (if not all) hosts I manage using ansible. Then you see a line with a name in between brackets. This is called a group of hosts. This group ends on the next brackets.
Wait that’s not entirely true, as you can see i have brackets in the IP on my raspberry pi group. These brackets are there so i don’t need to sum all the 5 hosts up as they all have ip’s next to each other.
Sudo_user
The next interesting config is the Sudo_user.
Using this config you can change the default sudo user.
Remote_User
The last config I’m going to mention is the remote_user.
In my case I set up an additional user called ansible that will execute all ansible commands on the remote hosts. If i want to use this user I’ll need to either be logged in as this user us use the config line to change the standard used user.
In normal conditions the current user is used for the ssh. But when set the remote_user well be used.
Ansible Ad-Hoc
Before we dive into the playbooks we go and check out how to use a single ansible command.
A single command in the terminal is called a Ad-Hoc command. These are used for commands that you rarely use but is a great way to test and learn.
The Ad-Hoc command in its basic form includes the ansible command, the host or group of hosts and the module we want to execute. Lets start with a ping to the local host, this way we know that ansible is running.
ansible localhost -m ping

So this works, now lets try to ping all our hosts:
ansible Cluster-S -m ping

So we got the ping figured out and all our nodes are online. Notice that they are not in the order of out hosts file? Server-1 is the first responder (192.168.1.11) as it is the local host, then Server-5. This can be coincidental, but Server-5 is probably faster then all the rest, or is idling while the other serves are doing tasks.
Ansible wouldn’t be ansible if it hadn’t had a package manager module, APT is one of them.
This module is a vast one and has many options. So lets see a few.
The first thing we do when using apt is update the local cache so we’ll do that here to.
For this to work we need to use an extra option in the ansible package that allows us to use extra variables on a module, the -a option.
Using the -b option we become the root user, its similar to using sudo
ansible Server-5 -b -m apt -a update_cache=yes
In the next example we’ll install nginX using ansible.
ansible Server-5 -b -m apt -a name=nginx
Unfortunately to use the full potential of the apt module we’ll need to use playbooks. So it ends here for now.
There are 100’s more modules waiting for you to be discovered. However there are to many of them to be handled in this tutorial. I’ll sum up a few so you have an idea of what is around.
- ping
- apt
- yum
- user
- dnf
- service
- copy
- file
- git
More info on them can be found in the ansible documentation.
Ansible Playbooks
An Ansible playbook is a file that tells ansible what to do. In a way a playbook contains multiple Ad-Hoc commands to run in sequence. We’ll start again with a simple ping command, but first lets create the file and folder.
cd
mkdir ansible-playbooks
cd ansible-playbooks
touch myplay.yml
Ansible playbooks are written in Yaml, “YAML Ain’t Markup Language”. Open up the newly created yaml file and lets walk through the setup.
The file starts with 3 dashes. Next we give the play a name, for example ‘ – name: Ping servers’. As with the Ad-Hoc commands we need to tell ansible which hosts we wish to access, this is done with ‘hosts: Cluster-Slave’. In my case i chose for the Cluster-Slave group i added to my hosts file
---
- name: Ping servers
hosts: Cluster-Slave
gather_facts: false
tasks:
- ping:
To run this we use the ‘ansible-playbook’ command in the terminal followed by the playbook.
ansible-playbook myplay.yml

Now In previous example we hardcoded the hosts in the file. But in ansible there is a way to set these on runtime. This means that you don’t have to make 5 files if you want to run them separately on different machines. This is achieved using the ‘–extra-vars’ option. For this to work we’ll change the play as follow:
---
- name: Ping servers
hosts: '{{ target }}'
gather_facts: false
tasks:
- ping:
You’ll see that i replaced the host with a variable called target. Notice the way for bracket using. To run a file like this you’ll use the ‘–extra-vars’ option followed by all required variables.
ansible-playbook myplay.yml --extra-vars "target=Server-2"

This will come in handy when you want to run a script on a new server/host without the need for changing the play every time. Every change you do in a play has the possibility to make mistakes.
Now lets spice things up and do the following with the APT module:
- check for updates
- check if apt is installed
- check if apt is latest version
- upgrade all packages to the latest version
Lets create a new file and copy the following into it that will do just that what we have described. As before we’ll use extra variables.
---
- name: check for apt update
hosts: '{{ target }}'
become: yes
tasks:
- name: check for updates
apt:
update_cache: yes
cache_valid_time: 3600
- name: Check if APT is installed
apt:
name: apt
state: present
- name: Check if APT is latest version
apt:
name: apt
state: latest
- name: Update all packages to their latest version
apt:
name: "*"
state: latest
When running the APT module you won’t get feedback until the module has finished its tasks. So don’t panic when you see nothing changing for a while. Don’t forget to specify the target.
ansible-playbook apt.yml --extra-vars "target=Cluster"

Servers will respond when they done a task. Take the output above for example. We can see that there are already 2 hosts who responded to the update request. On one I manually did a apt update and that’s exactly what we see here.
Host 192.168.1.15 responded with changed, this means that he preformed an apt update upon our request.
When all goes well we’ll see that both the update, the present and the upgrade has been completed.

In my case one of the servers responded with a fail on the upgrade all.

Now here is that error, as you can see its a big one and not really formatted great. So we’ll have to login to the server and check the logs.
So lets get to our ansible master and try the playbook for our failed host only.
ansible-playbook apt.yml --extra-vars "target=Server-4"
For some unknown reason the error didn’t come again.
Where to now
So we have covert the basis of ansible here. We will use ansible further on in this cluster tutorial to install and maintain our cluster.
Due to the fact that ansible is so big, we won’t be able to cover all point in future tutorials. If you are looking for more information about ansible then head on to there documentation here.
Hope to see you in our next Cluster episode or any other tutorial.
Don’t hesitate to correct us when we made a mistake, or when something isn’t clear.
Write a comment or use the contact page.