You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@yunikorn.apache.org by "weichen lai (Jira)" <ji...@apache.org> on 2026/09/06 13:25:00 UTC

[jira] [Updated] (YUNIKORN-3445) SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them

     [ https://issues.apache.org/jira/browse/YUNIKORN-3445?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

weichen lai updated YUNIKORN-3445:
----------------------------------
    Summary: SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them  (was: [Core] SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them)

> SortAllocationsBasedOnAsk prioritizes originator and opted-out pods for preemption instead of protecting them
> -------------------------------------------------------------------------------------------------------------
>
>                 Key: YUNIKORN-3445
>                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3445
>             Project: Apache YuniKorn
>          Issue Type: Bug
>          Components: core - scheduler
>    Affects Versions: 1.9.0
>            Reporter: weichen lai
>            Assignee: weichen lai
>            Priority: Major
>
> h3. Overview
> In {{pkg/scheduler/objects/preemption_utilities.go}}, {{SortAllocationsBasedOnAsk()}} and {{scoreAllocationBasedOnAsk()}} determine victim ordering during preemption.
> Under the current implementation, allocations with {{!allowPreemptSelf}} (opted-out) or {{isOriginator}} (driver/manager) receive higher-order score bits ({{scoreNoPreempt}} = {{1 << 34}}, {{scoreOriginator}} = {{1 << 33}}):
> {code:go}func scoreAllocationBasedOnAsk(allocation *Allocation, ask *resources.Resource) uint64 {
> 	var score uint64 = 0
> 	if allocation.IsOriginator() {
> 		score |= scoreOriginator // 1 << 33
> 	}
> 	if !allocation.IsAllowPreemptSelf() {
> 		score |= scoreNoPreempt  // 1 << 34
> 	}
> 	score += allocation.GetAllocatedResource().TypeMatching(ask)
> 	return score
> }
> {code}
> Because {{SortAllocationsBasedOnAsk()}} orders allocations in descending order ({{scoreLeft > scoreRight}}), opted-out and originator allocations receive higher scores and are placed at the beginning of the candidate slice rather than at the end.
> h2. 
> h3. Comparison with Design Documentation
> This ordering conflicts with documented design specifications:
> * **Preemption Law #1 (preemption policies are strong suggestions, not guarantees):** Opting out of preemption and originator status are intended as a last resort when no other suitable allocations can be preempted.
> * **Quota Preemption Design Document:** The specification states that non-originators and pods with {{allowPreemption: true}} should receive higher scores to prioritize regular allocations for preemption over originators and opted-out pods.
> h2. 
> h3. Test Verification
> The following test demonstrates the ordering in {{pkg/scheduler/objects/preemption_utilities_test.go}}:
> {code:go}func TestSortAllocationsBasedOnAsk_PreemptionOrdering(t *testing.T) {
> 	node := NewNode(&si.NodeInfo{
> 		NodeID: "node1",
> 		SchedulableResource: &si.Resource{
> 			Resources: map[string]*si.Quantity{"first": {Value: 100}},
> 		},
> 	})
> 	res := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10})
> 	total := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 100})
> 	ask := resources.NewResourceFromMap(map[string]resources.Quantity{"first": 10})
> 	regularPod := createAllocation("regularPod", "app1", node.NodeID, true, false, 10, false, res)
> 	originatorPod := createAllocation("originatorPod", "app1", node.NodeID, true, true, 10, false, res)
> 	optedOutPod := createAllocation("optedOutPod", "app1", node.NodeID, false, false, 10, false, res)
> 	allocations := []*Allocation{regularPod, originatorPod, optedOutPod}
> 	SortAllocationsBasedOnAsk(allocations, total, ask)
> 	// Current ordering:
> 	// allocations[0]: optedOutPod
> 	// allocations[1]: originatorPod
> 	// allocations[2]: regularPod
> 	//
> 	// Expected ordering per design: regularPod should be placed at index 0
> 	assert.Equal(t, allocations[0].GetAllocationKey(), "regularPod",
> 		"Expected regularPod at index 0, but got: %s", allocations[0].GetAllocationKey())
> }
> {code}
> *Output:*
> {code}=== RUN   TestSortAllocationsBasedOnAsk_PreemptionOrdering
>     preemption_utilities_test.go:320: Expected regularPod at index 0, but got: optedOutPod
> --- FAIL: TestSortAllocationsBasedOnAsk_PreemptionOrdering (0.00s)
> {code}
> h2. 
> h3. Impact
> During Quota Preemption, reducing a queue's quota results in originator and opted-out allocations being preempted before standard worker allocations.
> h2. 
> h3. Proposed Solution
> In {{pkg/scheduler/objects/preemption_utilities.go}}, assign the higher-order score bits to unprotected allocations ({{allowPreemptSelf == true}} and {{!isOriginator}}):
> {code:go}const (
> 	scoreAllowPreempt  uint64 = 1 << 34
> 	scoreNonOriginator uint64 = 1 << 33
> )
> func scoreAllocationBasedOnAsk(allocation *Allocation, ask *resources.Resource) uint64 {
> 	var score uint64 = 0
> 	if !allocation.IsOriginator() {
> 		score |= scoreNonOriginator
> 	}
> 	if allocation.IsAllowPreemptSelf() {
> 		score |= scoreAllowPreempt
> 	}
> 	score += allocation.GetAllocatedResource().TypeMatching(ask)
> 	return score
> }
> {code}



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

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@yunikorn.apache.org
For additional commands, e-mail: issues-help@yunikorn.apache.org