Setting Up a Raspberry Pi Cluster
Tags: raspberrypi, rpi, ssh
Published: 2021-02-28 20:18:55

<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/veceory0gt2nh0gfwefd.png" />

<sup><b>Credits:</b> Logo created by [raspberrypi.org](https://www.raspberrypi.org/)</sup>

Installation instructions for setting up a local Raspberry Pi cluster at your home desk.

- [Operating System on SD Card](#os-install) 
- [Network Setup](#network-setup)
- [RPi Configuration](#rpi-configuration)
- [SSH Config](#ssh-config)
   - [Client](#ssh-client)
   - [RPi Server](#ssh-rpi-server)
- [Verification](#verification)
- [Troubleshooting](#troubleshooting)
- [Summary](#summary)

<p>&nbsp;</p>

> **Note:** For the time this post was published, there isn't an official `Raspberry Pi OS` image that supports a 64 bit system. There are [beta versions](https://downloads.raspberrypi.org/raspios_arm64/images/) but with limitations. This blog post won't cover them until officially released.

<p>&nbsp;</p>

<div style="text-align: center;"><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ig95j6mkgnopt3zwpq02.png" alt="rpi-cluster-orig" height="400"/></div>

<p>&nbsp;</p>

<h2 id="os-install">Operating System on SD Card</h2>

1. Connect the SD card to your local machine (laptop / desktop)

2. Download `Raspberry Pi OS Lite (Debian Buster)` image from [here](https://www.raspberrypi.org/software/operating-systems/#raspberry-pi-os-32-bit)

3. Flash OS image using `Raspberry Pi Imager` as specified in [here](https://www.raspberrypi.org/software/)

      <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzv3xq58ylonw9tbosbk.png" />

4. After flashing, eject and re-connect the SD card again to your local machine

5. Check for `boot` connected device

6. Mount the SD card 

7. Open a terminal session and create a text file named `ssh` in the boot partition

      ```bash
      # If you are working on macOS
      sudo touch /Volumes/boot/ssh

      # Other Unix-like operating system
      sudo touch <path-to-rpi-boot-volume>/ssh
      ```

8. Eject the SD card and connect it to the Raspberry Pi

---

<h2 id="network-setup">Network Setup</h2>

1. Power up the RPi and connect directly to the home router
1. Open the router network [dashboard](http://192.168.1.1/)
  
      > **Note:** Your router dashboard address might differ, check with your router manufacture guide.
   
1. Verify under `LAN settings` ->  `Client List` that there is a new `raspberrypi` client 
1. Assign a static IP address using this [guide](http://blog.zachinachshon.com/rpi-network/)

---

<h2 id="rpi-configuration">RPi Configuration</h2>

1. SSH into the server using `ssh pi@<RPI-IP-ADDRESS>` with an IP address from previous step and the default password `raspberry`
1. Set the GPU memory split to 16MB by editing the RPi configuration file `sudo vi /boot/config.txt` and appending `gpu_mem=16` to it

      > **Note:** We specify the minimum memory possible to reserve for GPU (display) since we won’t require user interface.

1. Reboot using `sudo reboot` for changes to take effect
1. SSH again to the RPI server and type `sudo raspi-config`. Edit the following settings:
   - Change the password for the `pi` user (**recommended**)
   - Set the hostname to your liking
   - Make sure SSH server is enabled
       > **Note:** If you are planning on using this server as a Kubernetes master - name it `kmaster`. If it is a Kubernetes node, name it `knode<number>` while `<number>` is the next in-line number of your cluster stack.

         <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdms0c9mmk55uawnldpr.png" />

1. Close the SSH session and reconnect to the RPi server again
1. Verify hostname was properly set and force manual replacement, if required. From the RPi terminal:
   - Run `cat /etc/hostname` and check for `kmaster`
   - Run `cat /etc/hosts` and check for `127.0.1.1 kmaster`
   - Run `hostname` which should return `kmaster`, otherwise run `sudo hostname kmaster` and check again
       
       > **Note:** Use `kmaster` or `knode<number>` according to the server type if you are setting up a Kubernetes cluster.

1. **(Optional):** Install your favourite utilities on the RPi server:
	
      ```bash
      # Use Vim as a text editor
      sudo apt-get -y install vim
      ```

1. **(Optional):** Set your preferred aliases on `~/.bashrc`:
	
      ```bash
      # Open bash run command file for editing
      vim ~/.bashrc
   
      # List all files/directories including hidden ones with size unit suffixes 
      alias l="ls -lah"
      ```

1. **(Optional):** If you are planning to install the Rancher `k3s` version of Kubernetes, you should enable a few container features by adding them _to the end of the `/boot/cmdline.txt` file_:

      ```bash
      # Edit file with sudo
      sudo vim /boot/cmdline.txt
   
      # Append the following
      cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory
      ```

---

<h2 id="ssh-config">SSH Config</h2>

We need to configure secure shell access for client <-> RPi server communication. It will allow us to access the RPi server from client machines such as our laptop and also allow secure communication between the RPi server and our locally installed utilities.

<h3 id="ssh-client">Client</h3>

These instructions are relevant to the computer being used to connect to the RPi server:

1. Create directory `~/.ssh` if it doesn't exists and cd into it
1. Run `ssh-keygen` (with name `kmaster OR knode<number>`, no passphrase)
1. Add the private key `kmaster` to the ssh agent (select between permanent/temporary)

    ```bash
    ssh-add ~/.ssh/kmaster      # Add temporary to keychain
    ssh-add -K ~/.ssh/kmaster   # Add permanently to keychain
    ```

    > **Note:** This will allow a secure communication without prompting for the password every time.
	
1. Copy the public key to RPi server

      ```bash
      # Master node
      ssh-copy-id -i ~/.ssh/kmaster.pub pi@<RPI-IP-ADDRESS>
		
      # Agent node
      ssh-copy-id -i ~/.ssh/knode<number>.pub pi@<RPI-IP-ADDRESS>
      ```
      > **Important:** For this step you will need to authenticate with your password. A file named `~/.ssh/authorized_keys` is auto-created with the public key content on the RPi server.

1. **(Optional):** If you have defined a static IP for the RPi server as described in [here](http://blog.zachinachshon.com/rpi-network/), add named hosts records on your client machine:

   ```bash
   # Use names instead of IP addresses
   echo -e "<MASTER-IP-ADDRESS>\tkmaster" | sudo tee -a /etc/hosts
   echo -e "<NODE-IP-ADDRESS>\tknode1" | sudo tee -a /etc/hosts
   ```

<p>&nbsp;</p>

<h3 id="ssh-rpi-server">RPi Server</h3>

These instructions are intended for the RPi server to enable SSH communication:

1. Disable SSH `PasswordAuthentication`:
   - Edit `ssh_config` by `sudo vim /etc/ssh/ssh_config`
   - Uncomment `PasswordAuthentication` by removing the `#` prefix
   - Change its value to `no`
   - Make sure `PasswordAuthentication` is properly aligned (4 spaces)

1. Restart SSH server

   ```bash
   sudo /etc/init.d/ssh restart
   sudo /etc/init.d/ssh status   # Verify SSH server is running
   ```

---

<h2 id="verification">Verification</h2>

To verify everything is set-up correctly, try to connect from the client machine i.e. laptop to the RPi server with the following command:

```bash
ssh pi@kmaster
ssh pi@knode<number>
```

---

<h2 id="troubleshooting">Troubleshooting</h2>

<h3 id="trouble-locale">Locale</h3>

**What?** Locale errors/warnings when connecting to a RPi server and/or running `locale` on a server node. These are a few example errors:

```bash
setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
```

**Solution:** We'll set our locale to `en_US` by running the following steps:

1. SSH to the RPi server
1. Edit the `locale.gen` file using `sudo vi /etc/locale.gen`
1. Uncomment the line with `en_US.UTF-8` by removing the `#` character (make sure there are no leading spaces)
1. Run `sudo locale-gen en_US.UTF-8`
1. Run `sudo update-locale en_US.UTF-8`
1. Run `locale` and make sure there are no errors/warnings

---

<h3 id="summary">Summary</h3>

By the end of this post you should have a working headless (non-GUI) Raspberry Pi(s) connected to your home network with SSH communication available, good job ! :clap:

**What now?** You are welcome to check back for a future blog post on how to install Kubernetes on top of your amazing RPi cluster.

Please leave your comment, suggestion or any other input you think is relevant to this post in the discussion below.

---

Like this post?
You can find more by:

Checking out my blog: https://blog.zachinachshon.com
Following me on twitter: @zachinachshon

Thanks for reading! ❤️