[ 
https://issues.apache.org/jira/browse/YUNIKORN-3375?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18105157#comment-18105157
 ] 

Dale Richardson commented on YUNIKORN-3375:
-------------------------------------------

Not a duplicate of YUNIKORN-3317, but a sibling worth linking: 3317 fixed "shim 
knows the pod, core doesn't" for *foreign* pods whose create was delivered as 
an informer update. This issue is the same symptom for *YuniKorn-managed* pods 
on the node re-add/adoption path, where the still-Bound task suppresses any 
report ({{updateYuniKornPod}} only calls {{SetTaskPod}}). The foreign branch of 
the very same adoption path does re-report ({{updateForeignPod}} -> 
{{CreateAllocationForForeignPod}}, tracking added by YUNIKORN-2834) -- that 
asymmetry is what shows the YuniKorn-managed branch is an oversight rather than 
a design decision. Also unlike foreign allocations, which the core tracks per 
node only, YuniKorn allocations are charged to queues: the core decremented 
queue allocated resources on node removal and nothing restores them while the 
pods keep running, so this issue additionally corrupts queue 
quota/fair-share/preemption accounting.


> Node delete/re-add silently corrupts queue accounting: adopted pods are never 
> re-reported to the core
> -----------------------------------------------------------------------------------------------------
>
>                 Key: YUNIKORN-3375
>                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3375
>             Project: Apache YuniKorn
>          Issue Type: Bug
>          Components: shim - kubernetes
>            Reporter: Dale Richardson
>            Priority: Major
>
> When a Node object is deleted and re-created while its pods keep running, the 
> shim and the core permanently disagree about the node's allocations, and 
> queue accounting is silently corrupted.
> *Mechanism* (all verified in code):
>  # Node delete: the shim orphans the node's bound pods 
> ({{{}Context.deleteNodeInternal{}}} -> {{{}SchedulerCache.RemoveNode{}}}); 
> the core removes the node, removes the allocations from the applications and 
> *decrements queue allocated resources* 
> ({{{}partition.removeNodeAllocations{}}}), then notifies the shim with 
> {{{}TerminationType STOPPED_BY_RM{}}}.
>  # The shim callback intentionally only forgets the pod in the cache and does 
> not fail the task ({{{}scheduler_callback.go{}}} ~117) – this filter is 
> correct and must stay: dispatching the release would delete running pods.
>  # Node re-add: {{registerNodes}} sends a bare {{si.NodeInfo}} (it cannot 
> carry allocations – {{existingAllocations}} is a reserved/removed SI field), 
> and the orphan-adoption path re-attaches the pods to the shim cache via 
> {{updateYuniKornPod}} -> {{SetTaskPod}} on the still-Bound task – {*}nothing 
> re-reports the allocations to the core{*}.
>  # No reconciliation exists. The divergence lasts until each pod terminates, 
> or until a scheduler restart (restart recovery does re-report).
> {*}The asymmetry that shows this is an oversight{*}: the same adoption path 
> already re-reports *foreign* pods to the core ({{{}updateForeignPod{}}} -> 
> {{CreateAllocationForForeignPod}} -> {{{}UpdateAllocation{}}}). Only the 
> YuniKorn-managed branch is silent, because the existing Bound task suppresses 
> task creation.
> *Impact* :
>  - Node-level double allocation does NOT occur: the shim predicate callback 
> runs {{NodeResourcesFit}} against the shim cache, which contains the adopted 
> pods, so a genuinely full node rejects new placements (kubelet admission is a 
> second backstop).
>  - The real damage is {*}accounting integrity{*}: the queue's allocated 
> resource was decremented while the pods keep running, and is never 
> re-incremented. A queue with max=X can end up running more than X (survivors 
> plus a full X of new admissions); user quotas, fair-share ordering, 
> preemption inputs, autoscaler outstanding-request calculations, metrics and 
> the web UI are all silently wrong. The core also wastes scheduling cycles 
> proposing a node it believes is empty while the shim rejects every attempt.
> {*}Reachability{*}: {{kubectl delete node}} on a live node (or automation 
> doing the equivalent) followed by kubelet self-re-registration recreates the 
> Node object within seconds; the pod-GC controller quarantines orphaned pods 
> for ~40s before deleting them, so pods surviving a brief flap is the normal 
> outcome, not a race. Cluster-autoscaler is not a trigger (it drains first). 
> Rare but ordinary operations; when it fires it affects every pod on the node, 
> for an unbounded duration on long-running workloads.
> {*}Reproduction{*}: deterministic in a fault-injection test built on the 
> MockScheduler harness (bind churn + node remove/re-add through the informer 
> path): after settle, pods placed in the shim cache have no matching core 
> allocation (e.g. one flapped node: shim 40 pods, core 0 allocations). 3/3 
> flapped runs reproduce; 0/2 static controls. Test to be contributed.
> {*}Suggested fix{*}: on adoption of a YuniKorn-managed pod whose task is 
> Bound, re-report the allocation the same way the foreign-pod branch and 
> restart recovery already do ({{{}UpdateAllocation{}}} with NodeID set -> the 
> core's {{MarkPreviouslyAllocated}} path). Alternatively (or additionally) 
> reconsider overloading {{STOPPED_BY_RM}} for core-initiated node-removal 
> releases, so the shim can distinguish them.



--
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