How to manage a Raspberry Pi cluster with Ansible

Quick guide to install Ansible on a Raspberry Pi and manage other Pi’s remotely.

All you need….

Step 1
Install Ansible on the Master Node and add Ansible under Debian to PPA [Personal Package Archive].

cd /etc/apt
sudo nano sources

A great thing is that the Ubuntu PPA works also for Raspbian Buster, at the top of the file add:

deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main

Step 2
Update your image and install Ansible.

sudo apt-get update 
sudo apt-get install ansible

Step 3
Open the [hosts] file and add the following.

sudo nano /etc/ansible/hosts

Define your hosts on the network as [master] and [slaves]. The great thing is Ansible controls via SSh so no extra installation on the [slaves]. However, note that you need to setup SSH on all nodes to remove the password prompts.

## set up ssh user name and path to python3 ##
[all:vars]
ansible_user='pi'
ansible_become=yes
ansible_become_method=sudo
ansible_python_interpreter='/usr/bin/env python3'

[master]

pi@10.0.30.101 //or whatever IP your Pi is under

[slave]

pi@10.0.30.102 //or whatever IP your Pi is under
pi@10.0.30.103 //or whatever IP your Pi is under

Note you can also combine IP ranges as [slaves] and write the IP’s like the following.

pi@10.0.30.[102:103]

Step 4
Let’s [“ping”: “pong”] our Pi’s.

ansible all -m ping

10.0.30.101 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.0.30.102 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.0.30.103 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Step 5
Writing a playbook. Let’s [update] and [upgrade] all Pi’s at once…

cd /etc/ansible
mkdir playbooks
touch update_upgrade.yml

Inside the playbook [update_upgrade.yml], we also add to the configuration to use sudo to install the updates and upgrades. Always good to find out if we need to reboot the Pi afterwards.

---
- hosts: all
  remote_user: pi
  become: true
  become_method: sudo
  tasks:
    - name: Update apt repo and cache on all boxes
      apt: update_cache=yes force_apt_get=yes cache_valid_time=3600

    - name: Upgrade all packages on Pi's
      apt: upgrade=dist force_apt_get=yes

    - name: Check if a reboot is needed on all Pi's
      register: reboot_required_file
      stat: path=/var/run/reboot-required get_md5=no

    - name: Reboot the Pi's if kernel updated
      reboot:
        msg: "Reboot initiated by Ansible for kernel updates"
        connect_timeout: 5
        reboot_timeout: 300
        pre_reboot_delay: 0
        post_reboot_delay: 30
        test_command: uptime
      when: reboot_required_file.stat.exists

Step 6
Run the playbook on the master Pi.

ansible-playbook -i hosts update.yml

The file is now in [staging] try to run [git status] again. You should see your file in green that should be committed. To commit the file with a note run:

PLAY [all] **************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [pi@10.0.30.101]
ok: [pi@10.0.30.103]
ok: [pi@10.0.30.102]

TASK [Update apt repo and cache on all boxes] *****************************************************************
changed: [pi@10.0.30.101]
changed: [pi@10.0.30.103]
changed: [pi@10.0.30.102]

TASK [Upgrade all packages on Pi's] ******************************************************************
ok: [pi@10.0.30.101]
ok: [pi@10.0.30.103]
ok: [pi@10.0.30.102]

TASK [Check if a reboot is needed on all Pi's] ****************************************************************
ok: [pi@10.0.30.101]
ok: [pi@10.0.30.103]
ok: [pi@10.0.30.102]

TASK [Reboot the Pi's if kernel updated] ******************************************************************
ok: [pi@10.0.30.101]
ok: [pi@10.0.30.103]
ok: [pi@10.0.30.102]

PLAY RECAP **************************************************************************
pi@10.0.30.101           : ok=2    changed=0    unreachable=0    failed=0
pi@10.0.30.102           : ok=2    changed=0    unreachable=0    failed=0
pi@10.0.30.103           : ok=2    changed=0    unreachable=0    failed=0

Step 6
Done. Well, there is a lot more you can achieve with Ansible…