Dale Richardson created YUNIKORN-3382:
-----------------------------------------

             Summary: Failed victim pod delete permanently wedges a preemption; 
release-path DeleteTaskPod is never retried
                 Key: YUNIKORN-3382
                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3382
             Project: Apache YuniKorn
          Issue Type: Bug
          Components: core - scheduler, shim - kubernetes
            Reporter: Dale Richardson


When the shim executes a core-initiated release by deleting the pod, a failed
delete is logged and dropped -- there is no retry on this path. One transient
apiserver failure leaves the release permanently half-executed.

h3. Mechanism

The core marks a preemption victim and hands it to the RM to release, but does 
not
free its capacity until the shim confirms:
- victim.MarkPreempted() at preempt time (preemption.go:659), before the RM is
  notified -- so the victim is excluded from all future victim selection
  (queue.go:2206) from that moment;
- victimQueue.IncPreemptingResource(...) (preemption.go:681);
- p.ask.MarkTriggeredPreemption() (preemption.go:702);
- notifyRMAllocationReleased(PREEMPTED_BY_SCHEDULER) (preemption.go:705).

The victim's node/queue release and DecPreemptingResource run only when the 
shim's
PREEMPTED_BY_SCHEDULER confirmation returns (partition.go:1562-1563, gated by 
the
"this release is the shim's confirmation" logic at partition.go:1577-1579).

The shim executes the release by deleting the pod, and drops any failure:

{code}
// Application.handleReleaseAppAllocationEvent (application.go:648-655)
err := task.DeleteTaskPod()
if err != nil {
    log.Log(...).Error("failed to release allocation from application", 
zap.Error(err))
}
{code}

Nothing re-queues the task, no timer retries the delete, and the core is never
told the release did not happen. MarkUnPreempted only runs on the "victim 
already
released" revert (preemption.go:669), never on the failed-delete path. The 
result
is permanent:
- the victim keeps running and stays IsPreempted forever, excluded from future
  preemption;
- the victim queue's preemptingResource is never decremented, so it 
under-reports
  its preemptable and remaining-guaranteed headroom by the victim's size;
- the high-priority ask the preemption was made for was marked as having 
triggered
  preemption and now starves -- its capacity never arrives.

h3. Reproduction

Chaos scenario: two-queue guaranteed/max config, cluster filled with 
low-priority
pods, high-priority wave forces preemption, victim deletes failed with p=0.5.
After settling, the victim runs on both sides consistently (no accounting
divergence), the queue holds a non-zero preemptingResource forever, and one
high-priority pod is never placed. One failed delete per wedge; deterministic 
per
seed. The same dropped-delete leaves released gang placeholders alive 
indefinitely.

h3. Impact

Transient apiserver delete failures (timeouts, webhook hiccups) are routine in
busy clusters. Each occurrence silently degrades preemption capacity and
guaranteed-quota enforcement for the victim queue until a scheduler restart, and
starves the ask that triggered the preemption.

h3. Fix sketch

Retry the delete (bounded backoff) or re-drive it from a reconciliation pass, or
report the failed release back to the core so it can re-issue. The single 
release
path above covers both the preemption and the gang-placeholder consequence.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to