# Pi Cluster: E2 Working together – Ansible

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.

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

### 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
- 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
- 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 if apt is installed

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

apt:
update_cache: yes
cache_valid_time: 3600

- name: Check if APT is installed
apt:
name: apt
state: present

apt:
name: apt
state: latest

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.