xnett.org

/var/www/xnett.org/homelab/proxmox-cluster-two-nodes-and-a-quorum-lesson.md

[HOMELAB]

Proxmox cluster: two mismatched nodes and a quorum lesson

Running a Proxmox VE cluster on an i7-4790K and a 4-thread mini PC: cloud-init VMs, local LVM, NFS backups, a witness VM for quorum and why CPU overcommit hit DNS first.

author:
Rolf
date:
2026-09-29 22:48
read:
~3 min

The virtualization layer is two Proxmox VE nodes in one cluster. They are very different machines, and most of what I've learned about running this lab has come from that mismatch.

The nodes

Node A Node B
CPU Intel i7-4790K, 4 cores / 8 threads Intel i7-7567U, 2 cores / 4 threads
RAM 32 GB 32 GB
Network 3 × 1 GbE in an LACP bond + dedicated mgmt NIC Single NIC, VLAN-aware bridge
Local storage Three LVM volume groups (~2.3 TB) One ~1 TB directory store

Node A is an old desktop platform that refuses to die. Node B is a small-form-factor box that sips power. Both run the same Proxmox VE version and the same network pattern: a VLAN-aware bridge that VMs attach to with a tag.

What runs where

VMs are spread so that anything with a twin lives on the other node from its twin:

Workload Node A Node B
Docker host #1 (8 vCPU, 12 GB) #2
Pi-hole DNS secondary primary
UniFi controller ✓
Jumphost (admin, Ansible, Git) ✓
HA witness ✓
Lab VMs (k3s, portal, macOS) ✓ (started on demand)

Building VMs from cloud images

No ISO installs. New VMs are AlmaLinux GenericCloud qcow2 images imported directly and configured with Proxmox's built-in cloud-init:

bash
qm create 120 --name lab-vm --memory 4096 --cores 2 \
  --net0 virtio,bridge=vmbr0,tag=<vlan> --scsihw virtio-scsi-single
qm importdisk 120 AlmaLinux-10-GenericCloud-latest.x86_64.qcow2 local-lvm
qm set 120 --scsi0 local-lvm:vm-120-disk-0 --boot order=scsi0 \
  --ide2 local-lvm:cloudinit \
  --ciuser admin --sshkeys ~/.ssh/authorized_keys \
  --ipconfig0 ip=dhcp
qm resize 120 scsi0 +30G
qm start 120

Cloud images run a package upgrade on first boot. If that pulls a newer kernel, modules like kernel-modules-extra get installed for the new kernel while you're still running the old one. Docker's iptables rules then fail with an addrtype error until you reboot. Reboot once after first boot and move on.

Storage

  • Local LVM on each node for VM disks: fast, simple, no shared-storage dependency.
  • NFS share on the NAS for backups (vzdump).
  • SMB share on the NAS for ISOs and templates, visible to both nodes.

There is no Ceph and no shared VM storage. With two nodes and 1 GbE it would cost more than it gives. Live migration isn't the goal; fast restore is.

The quorum lesson

The cluster was built for three nodes. Right now the third is offline, so the cluster runs on two votes out of three: still quorate, but with zero margin. Lose one node and the other goes read-only for cluster operations until the third comes back.

bash
pvecm status | grep -E "Expected votes|Total votes|Quorate"

For Proxmox itself that's a known, accepted trade-off. For the application HA stack (etcd and Redis Sentinel behind Ops Center) it wasn't acceptable. I added a tiny witness VM (2 vCPU, 2 GB) whose only job is to be the third member. It sits on the smaller node on purpose: the scenario I care about is patching and rebooting the big node, and with the witness on the other side, quorum survives that.

CPU overcommit is real

Node B has 4 threads. At one point its VMs added up to 16 vCPUs, and the host load sat at saturation. The first thing to suffer wasn't the busy VM. It was the primary DNS server on the same node, which started timing out while the secondary on the other node was fine. That asymmetry is what gave it away.

The fixes:

  • Cap the noisy VM instead of trusting the scheduler: qm set <vmid> --cpulimit 2
  • Move demo/test stacks off the small node entirely
  • Treat vCPU totals per node as a budget, not a free-for-all
bash
# quick overcommit check per node
qm list | awk 'NR>1 && $3=="running"{print $1}' | \
  xargs -I{} qm config {} | awk '/^cores:/{s+=$2} END{print s " vCPU allocated"}'
nproc

Backups

Weekly vzdump jobs write every VM to the NAS over NFS, with Proxmox notifications routed into my monitoring. The backup share is the current bottleneck: the biggest Docker host alone is several hundred GB, so the next upgrade is either more space or Proxmox Backup Server with deduplication.

# EOF