Skip to content
article

Four Pi 5s, one k3s cluster: full build log, what went wrong, and why I'd buy a mini PC next time

Parts list, every command, power numbers off the wall meter, and an honest verdict

Matt O'Brien@pi_tinker_matt

August 11, 2026 · 6 min read

G'day legends. This took three weekends, two trips to Jaycar and one very long conversation with the wife about "what exactly is a control plane". Years ago Jeff Geerling's Pi Dramble videos put the idea in my head and it never left, so if you've not seen the original, start here:

This is the full log. Every command I ran, everything that went wrong, and at the end an honest answer to "should you build one".

Parts list

  • 4 × Raspberry Pi 5, 8GB
  • 4 × official Active Cooler
  • 4 × M.2 HAT+ with a 256GB NVMe each
  • 4 × official 27W USB-C power supply (more on why below)
  • 1 × 5 port gigabit switch, unmanaged, nothing fancy
  • 4 × short Cat6 patch leads, a 120mm USB fan, and a rack I printed in PETG

All up just under AU$1,100, which is a number I have not said out loud in the house.

Step 1: flash and name them

Raspberry Pi OS Lite, 64-bit. I flashed each NVMe directly from my laptop in a USB M.2 enclosure using Raspberry Pi Imager, which is faster than any clever cloning. In Imager's settings I set the hostname (node1 to node4), a user, my SSH public key, and turned off password login. Then DHCP reservations on the router so they're always 192.168.1.51 to .54.

Step 2: boot from NVMe

With the official HAT+ the PCIe port switches on by itself. On the cheap third party HAT I tried first I had to add this to /boot/firmware/config.txt:

dtparam=pciex1
# optional, not officially supported, works on mine, don't blame me:
dtparam=pciex1_gen=3

Then set the boot order so it tries NVMe first:

sudo rpi-eeprom-config --edit
# set:
BOOT_ORDER=0xf416

Read it right to left: 6 is NVMe, then 1 is SD, then 4 is USB, then f means start over.

Step 3: turn on the memory cgroup

This is the one that gets everybody. Pi OS ships with the memory cgroup disabled and k3s refuses to start without it. The log tells you exactly what to do, which is nice of it:

Failed to find memory cgroup, you may need to add "cgroup_memory=1 cgroup_enable=memory" to your linux cmdline (/boot/cmdline.txt on a Raspberry Pi)

On Bookworm the file is /boot/firmware/cmdline.txt. It's ONE line. Add this to the end of that line, don't put it on a new line:

cgroup_memory=1 cgroup_enable=memory

Reboot all four.

Step 4: install k3s

On node1, the server:

curl -sfL https://get.k3s.io | sh -s - server \
  --write-kubeconfig-mode 644 \
  --disable servicelb \
  --node-ip 192.168.1.51

sudo cat /var/lib/rancher/k3s/server/node-token

On node2, node3 and node4, the agents, using that token:

curl -sfL https://get.k3s.io | \
  K3S_URL=https://192.168.1.51:6443 \
  K3S_TOKEN=K10...the-long-token... \
  sh -

Back on node1:

$ kubectl get nodes
NAME    STATUS   ROLES                  AGE
node1   Ready    control-plane,master   41m
node2   Ready    <none>                 6m
node3   Ready    <none>                 5m
node4   Ready    <none>                 5m

(I trimmed the version column, it'll be newer by the time you read this.) To drive it from the laptop:

scp node1:/etc/rancher/k3s/k3s.yaml ~/.kube/config
sed -i 's/127.0.0.1/192.168.1.51/' ~/.kube/config

Step 5: MetalLB for real IPs

k3s comes with its own little load balancer (ServiceLB, the old klipper-lb) and honestly it's fine. I disabled it because I wanted every service to get its own LAN IP, so Pi-hole can be .240 and Grafana .241 and so on.

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml

Then tell it which addresses it may hand out (keep these outside your router's DHCP range!):

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: lan
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: lan
  namespace: metallb-system

Step 6: storage

k3s ships the local-path provisioner, so a PersistentVolumeClaim just works, but the volume lives on one node and the pod is stuck to that node forever. I tried Longhorn for replicated storage. It needs open-iscsi on every node and it felt heavy on the Pis, so I backed it out. Anything that needs to move between nodes now uses an NFS share off the NAS. Not elegant, works.

What went wrong

1. Power (the big one)

First attempt I used a single 100W four port USB-C charger to power all four. Tidy! Wrong. The Pi 5 wants 5V at 5A. On a charger that only offers 3A per port it limits USB current and tells you so at boot ("This power supply is not capable of supplying 5A"). Under load node3 kept browning out:

$ vcgencmd get_throttled
throttled=0x50005

That's under-voltage right now, throttled right now, and both have happened since boot. Four official 27W bricks on a power board later: throttled=0x0 on every node for six weeks. Ugly, but zero throttling.

2. Thermals

In my lovely printed rack the coolers on node1 and node2 faced each other, so node1 blew its hot air straight into node2's intake. node2 sat at 81°C under load while the others were in the 60s. Turned all four the same way and put a 120mm USB fan behind the rack. Max under stress-ng now is 58°C.

3. HA etcd

One server uses SQLite under the hood and that's fine. Being me, I then rebuilt with three servers and embedded etcd (--cluster-init on the first one) for "high availability". On NVMe it's alright. On my test run with SD cards etcd spammed "apply request took too long" and leader elections all night. If you're on SD cards, do not do HA etcd. Just don't.

4. arm64 images

Half the random Docker images I wanted were amd64 only. Before you get attached to one, check:

docker manifest inspect some/image:tag | grep architecture

Power numbers (wall meter, all four nodes plus switch plus fan)

  • Idle: 19W
  • All four flat out with stress-ng: 46W
  • Average over a week with my actual stuff running: 22W

22W around the clock is about 16 kWh a month. At roughly 33c a kWh that's a bit over five bucks a month. Cheaper than I expected.

What actually runs on it

Pi-hole (on its own MetalLB IP), Uptime Kuma, Gitea, Mosquitto for the weather station, and Prometheus plus Grafana. Prometheus retention is set to 7 days because it'll happily eat a whole NVMe.

Would I build it again?

For learning Kubernetes: absolutely. Nothing teaches you how a cluster behaves like yanking a power cable out on purpose and watching what happens. I understand pods, scheduling and node failure properly now in a way I never did from videos.

For running services? Honestly, no. A second hand mini PC with an 8th gen i5 costs less than half of this, idles at about the same wattage, runs every amd64 image on earth, and one box can't have a network partition with itself. If you want to learn k8s, build the Pi cluster. If you want Jellyfin, buy the mini PC. Both are fine answers, just know which question you're asking.

Next up: pulling node2's plug on purpose and timing how long things take to come back. Spoiler, longer than you'd think. A node goes NotReady after about 40 seconds, but by default the pods on it aren't evicted for five minutes.

cheers, Matt 🍓

Written by

Matt O'Brien

Brisbane maker. I put Raspberry Pis in things that did not need Raspberry Pis. 400k on YouTube, a shed full of half-finished builds and a very patient wife. Parts lists always included 🍓

Get the best of #raspberry_pi_lab weekly

One email each Monday with the most useful posts. No spam; unsubscribe in one click.

Comments

35

Sign in to join the conversation.

Sign in to comment
Lena Hoffmann@arch_btw_lena3 rep in Pi Lab
"it's ONE line" in bold should be printed on every pi box. i lost an evening to a newline in cmdline.txt once. great writeup
19 net votes
Graham Whitfield@greybeard_graham#7 in Pi Lab
Best thing I have read on here this month. The verdict at the end is the bit most people leave out. Building it to learn and building it to run things are different projects, and it is good to see someone say so plainly. Cheers, G.
10 net votes
S. Ramanathan@ramanathan_retd#6 in Pi Lab
Dear Matt, A very instructive post. I confess I understood perhaps half, but the half I understood was explained better than many manuals I read in 34 years. I shall stay with my one Pi for now. With regards, S. Ramanathan
14 net votes
Alasdair Reid@onprem_or_die2 rep in Pi Lab
four computers and a printed rack to run pi-hole. the YAML generation strikes again
16 net votes
Lindiwe Mokoena@loadshedding_lindi1 rep in Pi Lab
22W average is lekker though. that's nothing on an inverter. my whole lab has to get through stage 4 on one battery so I read the power section first and the kubernetes second 😂
15 net votes
Hamish Turner@hamish_on_the_farm#3 in Pi Lab
mean as Matt. the bit about pods not moving for 5 min is exactly the kind of thing you only find out when it matters. chur
11 net votes
Oleksii Bondarenko@oleksii_kyiv1 rep in Pi Lab
22W is very interesting number for me. our power station keeps the router and one laptop alive during blackout, this cluster it could also keep for many hours. maybe I build it only to have something to do in the dark)))
15 net votes
Dazza@dazza_rates_ur_desk#9 in Pi Lab
mr blinky lights has built a rack of blinky lights. 4/10. the printed rack is doing a lot of heavy lifting in that sentence
16 net votes
Rizal Pratama@rgb_rizal1 rep in Pi Lab
please share photo of the rack!! how you route 4 power brick + 4 lan + fan cable? this is what I want to know ✨
10 net votes
Dazza@dazza_rates_ur_desk#9 in Pi Lab
he doesnt route them rizal. thats the point. bird nest confirmed
11 net votes
Karthikeyan S@karthik_embedded#2 in Pi Lab
The throttled=0x50005 part is the most useful line in this post. People blame software for power problems all the time. If you measure the 5V rail at the GPIO header with scope during load you will see dips that multimeter never shows.
17 net votes
Nguyễn Minh Hiếu@homelab_hieu#4 in Pi Lab
very very good write up Matt. I agree 100% with the verdict. my k8s learning was also on 3 Pi 4, my real services are on Proxmox mini PC. one more tip for people: set Prometheus retention by size not only by time, --storage.tsdb.retention.size=20GB, then it cannot eat the disk even if you add more exporters later. hope this help :)
10 net votes
Chaminda Perera@chaminda_sysops2 rep in Pi Lab
Very nice. In the bank we would call this a test environment and then someone would put production on it within six months, I am telling you. Be careful the family does not start depending on that Pi-hole.
13 net votes
Prashanth Gowda@prashanth_sre1 rep in Pi Lab
ok i dont normally comment but kubernetes on a tiny budget is my one topic so here goes. 1. the 5 minute eviction thing: you can tune it per pod with tolerations for node.kubernetes.io/unreachable and node.kubernetes.io/not-ready, tolerationSeconds: 30. dont do it cluster wide, do it for the stuff you care about like pi-hole. 2. for pi-hole specifically run 2 replicas on different nodes with a podAntiAffinity, and give the router both IPs as DNS. otherwise your whole house loses internet when you test failure and your wife will notice before grafana does 3. local-path + node failure = pod stuck Pending forever, because the PV has node affinity. thats not a bug, thats what local-path means. nfs is the right call for anything that moves 4. k3s ships traefik, if you also install nginx ingress because a tutorial said so you now have two ingress controllers fighting. ask me how i know 5. etcd on SD is pain, agree 100%. on NVMe its fine for 3 nodes solid post matt. saving it
16 net votes
Ryan Goh@ai_maxi_ryan3 rep in Pi Lab
respect the grind but why write all this yaml by hand in 2026? just ask claude to generate the helm charts and the whole cluster config. 4 seconds 🚀🤖
11 net votes
Graham Whitfield@greybeard_graham#7 in Pi Lab
Ryan, the point of the exercise is to learn how it works. A machine that writes the YAML for you teaches you how to ask a machine to write YAML. That is a different skill, and a much less useful one at three in the morning when the machine's YAML is wrong. Cheers, G.
14 net votes
Ryan Goh@ai_maxi_ryan3 rep in Pi Lab
ok boomer. skill issue. the future doesnt care about your tomatoes uncle, it cares about shipping. dinosaurs gonna dinosaur
-17 net votes
Alasdair Reid@onprem_or_die2 rep in Pi Lab
away and bile yer heid ryan. the man has kept more servers alive than you've had pivots
25 net votes
Nguyễn Minh Hiếu@homelab_hieu#4 in Pi Lab
please calm down both :) this is a good thread, let's keep it about the cluster
17 net votes
Gwen Albright@gwenprints#4 in Pi Lab
Okay but the rack! Is it PETG? Share the STL please (and did you put heat-set inserts in it or are the Pis on self tapping screws (I will judge you only a little))
15 net votes
Trey Robinson@techwithtrey3 rep in Pi Lab
Here's the thing, the verdict section is why I trust Matt over most of YouTube. "Build it to learn, buy the mini PC to run stuff" is the honest answer nobody wants to put in a thumbnail. Bookmarked 🔥
13 net votes
Daan Visser@daan_fpga4 rep in Pi Lab
Nice log. A little bit of a side note on the PCIe gen 3 setting: on my Pi 5 it worked fine with one NVMe and gave errors in dmesg with another one (AER messages, how it's called, "corrected error"). So if you use gen 3, check dmesg after a big copy, not only that it boots.
19 net votes
Sam Whitaker@segfault_sam3 rep in Pi Lab
"one very long conversation with the wife about what exactly is a control plane" is the most relatable sentence in the history of this website
16 net votes
Karl Lindqvist@kernel_karl2 rep in Pi Lab
One server and SQLite would have been enough. HA etcd at home buys you three ways to fail instead of one. Good post otherwise.
14 net votes
Jordan Pike@jpike1 rep in Pi Lab
I run k8s at work for a living and this is a better explanation of eviction and local-path than half our internal docs. The "know which question you're asking" line is going in my next onboarding doc, with credit.
15 net votes
Matt O'Brien@pi_tinker_matt#1 in Pi Lab
Cheers everyone, didn't expect this many! Answering a few: Gwen: PETG, M2.5 heat-set inserts, I'm not a monster. STL is on my Printables, I'll link it in the next post. Prashanth: mate, that comment is better than my post. Doing the 2 replica Pi-hole this weekend, the wife has already noticed once. Karl: yeah, fair. The HA etcd was 100% "because I could".
17 net votes
Marcus Johnson@marcus_oncall1 rep in Pi Lab
On-call person here. The tolerationSeconds tip from @prashanth_sre is the real gold in this thread. Five minutes is a very long time when the thing that's down is DNS.
16 net votes
Frank Ostrowski@frank_cpp982 rep in Pi Lab
Four computers to serve a web page and a DNS cache. In 1994 we ran a whole plant floor on one 486. That said, the power and thermal sections are proper engineering. Regards.
15 net votes
Leo Chen 陈立@szhw_leo#8 in Pi Lab
For people who copy this with cheap NVMe HAT: some clone HAT have no proper 3.3V regulator for the SSD, only pass through. Then high power NVMe brownout under write. Official HAT+ or check the board have own regulator.
12 net votes
Diego Ramírez@diego_firmware2 rep in Pi Lab
The fan of one node blowing into the other node is a classic. In automotive we have ECUs in the same box doing exactly this and somebody always discovers it in the summer test. Nice post Matt
10 net votes
Matt O'Brien@pi_tinker_matt#1 in Pi Lab
Righto, play nice everyone. Ryan, you're welcome to post your generated config and we'll run it on node4. If it works I'll say so on camera. Leo, good shout, the first cheap HAT I tried was exactly that. Back in the box it went.
13 net votes
Rhys Llewellyn@rhys_teaches_code2 rep in Pi Lab
Showing the "pull a plug and watch what happens" part to my A level class next week. They have only ever seen Kubernetes as a word on job adverts. Diolch Matt, this is tidy.
12 net votes
Bikash Kalita@bikash_from_ghy1 rep in Pi Lab
Coming back to this for the third time. Decided to go the mini PC route after reading the verdict, my use case is Jellyfin and Nextcloud and not learning k8s. Saved me about 20k rupees probably. Thank you Matt
14 net votes
Jaxon Pearce@j4x0n_mods#9 in Pi Lab
bro i read this 3 times. saving up for 4 pis rn, is 1 pi enough to start or do i need all 4 to learn k8s
14 net votes
Matt O'Brien@pi_tinker_matt#1 in Pi Lab
One is plenty to start mate. k3s runs fine on a single Pi 4 or 5, the server is also a node. Learn deployments, services and ingress on one, then add a second when you want to see what happens when one dies. Don't spend $1,100 at 16, spend $100 and learn heaps
6 net votes