Dev: bootstrap: Reject to remove qdevice when it will cause quorum lost#2041
Dev: bootstrap: Reject to remove qdevice when it will cause quorum lost#2041liangxin1300 wants to merge 2 commits into
Conversation
`crm cluster remove --qdevice` command will be rejected if it will cause quorum lost for the cluster configured with diskless SBD, since the diskless SBD will self-fence the node without quorum
Codecov Report❌ Patch coverage is
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
My question is, why couldn't it remove the on-disk qdevice config and restart the cluster or tell the user to restart the cluster later? Aren't there QDEVICE_RESTART/QDEVICE_RESTART_LATER for the purpose? |
Since when the cluster is using diskless SBD, and the cluster "will" lose quorum after remvoing qdevice, after restart cluster, the existing node will be fenced. Let me summarise all of the cases here:
|
Well, I assume the cause is, stop of corosync-qdevice.service will cause loss of votes right away. So diskless sbd will react if the quorum is lost, given that it's still armed. But how about a direct "systemctl stop corosync" (meaning stopping the cluster stack as a whole). Does it still trigger sbd self-reset in such a situation? |
No, stop corosync will stop everything, including the sbd process |
|
Well, we are talking about how to properly remove qdevice in such a situation by gracefully shutting down the cluster first. First of all, it's not the removal of qdevice config causing loss of votes/quorum. It's stop of "corosync-qdevice.service" alone. Let me elaborate the situation:
Expected votes: 3
Expected votes: 3 Hence loss of quorum and diskless SBD reacts (Don't get confused about the timing of the actual reset, since reset anyway triggers after SBD_WATCHDOG_TIMEOUT since loss of quorum has occurred). Given that the number of expected votes remains, if to remove qdevice, the proper way is to gracefully shut down the cluster stack first of all. And the only graceful way to shut down the cluster stack in such as situation is to shut down it as a whole. Then by removing qdevice config, the "Expected votes" will correspondingly reduce when cluster starts again, so that removal of qdevice won't be an issue. Of course, despite the specific workflow, I'd assume the only reason that an user wants to remove qdevice is in order to change their cluster's topology. For instance for a 2-node cluster, they want to either:
or:
In case we want to proactively prevent users from crippling their cluster according to the requirement "Use diskless SBD only for clusters with more than two nodes, or in combination with QDevice", for example, if diskless SBD still is used, we don't want users to remove qdevice from a 2-node cluster unless they first either add another node or change the fencing mechanism. But that'd be a different topic and a different logic to achieve that, no matter whether loss of quorum could potentially occur and what this workflow should be like. |
This could be rephrased as Along with that, the error message could be tweaked, something like |
I can understand the concern Yan raised above. Basically, the original narrative above is incorrect and misleading the actual workflow. The qdevice removing process doesn't stop qdevice when the cluster is running. In fact, crmsh bootstrap turns on "maintenance" mode first, then disable qdevice before remove it from corosync.conf, and finally restart the whole cluster all together. The tweaked message in the earlier comment explains better. And, one more further rephrase could be like this: |
|
It's fine to leverage maintenance mode. But despite that, as long as a procedure involves restart of the whole cluster, the proper way anyway should be stopping the whole cluster stack altogether. That's basically how a cluster or a cluster partition can gracefully shut down anyways. It just doesn't make sense to split out stop of qdevice and make a stopping cluster to unnecessarily suffer from absolute loss of votes hence possible loss of quorum. Technically it's possible to choose the timings when to "systemctl disable" (without --now) qdevice service and when to remove the on-disk qdevice config. It's just neither sensible nor necessary to stop qdevice alone when a cluster is active and about to stop. Be aware, without qdevice config hence without additional expected votes from qdevice, a single node or 2-node cluster still can start and form a quorate cluster. Even if corosync wait_for_all is enabled, when a partition cannot be quorate until all nodes have come online, diskless SBD won't reset a yet-to-be-quorate node/partition on startup. As said, in case we'd want to enforce qdevice for a cluster with <= 2 nodes and diskless SBD, hence also prevent qdevice from being removed from such a setup, it should be achieved with a different logic or code path, which should be based on how many nodes are configured in corosync's nodelist. |
| quorate = utils.calculate_quorate_status(expected_votes, actual_votes) | ||
| if not quorate and diskless_sbd and mode == QDEVICE_REMOVE: | ||
| # Reject to remove qdevice, as it will lose quorum | ||
| # then diskless SBD will self-fence the node | ||
| return QdevicePolicy.QDEVICE_REMOVE_REJECT |
There was a problem hiding this comment.
| quorate = utils.calculate_quorate_status(expected_votes, actual_votes) | |
| if not quorate and diskless_sbd and mode == QDEVICE_REMOVE: | |
| # Reject to remove qdevice, as it will lose quorum | |
| # then diskless SBD will self-fence the node | |
| return QdevicePolicy.QDEVICE_REMOVE_REJECT | |
| qdevice_votes = pseudo.code.to.get.corosync.conf.quorum.device.votes | |
| quorate = utils.calculate_quorate_status(expected_votes-qdevice_votes, actual_votes-qdevice_votes) | |
| if not quorate and diskless_sbd and mode == QDEVICE_REMOVE: | |
| # Rejected since it would result in a malfunctioning cluster lacking quorum | |
| # either the disk-based sbd cluster or the diskless sbd cluster |
| utils.check_all_nodes_reachable("removing QDevice from the cluster") | ||
| qdevice_reload_policy = qdevice.evaluate_qdevice_quorum_effect(qdevice.QDEVICE_REMOVE) | ||
| if qdevice_reload_policy == qdevice.QdevicePolicy.QDEVICE_REMOVE_REJECT: | ||
| utils.fatal("Can't remove QDevice since the quorum will be lost for diskless SBD cluster") |
There was a problem hiding this comment.
| utils.fatal("Can't remove QDevice since the quorum will be lost for diskless SBD cluster") | |
| utils.fatal("operation is rejected since it would result in a malfunctioning cluster lacking quorum") |
There was a problem hiding this comment.
It wouldn't necessarily become "malfunctioning" purely based on the logic here :-) It's just that the next cluster startup will require an actual majority or "wait_for_all" to become first quorate.
What I can tell about the case in here is, an user may want to remove qdevice when not all cluster nodes are online, right? But actually it's technically feasible no matter what the quorum status is like, as long as the offline nodes are still reachable through ssh.
The actual problem is, after removal of qdevice, if they/we still want to only bring up the same subset of nodes and expect them to reach the status as before the removal of qdevice right away, it won't be in the same condition any more though. But it's actually about how quorum is first granted on cluster startup, which either requires an actual majority or "wait_for_all" (automatically enabled when "two_node" is enabled). But that's reasonable, even if qdevice is not in place.
So to me, this could be a case where we'd rather tell user "I can remove the on-disk configuration of qdevice for you, but you'll either want to restart cluster later manually by yourself, otherwise I can restart the cluster for you now but bring up all the nodes".
BTW, it's really confusing to still call it QDEVICE_RESTART_LATER when it's leveraging maintenance mode and actually restarting the cluster. The name QDEVICE_RESTART_LATER should probably be preserved for the situation where it really requires users to manually restart their cluster by themselves.
After all, as said, to determine whether a cluster would become malfunctioning, the logic in "warn_diskless_sbd()" and the warning there tell the key:
"Diskless SBD requires cluster with three or more nodes. If you want to use diskless SBD for 2-node cluster, should be combined with QDevice."
crm cluster remove --qdevicecommand will be rejected if it will cause quorum lost for the cluster configured with diskless SBD, since the diskless SBD will self-fence the node without quorumFix issue:
cluster remove --qdeviceshould be rejected on the last standing node with qdevice for the 2-node diskless sbd cluster #2039