fix(satellite): bounded DRBD teardown on Resource delete + pod preStop (Bug 82)#4
fix(satellite): bounded DRBD teardown on Resource delete + pod preStop (Bug 82)#4kvaps wants to merge 1 commit into
Conversation
…p (Bug 82) Deleting an RD whose kernel slot was `suspended:quorum` blocked `drbdadm down` indefinitely, stalling the satellite finalizer-strip path and stranding `/dev/drbd<minor>` slots. Recycled port to minor allocations then failed `create-md` with "Device 'N' is configured!" and a satellite pod restart hit the same hang in its preStop hook (DaemonSet stuck Terminating, only `kubectl delete --force` unblocks). `Adm.DownForce` wraps `drbdadm down` with a bounded context (`DownForceTimeout` = 15s) and on failure falls back to per-volume `drbdsetup detach --force` + kernel-direct `drbdsetup down`, neither of which wait for quorum. `Reconciler.DeleteResource` routes through `DownForce` so finalizer-strip is unconditional after best-effort cleanup. The DaemonSet preStop hook gains the same fallback so pod restarts can't stall on quorum-stuck slots. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Duplicate of #2 — the combined Bug 81+Bug 82 PR landed first with the same DownForce/preStop pattern. Closing as redundant. |
There was a problem hiding this comment.
Code Review
This pull request introduces a robust teardown mechanism for DRBD resources to address issues where drbdadm down hangs due to lost quorum. A new DownForce method is implemented that attempts a graceful shutdown with a timeout, falling back to kernel-direct drbdsetup commands if necessary. These changes are integrated into the satellite reconciler and the daemonset's pre-stop lifecycle hook, accompanied by comprehensive unit tests. Feedback suggests enhancing the DownForce implementation by explicitly checking for context cancellation before and during the fallback sequence to avoid unnecessary operations if the parent context has already expired.
|
|
||
| // Fallback path: force-detach every volume (no quorum wait), | ||
| // then kernel-direct `drbdsetup down`. Use the parent ctx so a | ||
| // tighter caller deadline still applies. |
There was a problem hiding this comment.
The fallback path should respect the parent context cancellation. If ctx was cancelled by the caller (e.g., the reconciler timed out or the pod is shutting down), we should bail out immediately instead of attempting the fallback sequence. This avoids unnecessary shell-outs when the operation is already doomed to fail due to context expiration.
if ctx.Err() != nil {
return err
}
// Fallback path: force-detach every volume (no quorum wait),
// then kernel-direct `drbdsetup down`. Use the parent ctx so a
// tighter caller deadline still applies.| for _, vol := range volumeNumbers { | ||
| target := fmt.Sprintf("%s/%d", resource, vol) | ||
| _, _ = a.exec.Run(ctx, "drbdsetup", "detach", "--force", target) | ||
| } |
There was a problem hiding this comment.
Inside the volume detach loop, it's safer to check for context cancellation. If the context is cancelled while iterating through many volumes, continuing to issue drbdsetup detach commands is wasteful. Checking ctx.Err() at the start of each iteration ensures we stop as soon as the context is no longer valid.
for _, vol := range volumeNumbers {
if ctx.Err() != nil {
return ctx.Err()
}
target := fmt.Sprintf("%s/%d", resource, vol)
_, _ = a.exec.Run(ctx, "drbdsetup", "detach", "--force", target)
}
Summary
suspended:quorumblockeddrbdadm downindefinitely, stalling the satellite finalizer-strip path. Recycled port to minor allocations then failedcreate-mdwith "Device 'N' is configured!" and pod restarts hit the same hang in preStop (DaemonSet stuck Terminating, requiringkubectl delete --force).Adm.DownForcewrapsdrbdadm downwith a 15s bounded context and on failure falls back to per-volumedrbdsetup detach --force+ kernel-directdrbdsetup down— neither command waits for quorum.Reconciler.DeleteResourceroutes throughDownForceso finalizer-strip is unconditional after best-effort cleanup.Observed on dev-kvaps stand
linstor rd d cc-autoplacedeletes the RD via REST./dev/drbd1000survives on every satellite —drbdsetup statusstill showscc-autoplaceassuspended:quorum disk:Inconsistent.create-mdwithDevice '1000' is configured! exit 20.drbdadm down allin preStop; DaemonSet rollout stuck Terminating untilkubectl delete pod --force.Test plan
go test ./pkg/drbd/... ./pkg/satellite/... -count=1— greenTestAdmDownForceHappyPath,TestAdmDownForceFallback,TestAdmDownForceFallbackMissingSlot,TestAdmDownForceBoundedDeadline,TestDeleteResourceForceTeardownOnSuspendedQuorumDevice '<minor>' is configured!on the next allocation.