Run Mosquitto (MQTT) on Raspberry Pi with K3S
By: Ad L'Ecluse
Tags: Raspberry Pi, Mosquitto, Kubernetes, Mqtt, K3s

While diving into the world of IoT, you’ve probably heard of MQTT along the way. I won’t explain what MQTT is, as there are a lot of other articles dedicated to this. But what I want to share is how to set up Mosquitto (An Open Source MQTT broker) on a Raspberry Pi using K3S.

Step 1: Prepare the volumes and configuration

The docker page of Mosquitto says the following:

Three directories have been created in the image to be used for configuration, persistent storage and logs.

More precisely, the following three folders:

/mosquitto/config

/mosquitto/data

/mosquitto/log

The /mosquitto/data and the /mosquitto/logs make perfect candidates to create Persistent Volumes for it. E.g.: you don’t want the logs to be gone when Mosquitto goes down for some reason and you want to check what happened.

Note that I’m using local-storage for the examples. For other types of volumes you can always check the Kubernetes documentation. But for the sake of simplicity I won’t use any external dependencies, so local storage is used here. Feel free to use any storage provider of your choice.

Persistent volume for the logs directory

This is the volume that represents the /mosquitto/logs directory.

apiVersion: v1

kind: PersistentVolume

metadata:

name: mosquitto-log-pv

spec:

capacity:

storage: 100Mi

volumeMode: Filesystem

accessModes:

- ReadWriteOnce

persistentVolumeReclaimPolicy: Retain

storageClassName: local-storage

local:

path: /data/mosquitto/log

nodeAffinity:

required:

nodeSelectorTerms:

- matchExpressions:

- key: kubernetes.io/hostname

operator: In

values:

- raspberryk3s

As we want to use this volume later on in the deployment configuration, we can already prepare the Volume Claim for it.

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

name: mosquitto-log-pvc

namespace: iot

spec:

accessModes:

- ReadWriteOnce

resources:

requests:

storage: 100Mi

Persistent volume for the data directory

This is the volume that represents the /mosquitto/data folder.

apiVersion: v1

kind: PersistentVolume

metadata:

name: mosquitto-data-pv

spec:

capacity:

storage: 100Mi

volumeMode: Filesystem

accessModes:

- ReadWriteOnce

persistentVolumeReclaimPolicy: Retain

storageClassName: local-storage

local:

path: /data/mosquitto/data

nodeAffinity:

required:

nodeSelectorTerms:

- matchExpressions:

- key: kubernetes.io/hostname

operator: In

values:

- raspberryk3s

Again we will provide the Volume Claim so it can be used later on in the deployment.

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

name: mosquitto-data-pvc

namespace: iot

spec:

accessModes:

- ReadWriteOnce

resources:

requests:

storage: 100Mi

Config Map for the mosquitto.conf file

The mosquitto.conf file holds all configuration settings for Mosquitto. We will use a ConfigMap to store this. As a simple example but a really useful one, we will password protect our Mosquitto service by using a pwfile .

The password_file expects a path where that file actually lives. So we need to mount the pwfile later on in the deployment at this path.

apiVersion: v1

kind: ConfigMap

metadata:

name: mosquitto-config

namespace: iot

data:

mosquitto.conf: |

password_file /mosquitto/config/pwfile/pwfile

Store the pwfile password in a Secret

As we are using a password let put this in a Secret object.

Note: the value for a Secret in Kubernetes must be stored in a Base64 encoded string.

We can generate it by executing the following steps:

docker run eclipse-mosquitto docker exec -it your-container-id sh Run mosquitto_passwd -c my-password-file.txt my-user with my-user being the username you want. It will then ask for a password. If you output the content of the file cat my-password-file.txt you get the content you’ll need Take this value and Base64 encode it

apiVersion: v1

kind: Secret

metadata:

name: mosquitto-pwfile

namespace: iot

type: Opaque

data:

pwfile: |

your-base64-password-value-here

Step 2: The Mosquitto deployment

After all the volumes and configurations are prepared we can now create the Deployment for Mosquitto. This will actually run Mosquitto and mounts all the necessary volumes, config map and secret to be able to run.

kind: Deployment

apiVersion: apps/v1

metadata:

name: mosquitto

namespace: iot

spec:

replicas: 1

selector:

matchLabels:

name: mosquitto

template:

metadata:

labels:

name: mosquitto

spec:

containers:

- name: mosquitto

image: eclipse-mosquitto

ports:

- containerPort: 1883

volumeMounts:

- name: mosquitto-config-file

mountPath: /mosquitto/config

- name: mosquitto-pwfile

mountPath: /mosquitto/config/pwfile

- name: mosquitto-log

mountPath: /mosquitto/log

- name: mosquitto-data

mountPath: /mosquitto/data

volumes:

- name: mosquitto-config-file

configMap:

name: mosquitto-config

- name: mosquitto-pwfile

secret:

secretName: mosquitto-pwfile

- name: mosquitto-data

persistentVolumeClaim:

claimName: mosquitto-data-pvc

- name: mosquitto-log

persistentVolumeClaim:

claimName: mosquitto-log-pvc

Step 3: Provide a service

Running Mosquitto as a deployment on its own is not really useful as other applications must be able to connect to it. Therefore we will need a service for this. The port used here is the same one that is used in the deployment above.

This will enable Mosquitto to be accessible inside your K3S cluster.

apiVersion: v1

kind: Service

metadata:

name: mosquitto

namespace: iot

spec:

ports:

- protocol: TCP

name: web

port: 1883

selector:

name: mosquitto

Step 4: Deploy to K3S 🚀

After creating all the configurations in the first 3 steps we can deploy this onto the K3S cluster on your Raspberry Pi.

If you like to split all objects in different files, you will end in a file structure similar to the following:

Example of all the files representing every single Kubernetes object that is used.

Now you can start applying these configurations onto your K3S cluster on your Raspberry Pi.

kubectl apply -f mosquitto-configmap.yaml

kubectl apply -f mosquitto-data-pv.yaml

kubectl apply -f mosquitto-data-pvc.yaml

kubectl apply -f mosquitto-logs-pv.yaml

kubectl apply -f mosquitto-logs-pvc.yaml

kubectl apply -f mosquitto-secret.yaml

kubectl apply -f mosquitto-deployment.yaml

kubectl apply -f mosquitto-service.yaml

Feel free to leave some comments if it helped you, if something is not clear or wrong. I’m always willing to learn and improve! 😊

Cheers 👋