WIP:Fix/mongo init container stuck - #307
Open
Plesoun wants to merge 8 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MR — mongo-init.js: preserve-live priority in
mergeLiveMemberWithDesired+ full PSA test suiteCluster under test: lmio-jaguar (dev/test PSA). Nodes:
lmio-jaguar10.17.170.21 — mongo-1lmio-gepard10.17.174.110 — mongo-2lmio-ibis10.17.169.63 — mongo-3 (arbiter, ZK role[arbiter])Orchestrator: ASAB Maestro / asab-remote-control
v26.33-alpha3. All changes applied the correct way: model.yaml → ZooKeeper →up(remote-control API). No manual file ops on nodes.1. What this MR contains
The only logic change is a revert-to-correct of a previous over-correction in
mergeLiveMemberWithDesired(mongo-init.js):Also dropped the redundant standalone
if (dm.priority !== undefined) out.priority = dm.priorityline (L523) — the block above already handles
dm.priority.Why preserve-live is correct:
out = Object.assign({}, cm)starts as a copy of the livemember. Votes, tags, secondaryDelaySecs all preserve live values and only default when absent.
Priority must behave the same. The earlier
else { out.priority = isArbiter ? 0 : 1 }clobbered alegitimate live priority (e.g.
priority: 2) to1on every phase-5rs.reconfigwheneverreplica-set.jsonomits the field — a silent election-preference regression. New members still getthe
arbiter ? 0 : 1default vianewMemberDocFromDesired(unchanged).SHA: script
bd5b355878d6…, 24606 B, 748 logical lines. ZK copy verified logicallyidentical to the reviewed sandbox file (comments only stripped).
2. Environment / Durable deployment
/library/Site/ASAB Maestro/Files/mongo/script/mongo-init.jsup(ZK is the source oftruth; disk overwrite on reconcile).
bd5b355878d6…on all 3 nodes = ZK. ✅3. Test suite— execution & results
Pass criteria after every test:
rs.status(): all remaining membershealth=1, exactly one PRIMARY, expected member count.mongo-*-init—docker ps -aacross all nodes shows zeromongo-*-initinExited(a transiently-Upinit during reconcile is fine; it must exit 0 and be auto-deleted by the governator's ExitCode==0 gate).upall 3 with unchanged modelbd5b3558everywhere, RS healthy, no lingeringupall 3upall 3upnoop-4 → noop-5on all 3 + simultaneousupnoop-5visible in compose, zero lingering initsupall 3upall 3T4b failure — captured live
Sherpa output from the PRIMARY-side (gepard) run, captured during the re-add:
Resulting RS: 2 members (gepard P + ibis ARB) — jaguar not re-added. Zero lingering inits
(all exited 0 as designed), but the intended member never joined.
Summary of priority/failover verification (the point of this MR)
Everything the preserve-live change touches passed:
4. Current blind spot (not covered by the sherpa — the reason T4b fails)
The sherpa cannot autonomously re-add a removed data member that sits at position 1 in
MONGO_HOSTNAMESand whose local mongod has no valid replica-set config.Mechanism
Every node's sherpa env:
MONGO_HOSTNAMES= mongo-1,mongo-2,mongo-3(iterated in order).mongo-1= position 1.hello.info === "Does not have a valid replica set config"(its localsystem.replsetholdsthe stale post-removal 2-member config; it is "not a member").
mongo-1first, the branch at L686(
!isWritablePrimary && !secondary && isreplicaset && info === "Does not have a valid replica set config")fires, it calls
initiateReplicaSet()→rs.initiate(desired)→ fails (an RS alreadyexists on gepard) →
quit(0)at L695.mongo-2(gepard, the live PRIMARY) to runrs.add.So the sherpa never reaches the node that could actually add jaguar.
Why it's positional
mongo-2): on re-add,mongo-1(jaguar) was still ahealthy PRIMARY, so the sherpa connected to jaguar first → found a live RS → correctly
rs.add'd gepard. ✅mongo-1): the stale non-member is first, so the initiateshort-circuit pre-empts the add path every time. ❌
Independent of this MR
This is not caused by the priority change. It is a pre-existing sherpa design gap in the
initiate-vs-add decision: the initiate branch should only fire when no reachable member is
already a valid primary. It reproduces deterministically (re-ran it twice in this session; identical
failure).
Secondary layer of the same blind spot (why plain
rs.addisn't enough even if reached)Even if the sherpa did reach gepard and call its normal
addMemberFromDesired→rs.add, addingan electable secondary to a set with only one writable data node (gepard) + arbiter is
rejected by MongoDB:
The correct path requires MongoDB's
rs.reconfigForPSASet(two-step: grantvotes 1 / priority 0,sync, then
priority 1). The sherpa's flow-3 PSA branch (usePsa→rs.reconfigForPSASet) existsin code, but is unreachable here because the initiate branch pre-empts it — leaving the removal
of a PRIMARY from a PSA set effectively one-way under pure-orchestrator control.
5. Manual workaround (used twice this session, verified)
To bring a removed PRIMARY back into a PSA set when the orchestrator can't:
Then verify 3 healthy members, priorities correct, zero lingering inits.
6. Recommended fixes (for follow-up, not part of this MR)
is already a valid primary / a live replica set exists. This fixes the pre-emption regardless of
hostname ordering.
rs.stepDown()+ handover before removal, or (b) teach the decommission path to use thePSA-safe reconfig so removal is not one-way.
MONGO_HOSTNAMES, or make the loop resilient to a stale first host.