Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
eb31bbb8
Commit
eb31bbb8
authored
Nov 27, 2018
by
Bobby (Babak) Salamat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Change sort function of the scheduling queue to avoid starvation
parent
ddf47ac1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
77 additions
and
1 deletion
+77
-1
scheduling_queue.go
pkg/scheduler/internal/queue/scheduling_queue.go
+22
-1
scheduling_queue_test.go
pkg/scheduler/internal/queue/scheduling_queue_test.go
+55
-0
No files found.
pkg/scheduler/internal/queue/scheduling_queue.go
View file @
eb31bbb8
...
@@ -206,10 +206,31 @@ type PriorityQueue struct {
...
@@ -206,10 +206,31 @@ type PriorityQueue struct {
// Making sure that PriorityQueue implements SchedulingQueue.
// Making sure that PriorityQueue implements SchedulingQueue.
var
_
=
SchedulingQueue
(
&
PriorityQueue
{})
var
_
=
SchedulingQueue
(
&
PriorityQueue
{})
// podTimeStamp returns pod's last schedule time or its creation time if the
// scheduler has never tried scheduling it.
func
podTimestamp
(
pod
*
v1
.
Pod
)
*
metav1
.
Time
{
_
,
condition
:=
podutil
.
GetPodCondition
(
&
pod
.
Status
,
v1
.
PodScheduled
)
if
condition
==
nil
{
return
&
pod
.
CreationTimestamp
}
return
&
condition
.
LastTransitionTime
}
// activeQComp is the function used by the activeQ heap algorithm to sort pods.
// It sorts pods based on their priority. When priorities are equal, it uses
// podTimestamp.
func
activeQComp
(
pod1
,
pod2
interface
{})
bool
{
p1
:=
pod1
.
(
*
v1
.
Pod
)
p2
:=
pod2
.
(
*
v1
.
Pod
)
prio1
:=
util
.
GetPodPriority
(
p1
)
prio2
:=
util
.
GetPodPriority
(
p2
)
return
(
prio1
>
prio2
)
||
(
prio1
==
prio2
&&
podTimestamp
(
p1
)
.
Before
(
podTimestamp
(
p2
)))
}
// NewPriorityQueue creates a PriorityQueue object.
// NewPriorityQueue creates a PriorityQueue object.
func
NewPriorityQueue
()
*
PriorityQueue
{
func
NewPriorityQueue
()
*
PriorityQueue
{
pq
:=
&
PriorityQueue
{
pq
:=
&
PriorityQueue
{
activeQ
:
newHeap
(
cache
.
MetaNamespaceKeyFunc
,
util
.
HigherPriorityPod
),
activeQ
:
newHeap
(
cache
.
MetaNamespaceKeyFunc
,
activeQComp
),
unschedulableQ
:
newUnschedulablePodsMap
(),
unschedulableQ
:
newUnschedulablePodsMap
(),
nominatedPods
:
map
[
string
][]
*
v1
.
Pod
{},
nominatedPods
:
map
[
string
][]
*
v1
.
Pod
{},
}
}
...
...
pkg/scheduler/internal/queue/scheduling_queue_test.go
View file @
eb31bbb8
...
@@ -24,6 +24,8 @@ import (
...
@@ -24,6 +24,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
podutil
"k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/pkg/scheduler/util"
"k8s.io/kubernetes/pkg/scheduler/util"
)
)
...
@@ -512,3 +514,56 @@ func TestSchedulingQueue_Close(t *testing.T) {
...
@@ -512,3 +514,56 @@ func TestSchedulingQueue_Close(t *testing.T) {
})
})
}
}
}
}
// TestRecentlyTriedPodsGoBack tests that pods which are recently tried and are
// unschedulable go behind other pods with the same priority. This behavior
// ensures that an unschedulable pod does not block head of the queue when there
// are frequent events that move pods to the active queue.
func
TestRecentlyTriedPodsGoBack
(
t
*
testing
.
T
)
{
q
:=
NewPriorityQueue
()
// Add a few pods to priority queue.
for
i
:=
0
;
i
<
5
;
i
++
{
p
:=
v1
.
Pod
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
fmt
.
Sprintf
(
"test-pod-%v"
,
i
),
Namespace
:
"ns1"
,
UID
:
types
.
UID
(
fmt
.
Sprintf
(
"tp00%v"
,
i
)),
},
Spec
:
v1
.
PodSpec
{
Priority
:
&
highPriority
,
},
Status
:
v1
.
PodStatus
{
NominatedNodeName
:
"node1"
,
},
}
q
.
Add
(
&
p
)
}
// Simulate a pod being popped by the scheduler, determined unschedulable, and
// then moved back to the active queue.
p1
,
err
:=
q
.
Pop
()
if
err
!=
nil
{
t
.
Errorf
(
"Error while popping the head of the queue: %v"
,
err
)
}
// Update pod condition to unschedulable.
podutil
.
UpdatePodCondition
(
&
p1
.
Status
,
&
v1
.
PodCondition
{
Type
:
v1
.
PodScheduled
,
Status
:
v1
.
ConditionFalse
,
Reason
:
v1
.
PodReasonUnschedulable
,
Message
:
"fake scheduling failure"
,
})
// Put in the unschedulable queue.
q
.
AddUnschedulableIfNotPresent
(
p1
)
// Move all unschedulable pods to the active queue.
q
.
MoveAllToActiveQueue
()
// Simulation is over. Now let's pop all pods. The pod popped first should be
// the last one we pop here.
for
i
:=
0
;
i
<
5
;
i
++
{
p
,
err
:=
q
.
Pop
()
if
err
!=
nil
{
t
.
Errorf
(
"Error while popping pods from the queue: %v"
,
err
)
}
if
(
i
==
4
)
!=
(
p1
==
p
)
{
t
.
Errorf
(
"A pod tried before is not the last pod popped: i: %v, pod name: %v"
,
i
,
p
.
Name
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment