Sahan Serasinghe

Senior Software Engineer | Master of Data Science

Building a Home Lab Kubernetes Cluster with Old Hardware and k3s

2025-07-26distributed systems 6 min read

If you’ve read my previous post about building a Raspberry Pi k3s cluster, you know I’m a huge fan of home labs. There’s something uniquely satisfying about getting distributed systems running on a bunch of hardware you already own. This time, though, I wanted something a bit more powerful-a cluster that could handle not just learning and tinkering, but also heavier dev, CI/CD, and even ML workloads.

And as it turns out, there’s a ton you can do with a handful of old laptops, a simple switch, and Ubuntu Server. If you’re thinking about upgrading your home cluster or want to avoid vendor lock-in, this one’s for you.


Why Move From Raspberry Pi to x86?

Don’t get me wrong-RPi clusters are awesome for learning, hacking, and even some light home automation. But if you’ve ever tried running real dev pipelines, CI/CD, or any data-heavy ML stuff, you’ll hit those limits fast. Plus, WiFi can get a bit flaky when you’re trying to keep nodes connected under load.

I had a few spare laptops sitting around, and it made perfect sense to give them a second life and push them to their limits. Bonus: with Ethernet and a decent switch, you get much more reliable connectivity.

Network Setup: Keep It Simple (and Reliable)

For this build, I kept things straightforward: all nodes are wired to a simple network switch. This gives much better performance and reliability compared to WiFi, but honestly, you could still pull this off over wireless if needed.

Network Switch

My network switch - how it all started 🛜

A quick tip:

  • Reserve static IPs for each node using your router’s DHCP reservations.
  • This makes node management, SSH, and Kubernetes networking so much easier.
  • Check your DHCP table and make sure every machine has a unique, predictable IP address.

Getting Ubuntu Server Set Up on Each Node

Here’s a high level diagram of what my setup looks like:

Home Lab Setup Diagram

Let’s talk about prepping each machine. My old laptops had a new lease on life running Ubuntu Server. I recommend Ubuntu Server LTS for its simplicity and compatibility. If you’re using VMs, just make sure to set the NIC to bridged mode so each VM acts as a full member of your home LAN.

Here’s my go-to checklist for each node:

  1. Update the system and install SSH:

    sudo apt update && sudo apt upgrade -y
    sudo apt install openssh-server -y
    sudo systemctl enable ssh
    sudo systemctl start ssh
  2. Set a memorable hostname:

    sudo hostnamectl set-hostname master   # or worker-1, etc.
  3. (Optional) Update /etc/hosts for local resolution:

    sudo nano /etc/hosts

    Change any lines like 127.0.1.1 old-hostname to your new hostname.

  4. Find your node’s IP address:

    ip a

    Use this IP for your DHCP reservation so it always stays the same.

  5. Test SSH from another machine:

    ssh <username>@<node-ip>

Installing k3s: Lightweight, Powerful, Familiar

This process feels pretty magical the first time you see it all come together. I stuck with k3s-lightweight and perfect for home or edge clusters.

On the Control Plane Node (“master”)

  1. Install k3s:

    curl -sfL https://get.k3s.io | sh -
  2. Check that k3s is running:

    sudo systemctl status k3s
  3. Get your cluster join token:

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

    Copy this somewhere safe-you’ll need it for your worker nodes.

  4. Get the node’s LAN IP:

    ip a

    Let’s say your master node IP is 192.168.0.200.

  5. Check your cluster status:

    kubectl get nodes

If you ever want to reset/reinstall k3s, just run:

sudo /usr/local/bin/k3s-uninstall.sh

On Each Worker Node (“worker-1”, “worker-2”, etc.)

  1. Join the cluster:

    curl -sfL https://get.k3s.io | K3S_URL=https://192.168.0.200:6443 K3S_TOKEN=<your-token-here> INSTALL_K3S_EXEC="--node-ip=<worker-ip>" sh -

    Replace 192.168.0.200 with your control plane’s IP.
    Replace <your-token-here> with the token from your master node.
    Replace <worker-ip> with this worker’s IP, e.g., 192.168.0.201.

  2. That’s it! The node will auto-register with your cluster. No manual kubeconfig needed.

  3. Check the cluster again from the master:

    kubectl get nodes

    You should see both master and your worker(s) as Ready!


Troubleshooting and Gotchas

As with any home lab project, there are always a few snags-here’s what I ran into and how to fix it:

  • Node not joining?

    • Double-check your token (no spaces, copy the whole thing).
    • Make sure you can ping the control plane from your worker node.
    • Firewalls can get in the way. Ensure port 6443 is open between nodes.
    • If you get hostname conflicts, just change the hostname and restart the k3s agent (sudo systemctl restart k3s-agent).
  • Cluster state looks weird after hostname change?

    • You might see both the old and new hostnames in kubectl get nodes. Just delete the old one:
      kubectl delete node <old-node-name>
  • IP address keeps changing?

    • Make a DHCP reservation for each node’s MAC address in your router.
  • WiFi unreliable?

    • Ethernet is always the best bet for clusters, especially for heavy workloads.

What’s Next?

With the basics in place, you’re ready to:

  • Run and test real-world apps and dev environments
  • Build your own CI/CD pipelines
  • Experiment with ML workloads on dedicated nodes

This way, you get all the power of a real Kubernetes lab, but full control and no monthly surprises from a cloud provider.


Lessons Learned

  • RPi clusters are great for edge computing and learning, but once you need real muscle, x86 hardware makes a huge difference.
  • WiFi is convenient, but Ethernet is still king for stable clusters-especially if you’re doing anything performance-sensitive.
  • Old laptops/desktops are a goldmine for home lab builds. Don’t let them collect dust!

Final Thoughts

If you have old machines and a bit of curiosity, you can build a cluster that’s surprisingly capable-no Raspberry Pis required.
And if you’ve already done it with RPis, this is the perfect upgrade path.
Keep an eye out for my next post where I’ll deep-dive into adding observability and tooling!

Happy clustering! 🫡

Sahan Serasinghe - Engineering Blog

Sahan Serasinghe Senior Software Engineer at Canva | Azure Solutions Architect Expert | Master of Data Science at UIUC | CKAD