RKE2 on a Raspberry Pi lab cluster¶
I use RKE2 on ARM64 Pi hardware when I want a small Kubernetes cluster that behaves enough like the larger systems I work with to be useful for experiments. This is a lab setup — not a reference production deployment.
RKE2 is a reasonable fit here: ARM64 builds exist, the install is small, and you get a real kubelet/API without assembling the control plane by hand. Pis are cheap, loud, and thermally honest, which is fine for learning and integration tests.
1) Hardware Prep: The Foundation¶
Minimum Requirements¶
# Control Plane Node
- Raspberry Pi 4 (4GB+ RAM recommended)
- 32GB+ SSD via USB 3.0 (preferred over microSD)
- Gigabit Ethernet connection
- Heat sink + fan (these Pis run hot under load)
# Worker Nodes (2+ recommended)
- Raspberry Pi 4 (2GB+ RAM minimum)
- 16GB+ SSD via USB 3.0
- Gigabit Ethernet connection
- Heat sink + fan
# Network Infrastructure
- Gigabit switch (managed preferred)
- UPS (Pis are fragile to power loss)
- Quality power supplies (2.5A+ per Pi)
Why This Hardware: Pis are ARM64, energy-efficient, and perfect for learning. SSDs prevent SD card burnout, and proper cooling prevents thermal throttling.
Network Topology¶
graph TB
subgraph "Raspberry Pi Farm"
MASTER[Pi Master<br/>Control Plane<br/>192.168.1.10]
WORKER1[Pi Worker 1<br/>192.168.1.11]
WORKER2[Pi Worker 2<br/>192.168.1.12]
WORKER3[Pi Worker 3<br/>192.168.1.13]
end
subgraph "Network Infrastructure"
SWITCH[Gigabit Switch]
ROUTER[Router/Gateway<br/>192.168.1.1]
UPS[UPS Backup]
end
subgraph "External Access"
LAPTOP[Admin Laptop]
INTERNET[Internet]
end
MASTER --> SWITCH
WORKER1 --> SWITCH
WORKER2 --> SWITCH
WORKER3 --> SWITCH
SWITCH --> ROUTER
ROUTER --> INTERNET
UPS --> MASTER
UPS --> WORKER1
UPS --> WORKER2
UPS --> WORKER3
LAPTOP --> ROUTER
classDef master fill:#ff6b6b,stroke:#d63031,stroke-width:3px
classDef worker fill:#74b9ff,stroke:#0984e3,stroke-width:2px
classDef network fill:#00b894,stroke:#00a085,stroke-width:2px
classDef external fill:#fdcb6e,stroke:#e17055,stroke-width:2px
class MASTER master
class WORKER1,WORKER2,WORKER3 worker
class SWITCH,ROUTER,UPS network
class LAPTOP,INTERNET external Why This Topology: Simple, scalable, and mirrors real data center patterns. Each Pi has a dedicated role and IP address.
2) OS & Base Config: The Operating System¶
Install Raspberry Pi OS Lite (64-bit)¶
# Download Raspberry Pi Imager
# Flash Raspberry Pi OS Lite (64-bit) to SSD
# Enable SSH during imaging
# Boot and connect via SSH
Why Raspberry Pi OS Lite: Minimal overhead, ARM64 support, and optimized for Pi hardware.
Base System Configuration¶
# Update system
sudo apt update && sudo apt upgrade -y
# Install essential tools
sudo apt install -y curl wget git vim htop iotop nethogs
# Set hostname (on master)
sudo hostnamectl set-hostname rpi-master
# Set hostname (on workers)
sudo hostnamectl set-hostname rpi-worker-1
sudo hostnamectl set-hostname rpi-worker-2
sudo hostnamectl set-hostname rpi-worker-3
Static IP configuration¶
Kubernetes join tokens and firewall rules are easier when node addresses do not drift. On Raspberry Pi OS Bookworm and later, networking is usually NetworkManager, not dhcpcd.
# List connections — names vary by image
nmcli -t -f NAME con show
# Example: static IPv4 on the wired profile (adjust NAME and address per node)
sudo nmcli con mod "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 192.168.1.10/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "192.168.1.1 8.8.8.8"
sudo nmcli con up "Wired connection 1"
Legacy images still on dhcpcd can use /etc/dhcpcd.conf static blocks — verify with systemctl status NetworkManager before editing the wrong stack.
Enable cgroups (Critical for Kubernetes)¶
# Edit /boot/firmware/cmdline.txt
sudo vim /boot/firmware/cmdline.txt
# Append to the single kernel cmdline (do not add a second line):
cgroup_enable=cpuset cgroup_enable=memory
# Reboot
sudo reboot
Why cgroups: Kubernetes requires cgroups for resource management. Without this, kubelet won't start.
SSH Key Setup¶
# Generate SSH key on your laptop
ssh-keygen -t ed25519 -C "rke2-pi-farm"
# Copy to all Pis
ssh-copy-id pi@192.168.1.10
ssh-copy-id pi@192.168.1.11
ssh-copy-id pi@192.168.1.12
ssh-copy-id pi@192.168.1.13
# Test passwordless SSH
ssh pi@192.168.1.10
Why SSH Keys: You'll be managing multiple Pis. Passwordless SSH saves time and prevents lockouts.
3) RKE2 Installation: The Kubernetes Engine¶
Control Plane Installation¶
# Install RKE2 on master
curl -sfL https://get.rke2.io | sh -
# Enable and start RKE2 server
sudo systemctl enable rke2-server.service
sudo systemctl start rke2-server.service
# Check status
sudo systemctl status rke2-server.service
# Get the cluster token (save this!)
sudo cat /var/lib/rancher/rke2/server/node-token
Why RKE2: Lightweight, secure defaults, ARM64 support, and easier to manage than kubeadm.
Worker Node Installation¶
# Install RKE2 agent on each worker
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sh -
# Create config directory
sudo mkdir -p /etc/rancher/rke2/
# Create config file (replace with your master IP and token)
sudo tee /etc/rancher/rke2/config.yaml << EOF
server: https://192.168.1.10:9345
token: <your-node-token-here>
EOF
# Enable and start RKE2 agent
sudo systemctl enable rke2-agent.service
sudo systemctl start rke2-agent.service
# Check status
sudo systemctl status rke2-agent.service
Why This Config: RKE2 agents need to know where the server is and how to authenticate.
Verify Cluster Status¶
# Copy kubeconfig to your laptop
scp pi@192.168.1.10:/etc/rancher/rke2/rke2.yaml ~/.kube/config
# Edit kubeconfig to use master IP
sed -i 's/127.0.0.1/192.168.1.10/g' ~/.kube/config
# Test cluster access
kubectl get nodes -o wide
kubectl get pods -A
Why This Works: RKE2 creates a working cluster with minimal configuration. The hard work is done for you.
4) Cluster Topology: Visualizing Your Farm¶
Network Flow Diagram¶
graph TB
subgraph "RKE2 Cluster"
subgraph "Control Plane"
MASTER[Pi Master<br/>rke2-server<br/>192.168.1.10]
ETCD[etcd<br/>Cluster State]
API[Kubernetes API<br/>Port 6443]
end
subgraph "Worker Nodes"
WORKER1[Pi Worker 1<br/>rke2-agent<br/>192.168.1.11]
WORKER2[Pi Worker 2<br/>rke2-agent<br/>192.168.1.12]
WORKER3[Pi Worker 3<br/>rke2-agent<br/>192.168.1.13]
end
subgraph "Services"
TRAEFIK[Traefik Ingress<br/>Port 80/443]
METALLB[MetalLB<br/>Load Balancer]
end
end
subgraph "External Access"
ADMIN[Admin Laptop<br/>kubectl]
USERS[End Users<br/>HTTP/HTTPS]
end
%% Control plane connections
MASTER --> ETCD
MASTER --> API
%% Worker connections
WORKER1 --> MASTER
WORKER2 --> MASTER
WORKER3 --> MASTER
%% Service connections
TRAEFIK --> WORKER1
TRAEFIK --> WORKER2
TRAEFIK --> WORKER3
METALLB --> WORKER1
METALLB --> WORKER2
METALLB --> WORKER3
%% External connections
ADMIN --> API
USERS --> TRAEFIK
%% Styling
classDef master fill:#ff6b6b,stroke:#d63031,stroke-width:3px
classDef worker fill:#74b9ff,stroke:#0984e3,stroke-width:2px
classDef service fill:#00b894,stroke:#00a085,stroke-width:2px
classDef external fill:#fdcb6e,stroke:#e17055,stroke-width:2px
class MASTER,ETCD,API master
class WORKER1,WORKER2,WORKER3 worker
class TRAEFIK,METALLB service
class ADMIN,USERS external Why This Architecture: Clear separation of concerns. Control plane manages, workers run workloads, services provide access.
5) Add-Ons and Workloads: Making It Useful¶
Install Helm¶
# Install Helm on your laptop
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Add common repositories
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add metallb https://metallb.github.io/metallb
helm repo update
Why Helm: Package manager for Kubernetes. Makes installing complex applications trivial.
Install MetalLB (Load Balancer)¶
# Install MetalLB
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb -n metallb-system --create-namespace
# Configure IP pool
kubectl apply -f - << EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.100-192.168.1.110
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
EOF
Why MetalLB: Bare-metal load balancing. Gives you LoadBalancer services without cloud provider.
Install Metrics Server¶
# Install metrics server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Verify
kubectl top nodes
kubectl top pods -A
Why Metrics Server: Resource monitoring. Essential for understanding cluster performance.
Install Longhorn (Distributed Storage)¶
# Install Longhorn
helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn -n longhorn-system --create-namespace
# Check status
kubectl get pods -n longhorn-system
Why Longhorn: Distributed storage for persistent volumes. Perfect for Pi clusters.
6) Best Practices for Pi Farm: Production Readiness¶
Node Labels and Taints¶
# Label master node
kubectl label node rpi-master node-role.kubernetes.io/master=true
# Taint master to prevent workloads
kubectl taint node rpi-master node-role.kubernetes.io/master=true:NoSchedule
# Label workers
kubectl label node rpi-worker-1 node-role.kubernetes.io/worker=true
kubectl label node rpi-worker-2 node-role.kubernetes.io/worker=true
kubectl label node rpi-worker-3 node-role.kubernetes.io/worker=true
Why Labels and Taints: Control where workloads run. Keep system pods on master, user workloads on workers.
etcd Backup Strategy¶
# Create backup script
sudo tee /usr/local/bin/etcd-backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/var/lib/rancher/rke2/backups"
mkdir -p $BACKUP_DIR
sudo rke2 etcd-snapshot save --name="backup-$(date +%Y%m%d-%H%M%S)"
find $BACKUP_DIR -name "*.db" -mtime +7 -delete
EOF
sudo chmod +x /usr/local/bin/etcd-backup.sh
# Add to crontab
echo "0 2 * * * /usr/local/bin/etcd-backup.sh" | sudo crontab -
Why etcd Backups: etcd contains all cluster state. Without backups, you lose everything.
Resource Limits and Monitoring¶
# Install Prometheus and Grafana
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
# Check resources
kubectl top nodes
kubectl top pods -A
Why Monitoring: Pi clusters have limited resources. Monitoring prevents overload and helps optimize performance.
Security Hardening¶
# Install Falco for runtime security
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco -n falco-system --create-namespace
# Install Sealed Secrets for secret management
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n sealed-secrets --create-namespace
Why Security: Even lab clusters need security. Good practices scale to production.
7) Scaling the Farm: Growing Your Cluster¶
Adding More Workers¶
# On new Pi, install RKE2 agent
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sh -
# Configure with existing token
sudo mkdir -p /etc/rancher/rke2/
sudo tee /etc/rancher/rke2/config.yaml << EOF
server: https://192.168.1.10:9345
token: <your-existing-token>
EOF
# Start agent
sudo systemctl enable rke2-agent.service
sudo systemctl start rke2-agent.service
Why This Works: RKE2 makes adding nodes trivial. Just configure and start.
External etcd for Large Clusters¶
# For 6+ nodes, consider external etcd
# Dedicate 3 Pis to etcd quorum
# Install etcd on dedicated nodes
# Configure RKE2 to use external etcd
Why External etcd: Large clusters need dedicated etcd for performance and reliability.
High Availability Setup¶
# Add more control plane nodes
# Configure load balancer for API server
# Use external etcd cluster
# Implement backup and disaster recovery
Why HA: Production clusters need redundancy. Plan for failure.
8) Testing the Cluster: Real Workloads¶
Deploy a Geospatial Service¶
# Deploy PostGIS
kubectl create deployment postgis --image=postgis/postgis:15-3.3
kubectl expose deployment postgis --type=LoadBalancer --port=5432
# Check service
kubectl get services
kubectl get pods
Why PostGIS: Real-world geospatial workload. Tests persistent storage and networking.
Deploy a Tile Server¶
# Deploy tileserver-gl
kubectl create deployment tileserver --image=maptiler/tileserver-gl
kubectl expose deployment tileserver --type=LoadBalancer --port=8080
# Access via LoadBalancer IP
curl http://192.168.1.100:8080
Why Tile Server: Tests networking, storage, and performance. Real geospatial workload.
Load Testing¶
# Install hey for load testing
go install github.com/rakyll/hey@latest
# Test API server
hey -n 1000 -c 10 https://192.168.1.10:6443/api/v1
# Test application
hey -n 1000 -c 10 http://192.168.1.100:8080
Why Load Testing: Understand cluster limits. Find bottlenecks before production.
9) Troubleshooting: When Things Go Wrong¶
Common Issues and Solutions¶
# Nodes not joining
# Check firewall ports
sudo ufw allow 9345/tcp
sudo ufw allow 6443/tcp
sudo ufw allow 10250/tcp
# Check kubelet logs
journalctl -u rke2-agent -f
# Check server logs
journalctl -u rke2-server -f
Why These Ports: Kubernetes needs specific ports for communication. Firewall blocks are common.
Performance Issues¶
# Check resource usage
kubectl top nodes
kubectl top pods -A
# Check disk usage
df -h
du -sh /var/lib/rancher/rke2/
# Check memory usage
free -h
cat /proc/meminfo
Why Monitoring: Pi clusters have limited resources. Monitor to prevent overload.
Network Issues¶
# Test connectivity
ping 192.168.1.10
telnet 192.168.1.10 6443
# Check DNS
nslookup kubernetes.default.svc.cluster.local
# Check network policies
kubectl get networkpolicies -A
Why Network Testing: Kubernetes is network-dependent. Connectivity issues break everything.
10) Maintenance and Operations¶
Regular Maintenance¶
# Update system packages
sudo apt update && sudo apt upgrade -y
# Update RKE2
curl -sfL https://get.rke2.io | sh -
# Restart services
sudo systemctl restart rke2-server
sudo systemctl restart rke2-agent
Why Regular Updates: Security patches and bug fixes. Keep your cluster current.
Backup and Recovery¶
# Backup etcd
sudo rke2 etcd-snapshot save --name="backup-$(date +%Y%m%d)"
# Backup kubeconfig
cp ~/.kube/config ~/.kube/config.backup
# Backup certificates
sudo cp -r /etc/rancher/rke2 /etc/rancher/rke2.backup
Why Backups: Disasters happen. Backups enable recovery.
Monitoring and Alerting¶
# Install monitoring stack
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
# Configure alerts
kubectl apply -f - << EOF
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: pi-cluster-alerts
namespace: monitoring
spec:
groups:
- name: pi-cluster
rules:
- alert: HighCPUUsage
expr: cpu_usage_percent > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
EOF
Why Monitoring: Proactive issue detection. Prevent problems before they become disasters.
11) TL;DR Quickstart¶
# 1. Hardware prep
# - 3+ Raspberry Pi 4s
# - SSDs via USB 3.0
# - Gigabit switch
# - UPS backup
# 2. OS setup
sudo apt update && sudo apt upgrade -y
sudo hostnamectl set-hostname rpi-master
# Add cgroups to /boot/firmware/cmdline.txt
sudo reboot
# 3. Install RKE2 master
curl -sfL https://get.rke2.io | sh -
sudo systemctl enable --now rke2-server
sudo cat /var/lib/rancher/rke2/server/node-token
# 4. Install RKE2 workers
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sh -
sudo mkdir -p /etc/rancher/rke2/
echo "server: https://192.168.1.10:9345" | sudo tee /etc/rancher/rke2/config.yaml
echo "token: <your-token>" | sudo tee -a /etc/rancher/rke2/config.yaml
sudo systemctl enable --now rke2-agent
# 5. Test cluster
kubectl get nodes -o wide
kubectl get pods -A
# 6. Install add-ons
helm install metallb metallb/metallb -n metallb-system --create-namespace
helm install longhorn longhorn/longhorn -n longhorn-system --create-namespace
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring --create-namespace
12) The Machine's Summary¶
RKE2 on Raspberry Pi creates a powerful, affordable Kubernetes learning environment. It's not just a toy—it's a mini data center that teaches real orchestration principles.
The Dark Truth: Pi clusters are fragile. Power loss kills them, thermal throttling slows them, and SD cards wear out. But with proper planning, they become reliable learning platforms.
The Machine's Mantra: "In redundancy we trust, in monitoring we observe, and in the Pi farm we find the path to orchestration mastery."
Why This Matters: Understanding Kubernetes on small scale prepares you for production clusters. The principles are the same, only the scale changes.
See also
- Pi-Based Sample Library Server — another production-quality Pi project; deploy the API on your RKE2 cluster
- Docker & Compose Best Practices — container fundamentals before going full Kubernetes
- IAM & RBAC Governance — lock down your cluster with proper RBAC from day one