Skip to main content
RunBook Academy

LinuxLIII · Quorum and Split BrainFailure detection

Failure detection - how a cluster decides a node has failed

Advanced⏱ ~13 mincorosyncpcs

What you'll learn

  • Explain how corosync infers node failure from missed tokens
  • Distinguish node-level detection from resource-level monitor operations
  • Predict what shortening a detection timeout does under load
  • Describe what no-quorum-policy does once quorum is lost

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-11

Not yet marked complete on this device.

Quorum answers “which partition may act”. Before that question can be asked, something has to decide that a node is missing at all. That decision is the least examined part of most cluster designs, and it is the one that fires at three in the morning.

Detection is inference from silence

No cluster ever observes a node dying. It observes that no message arrived within a time limit, and it infers failure from that silence.

This is worth stating in those words, because the whole rest of the discipline follows from it:

  • Silence and death are not the same event. A node can be silent and fully alive - stalled on I/O, swapping, its corosync process starved of CPU, or on the far side of a broken switch.
  • The inference is therefore sometimes wrong, and being wrong is not free: the cluster fences a live node and moves its resources, which is an outage it caused itself.
  • Nothing in the detection layer can close that gap. Only fencing converts “we heard nothing” into “it has stopped”, which is why linux-why-fencing-exists exists as a separate discipline rather than a configuration option.

Node-level detection: the corosync token

Corosync passes a token around the ring. A node that holds the token and does not pass it on is retransmitted to a fixed number of times, and when the token still does not complete its circuit within the token timeout, the ring is declared failed and reformed without that node.

The parameters live in the totem section of /etc/corosync/corosync.conf. Read the values your cluster is actually running rather than trusting any published default - several of them are derived at runtime from the node count, so the effective value is not the one in the file:

Read-only / Safethe effective values, not the configured ones
# corosync-cmapctl | grep -E 'totem\.(token|consensus|join)|runtime\.config\.totem'
runtime.config.totem.token (u32) = 3650
runtime.config.totem.token_retransmits_before_loss_const (u32) = 4
runtime.config.totem.consensus (u32) = 4380
runtime.config.totem.join (u32) = 50

Illustrative output

The two that matter for detection latency:

ParameterRole
tokenHow long the token may be outstanding before the ring is declared failed. This is the dominant term in detection time.
token_retransmits_before_loss_constHow many retransmits are attempted within that window before giving up.
consensusHow long nodes wait to agree on the new membership after the ring fails.

Detection is not instantaneous and not exactly token either: the ring has to fail, a new membership has to be agreed, and Pacemaker then has to act on it. Measure it on your own cluster rather than computing it - stop corosync on a node and time the gap to the membership change in the log on a survivor:

# On a survivor, before you break anything
journalctl -u corosync -u pacemaker -f -o short-iso

Then compare the timestamp of the last healthy token to the Members left line. That number is your real detection latency, and it belongs in the runbook next to the recovery time objective.

Ring health is separate from membership and is the signal that tells you detection is about to get exciting:

sudo corosync-cfgtool -s
sudo corosync-cfgtool -n

A link showing anything other than a healthy status, or a log full of token retransmits, means the cluster is close to declaring a failure that has not happened.

The false-positive trap

Every operator eventually wants faster failover and reaches for the token timeout. It works, and it is one of the more effective ways to cause an outage.

The default is deliberately slack. Corosync is tuned to tolerate a busy production Linux host rather than to minimise failover time on an idle one.

Resource-level detection: monitor operations

Corosync detects nodes. Pacemaker detects resources, and it does so by running the resource agent’s monitor action on a schedule. If the monitor fails, or takes longer than its timeout, Pacemaker treats the resource as failed.

# A monitor operation with an explicit interval and timeout
pcs resource update pgsql op monitor interval=20s timeout=30s

# What is configured now
pcs resource config pgsql

Three properties of this deserve attention:

  • A monitor timeout is treated as a failure. The agent that took too long may have been perfectly healthy behind a slow disk. The same false-positive logic as the token timeout applies, one layer up.
  • The interval bounds your detection time. A resource that died one second after a 20-second monitor completed is undetected for nineteen seconds. Shortening the interval costs CPU and increases false positives.
  • Repeated failures escalate. Pacemaker counts failures per resource per node, and migration-threshold decides when to stop retrying locally and move the resource elsewhere. Without it, a resource can restart in place forever while the service is down.
# Move the resource after 3 failures on a node rather than retrying forever
pcs resource update pgsql meta migration-threshold=3

# Inspect and clear the counters
pcs resource failcount show
pcs resource cleanup pgsql

What happens after the decision

Detection produces a membership change; quorum arithmetic then decides whether this partition may act. If it may not, no-quorum-policy decides what happens to the resources this partition is already running - and the choice is a real decision with real consequences, not a default to inherit.

ValueBehaviour on an inquorate partition
stopStop all resources. The default, and the safe answer for anything touching shared storage.
freezeContinue running current resources, but start nothing new and recover nothing.
demoteDemote promotable resources to the unpromoted role, then act as stop for the rest.
ignoreCarry on as if quorum were held.

demote is the one worth understanding, because it is the honest description of a very common requirement. A demoted database replica is still running and still answers reads; what it will not do is accept writes, because it is no longer promoted. A partition that has lost quorum can therefore keep serving read traffic while being structurally incapable of becoming a second writer.

# Read what is set now, in a form that works on any pcs version
sudo cibadmin --query --scope crm_config

# Set it deliberately
sudo pcs property set no-quorum-policy=demote

The allowed values, and the name of the self-fencing option in particular, have changed across Pacemaker releases. Check the documentation for the version you are running rather than copying a value from a blog post; an unrecognised value is rejected, but a recognised value with different semantics than you expected is silent.

The detection budget

Put the numbers end to end and the recovery time objective becomes arithmetic rather than hope:

Node dies
  + token timeout                  ring declared failed
  + consensus                      new membership agreed
  + fence action                   node proven stopped
  + resource start + monitor       service actually serving
  ------------------------------------------------------
  = time to recovery

The fence term is usually the largest and the most variable, because it depends on a BMC responding. Measuring each term once, on your own hardware, is worth more than any published default - and it is the only way to find out that your fence device takes ninety seconds before anybody is depending on it.

Knowledge check

Knowledge check · 5 questions

  1. Q1. What does corosync actually observe when it declares a node failed?

  2. Q2. Lowering the corosync token timeout is a safe way to reduce failover time, because it only affects how quickly a genuine failure is noticed.

  3. Q3. Which statements about Pacemaker monitor operations are correct? Select all that apply.

  4. Q4. A partition has lost quorum. The requirement is that it keeps answering read queries but can never become a second writer. Which no-quorum-policy expresses that?

  5. Q5. Detection latency should be measured on your own cluster rather than calculated from the values in corosync.conf.

Passing score: 75%. Answers are checked in this browser.