
Every infrastructure engineer knows the cold sweat. A management node reboots, the compute fleet drops dead, and youâre suddenly staring down a massive outage because you thought you could run a âhighly availableâ cluster without Pacemaker drinking itself to death. You SSH in, frantically type systemctl status nfs-server --failed, and watch the terminal fill with angry red text.
inactive (dead)
Dependency failed for Cluster Controlled nfs-server
Your immediate reaction is to start aggressively forcing services back up. Donât. If youâre dealing with a High Availability (HA) cluster managed by the absolute misery of Corosync and Pacemaker, manual intervention is the fastest way to trigger a glorious split-brain.
That wall of red text isnât a failure. Itâs the system working exactly as designed. Your node isnât broken; itâs just obeying the cluster state machine to prevent a catastrophic storage apocalypse.
The Illusion of Local Failure
On a standalone server, systemd is a simple dictator. A service dies, you restart it, you go drink coffee. In HA land, you have to throw that troubleshooting muscle memory directly in the bin.
When an active/passive cluster node reboots, it wakes up with intentional amnesia. If the cluster already migrated your resources to the peer node, the rebooted node must sit down and shut up.
Sure, we could have over-engineered this with a Kubernetes cluster running on a fleet of multi-million dollar NVIDIA H100s, paying the cloud lock-in tax just to serve a few files. Or we could have filled out endless compliance theater spreadsheets to satisfy NIS2 audits. Instead, we chose the classic, intimate misery of Corosync.
If the node unilaterally started NFS while the other node was also serving it, youâd get a split-brain. Thatâs a one-way ticket to corrupted storage, lost metadata, and a weekend spent explaining why your shared filesystem looks like it went through a blender.
So the cluster forcefully suppresses local services. The node is perfectly fine; itâs just being a compliant subordinate to prevent a data-destroying mutiny.
Anatomy of a Dependency Chain
Pacemaker builds strict, sequential dependency chains because developers canât be trusted to write self-healing code. They assume their app is âproduction-readyâ when itâs actually just three shell scripts in a trench coat, built on a house of cards.
A typical clustered NFS stack looks like this:
- Storage: Mount the underlying block devices (
fs-data-nfs-optcluster). - Network: Bind the Floating Virtual IP (
vip-nfs). - Application: Start the NFS Server (
service-nfs).
This ordering is absolute. If Step 2 fails, Step 3 is dead in the water. The cluster wonât even think about attempting to start the NFS daemon if the virtual IP isnât ready.
When you check the logs and see Job nfs-server.service/start failed with result 'dependency', the system is screaming: âI cannot start because the resource that must happen before me is missing!â
Finding the Real Fire
Recently, one of our management nodes (mgmt-01) bit the dust, leaving dozens of compute nodes hanging while they waited for NFS mounts. The rebooted node was throwing dependency errors left and right, but the actual fire was elsewhere.
I ran pcs status to see what kind of cluster disaster was unfolding:
* Resource Group: nfs:
* fs-data-nfs-optcluster (ocf::heartbeat:Filesystem): Started mgmt-02
* vip-nfs (ocf::heartbeat:IPaddr2): Stopped
* service-nfs (systemd:nfs-server): Stopped
Look at that closely. During the failover chaos, the storage successfully migrated to mgmt-02âwhich, if youâve ever dealt with Lustre split-brains or metadata crashes, is basically a mathematical miracle. But the network stack blinked. The Virtual IP (vip-nfs) failed to bind on the new host.
Since the VIP failed to start, the entire dependency chain snapped. The active node refused to start the NFS service, and the passive node was ordered to stay down. The entire setup was held hostage by one tiny networking hiccup.
Trust the State Machine
The fix wasnât rebuilding the NFS stack or editing local configs. In fact, it was just a single, simple cluster command:
pcs resource cleanup vip-nfs
I ran that on the active node, which cleared the transient error state and forced the cluster to try binding the IP again. As soon as the IP came online, the dependency was satisfied, and NFS spun right up.
The big takeaway? When youâre dealing with HA clusters, local logs will straight-up lie to you. The next time you see a wall of âDependency Failedâ errors after a reboot, take a breath. Donât fight systemd.
Zoom out, query the cluster state machine, and find where the chain is actually broken. Those scary red errors are just the sound of your architecture saving your dataâand sparing you from a NIS2 regulatory compliance audit nightmare.
Itâs almost comforting when the system is smart enough to fail on purpose.