Building a Production-Ready Kubernetes Cluster on Ubuntu 24.04 LTS (with Cilium CNI)

Build a production-ready 4-node Kubernetes cluster on Ubuntu 24.04 LTS — from bare VMs to Cilium CNI with Hubble observability. Includes every gotcha we hit so you don't have to.
Building a Production-Ready Kubernetes Cluster on Ubuntu 24.04 LTS (with Cilium CNI)

On this page

So you've got a few VMs sitting around and you want to stand up a real Kubernetes cluster — not Minikube, not Kind, not MicroK8s. A proper multi-node cluster with a dedicated control plane, worker nodes, and a modern CNI. This is that guide.

I recently built a 4-node cluster from scratch on Ubuntu 24.04 LTS VMs: 1 master, 3 workers — migrated the CNI from Flannel to Cilium, and wired up Hubble for real-time observability. Along the way I hit a handful of Ubuntu 24.04-specific gotchas that aren't well documented. I'm going to walk you through the whole thing, war stories included.

The Setup

Node IP Role
k8s-master 192.168.2.134 Control plane
k8s-worker-1 192.168.2.135 Worker
k8s-worker-2 192.168.2.136 Worker
k8s-worker-3 192.168.2.137 Worker

All nodes: Ubuntu 24.04.4 LTS, ARM64 (aarch64), kernel 6.8.0, containerd 2.2.1, Kubernetes 1.31.14.

Phase 1: Common Setup (All Nodes)

Before anything Kubernetes-specific, every node needs the same baseline configuration. This is the stuff that has to be right or everything downstream breaks.

Disable Swap (Properly)

Kubernetes requires swap to be off. Ubuntu 24.04 uses zram-based swap by default, which swapoff -a alone won't permanently disable. You need all three:

swapoff -a
sed -i '/\bswap\b/s/^/#/' /etc/fstab
systemctl mask swap.target

The systemctl mask swap.target is the part most guides miss. Without it, swap comes back after a reboot on Ubuntu 24.04.

Kernel Modules (Persistent)

cat > /etc/modules-load.d/k8s.conf <<'EOF'
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

sysctl Networking

cat > /etc/sysctl.d/k8s.conf <<'EOF'
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sysctl --system

This post is for subscribers only

Subscribe to LevelUp I.T. newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox. It's free!
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!