Julian Wiley

Building a Raspberry Pi 5 Kubernetes Cluster

January 14, 2026· 2 min readRPi Kubernetes

A complete guide to building a 4-node Raspberry Pi 5 Kubernetes cluster with k3s and an Ubuntu desktop as a hybrid control plane.

Raspberry PiKubernetesk3sHomelabARM64

Why Raspberry Pi for Kubernetes?

Cloud Kubernetes is convenient but expensive for learning and experimentation. A Raspberry Pi cluster gives you real multi-node Kubernetes experience -- network partitions, node failures, resource constraints, ARM architecture quirks -- for under $400.

This project runs a 4-node RPi5 cluster with an Ubuntu desktop as a hybrid control plane, serving as a platform for ML workloads, observability, and model serving.

Hardware

ComponentSpecQty
Raspberry Pi 58GB RAM, ARM644
Control PlaneUbuntu Desktop, x86_641
NVMe HATsFor RPi5 boot/storage4
PoE+ HATsPower over Ethernet4
PoE Switch8-port gigabit1
USB SSDsExternal storage per node4

The control plane is an Ubuntu desktop that doubles as a workstation. It runs the k3s server, handles GPU workloads (model training and inference), and hosts heavier services that would overwhelm the Pi nodes.

Why k3s

Standard Kubernetes (kubeadm) has a 2GB RAM minimum for the control plane alone. With 8GB per Pi, that's 25% of each node's resources just for overhead. k3s strips Kubernetes down to essentials -- it uses SQLite instead of etcd, bundles the container runtime, and runs as a single binary under 100MB.

# Server (control plane)
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.29.0+k3s1" sh -s - server \
  --write-kubeconfig-mode 644 \
  --disable traefik \
  --flannel-backend=vxlan

# Agent (worker nodes)
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.29.0+k3s1" sh -s - agent \
  --server https://control-plane.local:6443 \
  --token $K3S_TOKEN

Network Architecture

The cluster uses a flat network with mDNS for discovery:

                 ┌─────────────────┐
                 │  Ubuntu Desktop  │
                 │  Control Plane   │
                 │  192.168.1.x     │
                 └────────┬────────┘
                          │
              ┌───────────┼───────────┐
              │     PoE Switch        │
              ├───┬───┬───┬───┬───────┤
              │   │   │   │   │
           ┌──┴─┐┌┴──┐┌┴──┐┌┴──┐
           │Pi-1││Pi-2││Pi-3││Pi-4│
           └────┘└────┘└────┘└────┘

MetalLB provides LoadBalancer services, and ingress-nginx handles HTTP routing. No static IPs required -- Avahi/mDNS handles node discovery (covered in a separate post).

Networking Add-ons

After k3s is running, the cluster needs:

  • MetalLB -- Bare-metal load balancer for LoadBalancer service type
  • ingress-nginx -- HTTP/HTTPS ingress controller
  • cert-manager -- Automated TLS certificates

Namespace Organization

Services are organized into logical namespaces:

data-services    -- MinIO, PostgreSQL, ChromaDB, Milvus
ml-platform      -- MLFlow, JupyterHub, Dask, Ray
observability    -- Prometheus, Grafana, Jaeger, Loki
mlops            -- Argo Workflows, BentoML
management       -- Control panel API and UI
development      -- Dev tools and scratch space

This keeps resource quotas, network policies, and RBAC cleanly separated.

What's Running

The cluster runs a full ML platform stack: experiment tracking (MLFlow), distributed compute (Dask, Ray), vector databases (ChromaDB, Milvus), observability (Prometheus, Grafana, Jaeger, Loki), workflow orchestration (Argo Workflows), and model serving (BentoML). Each of these gets a deeper dive in subsequent posts.

Related Posts