Five-node Proxmox and Ceph cluster on mixed Dell and HPE hardware
The first version of this lab cluster kept one copy of its data and lost it when a single node was corrupted. I rebuilt it on two Dell and three HPE servers so any one node can fail while VMs keep running and storage keeps serving. Hardware alerts catch failing parts early, fencing makes failover safe, and drifted nodes return to the CIS Level 1 baseline without anyone logging in.
Survives 1 node- Role
- Project lead
- Scale
- 5 nodes, 30 × 1 TB HDD, ~15 TB usable
- Stack
- Proxmox VE, Ceph, CephFS
- Targets
- Survive 1 node, CIS Level 1, monitored
Context
I led the rebuild at a system integrator I have since left. The cluster was the team's internal lab: we ran test VMs and containers on it, and evaluated tools there before recommending them to customers. This page describes it as it stood when I left.
I designed the rebuild so the cluster keeps its data, and keeps serving it, when any one node fails. Everything below follows from that goal.
The hardware is five bare-metal servers, two Dell and three HPE, with seven drive bays each. One bay holds an SSD that boots Proxmox VE. The other six hold 1 TB HDDs, and every HDD belongs to Ceph: 30 disks, about 30 TB raw.
Constraints:
- Mixed vendors and disk models in one cluster
- SSDs are reserved for the hypervisor OS; Ceph gets HDDs only
- Internal lab: one site, no disaster recovery, no backup outside Ceph
- Hardened to CIS Level 1 plus a Proxmox hardening checklist
Architecture and failover
Compute: Proxmox VE with HA
All five nodes run Proxmox VE and host VMs and containers. Corosync gives each node one vote, so the cluster keeps quorum while three of five are up. One HA group covers every node.
When a node stops responding, the HA manager waits for it to be fenced: its local watchdog resets it, and IPMI confirms the power is off. Only then does Proxmox restart its VMs on the surviving nodes. Fencing first means a VM can never run on two nodes at once against the same disk.
Storage: Ceph on every node
Every node runs Ceph next to its VMs:
- One OSD per HDD, 30 in total, holding the data.
- A monitor per node. The five monitors hold the cluster map and keep quorum while three are up.
- Managers, which run the health checks and report metrics.
- Metadata servers for CephFS.
Proxmox stores VM and container disks as block devices, so those live on RBD. ISO images, templates, scripts and notes are files, so they live on CephFS. Each use has its own pool.
The fix for the first version's failure is erasure coding. Ceph splits each object into data chunks and parity chunks and spreads them across nodes, so no single node holds enough of an object to make it unreadable. When a node fails, Ceph reads every object from the other four and I/O keeps running. Half of raw capacity stays usable, about 15 TB. Each erasure-coded pool is paired with a small replicated pool, at three copies, for metadata.
Until the failed node returns, or Ceph rebuilds its chunks elsewhere, the pools run with less redundancy. A second node failure in that window puts data at risk.
Keeping nodes up: alerts before failures
Erasure coding handles a node that fails. The BMCs reduce how often that happens. iDRAC on the Dell servers and iLO on the HPE servers report failing parts over IPMI before they take a node down: a disk with rising SMART errors, a power supply or fan going bad, memory errors. A disk that predicts its own failure is drained and swapped while it still works.
The watchdog does a different job. It cannot prevent a fault, but when a node hangs it resets that node, so HA can safely move its VMs. The alerts shorten how long nodes are down; the watchdog shortens how long VMs are down.
Operations: logs, drift and the baseline
Every node sends system, Ceph and audit logs to ELK, alongside the BMC alerts. The team ran several ELK stacks side by side, partly to compare them before recommending one to customers.
An n8n workflow reads alerts and configuration-change events from ELK. It notifies the team when a service or node misbehaves, and an AI step writes a daily performance summary. When a node drifts from the CIS Level 1 baseline, n8n calls a CI/CD webhook, and the pipeline re-applies the baseline from git. The AI step reports and never writes a change to a node.
Try it: fail a node, catch a disk before it dies, cut power to the whole site, or break the CIS baseline and watch the pipeline restore it. Timings are illustrative, based on Proxmox HA and Ceph defaults.
- Primary / serving
- Recovering
- Degraded
- Down
- Replication / control
Pick a failure to see how the system detects and recovers from it.
Key decisions
Ceph on every node instead of local or external storage
VMs had to restart on any node, and ISOs, templates and scripts had to be reachable from all five servers.
Trade-off: The HDDs set the speed limit, and Ceph needs its own monitoring and spare capacity.
Erasure coding per node, after a version with no redundancy
The first pools kept one copy of each object. When a node was corrupted, no second copy existed to rebuild from.
Trade-off: Erasure-coded writes and rebuilds are slower than plain copies, and the gap is wider on HDD.
SSD for the hypervisor, HDDs for Ceph
Each node has seven drive bays: one SSD and six 1 TB HDDs. The SSD is reserved for the Proxmox OS.
Trade-off: Ceph runs on HDD only, so every write waits for the slowest disk.
One HA group fenced by watchdog and IPMI
Proxmox can only restart a VM safely once the failed node is certainly off. Otherwise two copies of the VM can write to one disk.
Trade-off: One group means no placement preferences, and there is no second site for disaster recovery.
n8n detects drift, the pipeline restores the baseline
Raw ELK alerts are noisy, nobody reads a day of logs to find slow trends, and a node that drifts from CIS Level 1 stays non-compliant until someone notices.
Trade-off: A deliberate manual change on a node is reverted too, unless it goes through git first.
Lifecycle
Ceph treats a missing disk as lost and starts copying its data to other disks to restore redundancy. On HDDs that copy takes hours. So planned work starts by telling Ceph the disk or node will be back, and every routine waits for storage to report healthy before it touches the next node or disk.
- Install Proxmox VE on the node's SSD.
- Harden it to the CIS Level 1 baseline before it joins, so no unhardened node ever enters the cluster.
- Join it to the cluster. The node now has a vote in deciding which nodes are alive.
- Give its six HDDs to Ceph, one storage service per disk (an OSD), and start a monitor on it. Ceph adds the node to its map of disks and moves a share of the existing data onto it.
- Done when storage reports healthy (
ceph -sshowsHEALTH_OK) and the cluster counts the new vote (pvecm status).
- Tell Ceph a planned reboot is coming (
ceph osd set noout). Without it, Ceph would treat the node's disks as failed and start hours of copying for a reboot that takes minutes. - Move the node's VMs to other nodes while they keep running (live migration).
- Update and reboot. Storage keeps serving from the other four nodes.
- Once the node is back and storage reports healthy, clear the flag (
ceph osd unset noout). - Move to the next node. Patching one node at a time means only one is ever missing, which is all the cluster is built to absorb.
- The node's management controller (iDRAC on Dell, iLO on HPE) sees a disk wearing out and raises an alert, which reaches the team through ELK and n8n.
- While the disk still works, tell Ceph to stop using it (
ceph osd out <id>). Ceph copies the disk's data to other disks, so the cluster never runs short of redundancy. - Wait until the copy finishes and storage reports healthy.
- Swap the disk with the node still running, and give the new disk to Ceph (
pveceph osd create /dev/sdX). - If a disk dies without warning, Ceph waits 10 minutes in case it comes back, then rebuilds the missing data from the parity on other disks. The result is the same, but the cluster has less margin until the rebuild finishes.
- Every node sends its system, storage and audit logs to ELK, plus hardware alerts from its management controller.
- n8n reads those logs. It tells the team when something breaks and writes a short daily performance summary.
- When a node's security settings drift from the CIS baseline, n8n triggers the CI/CD pipeline.
- The pipeline re-applies the reviewed baseline from git. Nobody logs in to fix the node by hand.
Failure modes
| Failure | Blast radius | Detection | Recovery |
|---|---|---|---|
| One node lost | Its VMs restart elsewhere in ~2 min; Ceph keeps serving with less redundancy | Corosync, HA manager, ELK alert | Automatic fence and VM restart; full redundancy once the node returns or its chunks are rebuilt |
| Second node lost before recovery | Data at risk | Ceph health | Bring a node back; there is no backup to restore from |
| Failing part (disk, power supply, fan, memory) | None if replaced in time | iDRAC or iLO alert over IPMI | Drain or migrate, then replace the part |
| HDD fails with no warning | No VM impact; less redundancy until backfill ends | Ceph health, ELK | Automatic backfill, then replace the disk |
| Site power lost | Everything stops: all VMs and all storage | Everyone at once | Restore power; Ceph recovers from acknowledged writes, then HA starts VMs |
| Network partition | The minority side loses Corosync and monitor quorum and fences itself | Corosync, Ceph monitors | Automatic on the majority side (3 of 5) |
| Pool corrupted by a bad change | Every VM, ISO, template and script in that pool | Ceph health | None: no backup outside Ceph |
| Configuration drift | One node off the CIS baseline | ELK change log, n8n rule | Automatic: n8n calls the CI/CD webhook, the pipeline re-applies the baseline |
| Slow writes | VM disk latency under heavy I/O | Daily performance summary | Design limit of HDD-only erasure coding |
Results
How the 99.99% is calculated
Ceph stops serving only when two or more of the five nodes are down at the same moment. Assume each node is up 99.7% of the time, about 26 hours of downtime a year, and that nodes fail independently. Two of them are then down together about 0.009% of the time, roughly 47 minutes a year:
storage availability ≈ 1 − 10p² p = 0.003 → ≈ 99.991%
This is an estimate from the design, not a measured uptime. The BMC alerts are what keep p that low, because most failing parts get replaced before they take a node down.
The estimate leaves out failures that hit every node at once. The cluster runs 24/7 on one site, so a power cut stops all five nodes together, and so would losing the network they share or a bad change pushed to every node. A power cut means a full outage, not lost data: Ceph confirms a write only once enough chunks are on disk, so the cluster comes back with every write it acknowledged, as long as no disk or controller held writes in a volatile cache.
What I'd change
I would add a backup outside Ceph, such as Proxmox Backup Server. Erasure coding keeps data available through disk and node failures, but a bad command or a corrupted pool reaches every chunk at once, the same kind of event that destroyed the first version.
I would make site power the next fix: a UPS with a scripted clean shutdown turns a power cut from a crash into a planned stop.
I would give Ceph a small flash device per node for its metadata and write-ahead log, or move VM disks to a replicated pool. On HDD-only erasure coding, every write waits for the slowest disk, and mixed disk models widen that gap.
Once the ELK evaluation ends, I would consolidate to one stack and document which logs the AI summary may read.