Skip to content

Running a Lightweight Kubernetes Cluster (k3s) on Raspberry Pi

Running a Kubernetes cluster on Raspberry Pi is an excellent way to learn production-grade container orchestration, set up a home lab, or deploy highly available microservices. While standard Kubernetes (kubeadm) is too heavy for the Pi's limited RAM, k3s by Rancher is a highly optimized, fully compliant lightweight alternative designed specifically for edge and IoT environments.

This guide walks you through setting up a k3s cluster from scratch on Raspberry Pi OS.


1. Prerequisites and Planning

For a functional Kubernetes cluster, we recommend: - At least two Raspberry Pi devices (Raspberry Pi 4 or 5 with 4GB/8GB RAM are highly recommended. A 1GB/2GB Pi is too small for running multiple workloads). - Wired Ethernet connection (Wi-Fi is prone to packet loss, which causes nodes to flap to offline states). - Raspberry Pi OS (64-bit) (essential for running 64-bit container architectures).

Cluster Architecture

        ┌────────────────────────────────────────────────────────┐
        │                 Master Node (Server)                   │
        │             IP: 192.168.1.100 (k3s server)             │
        └────────────────────────────────────────────────────────┘
                                    │ (Joins via Secure Token)
        ┌────────────────────────────────────────────────────────┐
        │                  Worker Node (Agent)                   │
        │              IP: 192.168.1.101 (k3s agent)             │
        └────────────────────────────────────────────────────────┘

2. Preparing the OS (Cgroups Configuration)

Kubernetes relies on Linux Control Groups (cgroups) to limit CPU and memory allocation for pods. By default, memory cgroups are disabled in Raspberry Pi OS and must be explicitly enabled.

Run this step on all nodes (Server and Agents):

1. Edit the Boot Command Line

Open /boot/firmware/cmdline.txt (or /boot/cmdline.txt on older OS versions) using sudo:

sudo nano /boot/firmware/cmdline.txt

2. Append Parameters

Add the following options to the end of the existing single line (do not insert newlines):

cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

3. Reboot the system

sudo reboot

4. Verify Cgroup Support

After rebooting, check that the memory cgroup is enabled:

cat /proc/cgroups | grep memory

3. Installing the k3s Server (Master Node)

On your designated Master Node, run the official k3s installation script:

curl -sfL https://get.k3s.io | sh -

This script: - Downloads the k3s binary. - Configures a systemd service (k3s). - Installs kubectl, ctr, and other standard container tools. - Starts the Kubernetes API server.

Verify Server Operation

Once the installation finishes, run:

sudo kubectl get nodes
You should see your master node in a Ready state:
NAME           STATUS   ROLES                  AGE   VERSION
raspberrypi1   Ready    control-plane,master   35s   v1.28.2+k3s1

Retrieve the Connection Token

To connect worker nodes to this master, you need the unique node token generated by the server. Retrieve it by running:

sudo cat /var/lib/rancher/k3s/server/node-token
(Copy the resulting string; you will need it for the next step).

4. Connecting Worker Nodes (Agent Nodes)

On your Worker Nodes (Agent nodes), run the installation script, specifying your Master Node's IP address and the Token you copied:

1
2
3
4
5
6
# Define environment variables
export K3S_URL="https://192.168.1.100:6443"
export K3S_TOKEN="K10fef8b8c1..." # Paste your actual token here

# Run installer in agent mode
curl -sfL https://get.k3s.io | sh -

The script automatically registers the agent to the master server and starts the k3s-agent service.

Verify Cluster Status

Go back to your Master Node and run:

sudo kubectl get nodes
You should now see all connected nodes:
1
2
3
NAME           STATUS   ROLES                  AGE    VERSION
raspberrypi1   Ready    control-plane,master   10m    v1.28.2+k3s1
raspberrypi2   Ready    <none>                 2m     v1.28.2+k3s1

5. Deploying a Workload

Let's verify the cluster's orchestration capabilities by deploying a simple web server workload.

1. Create a Deployment file (web-deploy.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rpi-web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

2. Apply the configuration

On the master node, deploy the YAML file:

sudo kubectl apply -f web-deploy.yaml

3. Verify Pod Status

sudo kubectl get pods -o wide
You will see two web server pods running, likely distributed across different physical Raspberry Pi devices:
1
2
3
NAME                       READY   STATUS    RESTART   IP           NODE
rpi-web-84f98d45d6-abc12   1/1     Running   0         10.42.1.3    raspberrypi2
rpi-web-84f98d45d6-xyz34   1/1     Running   0         10.42.0.5    raspberrypi1

Access the web server from any browser on your local network by navigating to http://<ANY_PI_IP>:30080.


6. Resource Management & Best Practices

  1. Configure Swap Space: Kubernetes expects Swap to be disabled by default. While k3s can run with Swap enabled, it can cause unstable scheduling. Set memory limits on your pods to prevent Out-Of-Memory (OOM) killing.
  2. Watch Storage wear: Running etcd/k3s logs writes constantly to disk. Use High-End SD cards (A1 or A2 rated) or boot from SSDs to prevent storage failure.
  3. Set Up a Local Registry: Pulling heavy Docker images over the internet on multiple Pi nodes can saturate local network bandwidth. Consider setting up a local Docker registry.