Running Kubernetes on Raspberry Pi hardware has never been more practical. K3s — Rancher’s lightweight Kubernetes distribution — strips out the heavy components while keeping full API compatibility, making it ideal for ARM-based single-board computers. With a cluster of Raspberry Pi 5s, you get a genuine multi-node Kubernetes lab at home that mirrors real production patterns: rolling deployments, service discovery, persistent volumes, and load balancing.
This guide walks you through building a 3-node K3s cluster from scratch, including networking, storage, and deploying your first application.
Hardware Requirements
A K3s cluster works with as few as 2 nodes (1 master + 1 worker), but 3 nodes gives you high availability for the control plane. Here’s what you need per node:
- Raspberry Pi 5 (4GB minimum, 8GB recommended) — K3s master needs at least 2GB reserved for itself
- 32GB+ microSD card per Pi (SSD via USB 3.0 is far better for etcd performance)
- Gigabit network switch — cluster traffic is latency-sensitive
- Ethernet cables — Wi-Fi is unreliable for inter-node communication
- Multi-port USB-C power supply or PoE HAT
Step 1: Prepare All Nodes
Flash Raspberry Pi OS Lite (64-bit) on each microSD using Raspberry Pi Imager. Set unique hostnames during imaging:
k3s-master— 192.168.1.100k3s-worker1— 192.168.1.101k3s-worker2— 192.168.1.102
Enable SSH and set the same username/password for convenience. Once all three are running, SSH into each and perform these steps:
sudo apt update && sudo apt full-upgrade -y
# Disable swap (Kubernetes requires it)
sudo dphys-swapfile swapoff
sudo dphys-swapfile uninstall
sudo systemctl disable dphys-swapfile
# Enable cgroups (required for container memory limits)
sudo sed -i 's/$/ cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1/' /boot/firmware/cmdline.txt
sudo reboot
Step 2: Install K3s on the Master Node
SSH into k3s-master and run the K3s installer:
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
K3s installs and starts automatically as a systemd service. Wait 60 seconds, then verify:
kubectl get nodes
# Should show k3s-master Ready control-plane,master
Get the node token that workers will use to join:
sudo cat /var/lib/rancher/k3s/server/node-token
# Copy this value — you'll need it for each worker
Step 3: Join Worker Nodes
SSH into each worker node and run the join command, substituting your master’s IP and token:
export K3S_URL="https://192.168.1.100:6443"
export K3S_TOKEN="YOUR_NODE_TOKEN_HERE"
curl -sfL https://get.k3s.io | K3S_URL=$K3S_URL K3S_TOKEN=$K3S_TOKEN sh -
Repeat on both k3s-worker1 and k3s-worker2. Then back on the master, verify all nodes have joined:
kubectl get nodes -o wide
# NAME STATUS ROLES AGE
# k3s-master Ready control-plane,master 5m
# k3s-worker1 Ready <none> 2m
# k3s-worker2 Ready <none> 1m
Step 4: Configure kubectl on Your Laptop
You don’t want to SSH into the Pi every time you manage the cluster. Copy the kubeconfig to your laptop:
# On your laptop (Linux/Mac)
mkdir -p ~/.kube
scp [email protected]:/etc/rancher/k3s/k3s.yaml ~/.kube/config
# Replace the server address
sed -i 's/127.0.0.1/192.168.1.100/' ~/.kube/config
# Test it
kubectl get nodes
On Windows, use WSL2 or copy the file to %USERPROFILE%.kubeconfig and edit the server address.
Step 5: Deploy Your First Application
Deploy a simple nginx web server across your cluster:
kubectl create deployment nginx --image=nginx:alpine --replicas=3
kubectl expose deployment nginx --port=80 --type=LoadBalancer
K3s includes a built-in load balancer (ServiceLB / Klipper). Check the service:
kubectl get svc nginx
# EXTERNAL-IP will show your node IPs
curl http://192.168.1.100
To deploy something more meaningful — like a Node.js app — create a YAML manifest:
cat > myapp.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: node:20-alpine
command: ["node", "-e", "require('http').createServer((r,s)=>{s.end('Hello from '+require('os').hostname())}).listen(3000)"]
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
EOF
kubectl apply -f myapp.yaml
Each request should round-robin between pods on different nodes — you’ll see different hostnames in the response.
Step 6: Set Up Persistent Storage
K3s includes a local-path storage provisioner. For a cluster-wide shared storage solution, install Longhorn:
# Install prerequisites on ALL nodes
sudo apt install -y open-iscsi nfs-common
# Install Longhorn via kubectl
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.0/deploy/longhorn.yaml
# Watch it come up (takes 3–5 min)
kubectl get pods -n longhorn-system --watch
Longhorn replicates data across nodes automatically — if one Pi loses power, your data is safe on the others. Access the UI:
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80
Then open http://localhost:8080 in your browser.
Step 7: Add Monitoring with Helm
Install Helm (the Kubernetes package manager) and deploy the kube-prometheus-stack:
# Install Helm on the master
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Add the prometheus-community repo
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# Install with reduced resource limits for Pi
helm install monitoring prometheus-community/kube-prometheus-stack
--set prometheus.prometheusSpec.resources.requests.memory=256Mi
--set grafana.resources.requests.memory=128Mi
-n monitoring --create-namespace
Access Grafana via port-forward, log in with admin/prom-operator, and see live cluster metrics across all your Pi nodes.
Frequently Asked Questions
What is the difference between K3s and full Kubernetes?
K3s removes several optional Kubernetes components (cloud provider integrations, alpha features, legacy APIs) and bundles containerd, Flannel CNI, CoreDNS, and a load balancer into a single ~70MB binary. It’s fully conformant with the Kubernetes API, so all standard YAML manifests and kubectl commands work identically. The main trade-off is fewer configuration options for advanced networking scenarios.
How many Raspberry Pis do I need for a K3s cluster?
You can start with just 2 (1 master + 1 worker). For high availability of the control plane itself, you need 3 or more master nodes with an embedded etcd cluster. For a homelab learning environment, 1 master + 2 workers is the practical sweet spot — it lets you see pod scheduling and node affinity in action.
Can I use microSD cards for K3s or do I need SSDs?
microSD works for getting started, but etcd (the Kubernetes state database) writes frequently and will wear out a microSD in weeks under load. Use a USB 3.0 SSD for the master node at minimum. Workers can use microSD since they don’t run etcd. Boot from SD and move the root filesystem to SSD using rsync + cmdline.txt root parameter change.
How do I update K3s to a newer version?
Re-run the installer script with the desired version: curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.30.0+k3s1 sh -. Update the master first, then each worker. K3s is backward compatible so mixed versions are temporarily fine during rolling updates.
Does K3s support ARM64 natively?
Yes. K3s provides ARM64 binaries natively and has done so since early versions. The Raspberry Pi 5 running 64-bit Raspberry Pi OS is fully supported. Most Helm charts and container images in Docker Hub also provide ARM64 variants — check for linux/arm64 in the image manifest.
Build your Pi cluster today. Shop Raspberry Pi 5 boards in 2GB, 4GB, and 16GB RAM variants at zbotic.in/raspberry-pi with fast delivery across India.
Add comment