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
3e696387
Commit
3e696387
authored
Dec 07, 2018
by
Guoliang Wang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[scheduler] Modify the scheduling result struct and improve logging for successful binding
parent
3a6d4c10
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
115 additions
and
67 deletions
+115
-67
extender_test.go
pkg/scheduler/core/extender_test.go
+57
-31
generic_scheduler.go
pkg/scheduler/core/generic_scheduler.go
+33
-13
generic_scheduler_test.go
pkg/scheduler/core/generic_scheduler_test.go
+3
-3
scheduler.go
pkg/scheduler/scheduler.go
+14
-12
scheduler_test.go
pkg/scheduler/scheduler_test.go
+8
-8
No files found.
pkg/scheduler/core/extender_test.go
View file @
3e696387
...
...
@@ -18,6 +18,7 @@ package core
import
(
"fmt"
"reflect"
"testing"
"time"
...
...
@@ -337,13 +338,13 @@ var _ algorithm.SchedulerExtender = &FakeExtender{}
func
TestGenericSchedulerWithExtenders
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
name
string
predicates
map
[
string
]
predicates
.
FitPredicate
prioritizers
[]
algorithm
.
PriorityConfig
extenders
[]
FakeExtender
nodes
[]
string
expected
Host
string
expectsErr
bool
name
string
predicates
map
[
string
]
predicates
.
FitPredicate
prioritizers
[]
algorithm
.
PriorityConfig
extenders
[]
FakeExtender
nodes
[]
string
expected
Result
ScheduleResult
expectsErr
bool
}{
{
predicates
:
map
[
string
]
predicates
.
FitPredicate
{
"true"
:
truePredicate
},
...
...
@@ -386,9 +387,13 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
predicates
:
[]
fitPredicate
{
machine1PredicateExtender
},
},
},
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedHost
:
"machine1"
,
name
:
"test 3"
,
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine1"
,
EvaluatedNodes
:
2
,
FeasibleNodes
:
1
,
},
name
:
"test 3"
,
},
{
predicates
:
map
[
string
]
predicates
.
FitPredicate
{
"true"
:
truePredicate
},
...
...
@@ -415,9 +420,13 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
weight
:
1
,
},
},
nodes
:
[]
string
{
"machine1"
},
expectedHost
:
"machine1"
,
name
:
"test 5"
,
nodes
:
[]
string
{
"machine1"
},
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine1"
,
EvaluatedNodes
:
1
,
FeasibleNodes
:
1
,
},
name
:
"test 5"
,
},
{
predicates
:
map
[
string
]
predicates
.
FitPredicate
{
"true"
:
truePredicate
},
...
...
@@ -434,9 +443,13 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
weight
:
5
,
},
},
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedHost
:
"machine2"
,
name
:
"test 6"
,
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine2"
,
EvaluatedNodes
:
2
,
FeasibleNodes
:
2
,
},
name
:
"test 6"
,
},
{
predicates
:
map
[
string
]
predicates
.
FitPredicate
{
"true"
:
truePredicate
},
...
...
@@ -448,9 +461,13 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
weight
:
1
,
},
},
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedHost
:
"machine2"
,
// machine2 has higher score
name
:
"test 7"
,
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine2"
,
EvaluatedNodes
:
2
,
FeasibleNodes
:
2
,
},
// machine2 has higher score
name
:
"test 7"
,
},
{
// Scheduler is expected to not send pod to extender in
...
...
@@ -469,10 +486,14 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
unInterested
:
true
,
},
},
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectsErr
:
false
,
expectedHost
:
"machine2"
,
// machine2 has higher score
name
:
"test 8"
,
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectsErr
:
false
,
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine2"
,
EvaluatedNodes
:
2
,
FeasibleNodes
:
2
,
},
// machine2 has higher score
name
:
"test 8"
,
},
{
// Scheduling is expected to not fail in
...
...
@@ -491,10 +512,14 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
predicates
:
[]
fitPredicate
{
machine1PredicateExtender
},
},
},
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectsErr
:
false
,
expectedHost
:
"machine1"
,
name
:
"test 9"
,
nodes
:
[]
string
{
"machine1"
,
"machine2"
},
expectsErr
:
false
,
expectedResult
:
ScheduleResult
{
SuggestedHost
:
"machine1"
,
EvaluatedNodes
:
2
,
FeasibleNodes
:
1
,
},
name
:
"test 9"
,
},
}
...
...
@@ -525,18 +550,19 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
false
,
schedulerapi
.
DefaultPercentageOfNodesToScore
)
podIgnored
:=
&
v1
.
Pod
{}
machine
,
err
:=
scheduler
.
Schedule
(
podIgnored
,
schedulertesting
.
FakeNodeLister
(
makeNodeList
(
test
.
nodes
)))
result
,
err
:=
scheduler
.
Schedule
(
podIgnored
,
schedulertesting
.
FakeNodeLister
(
makeNodeList
(
test
.
nodes
)))
if
test
.
expectsErr
{
if
err
==
nil
{
t
.
Errorf
(
"Unexpected non-error,
machine %s"
,
machine
)
t
.
Errorf
(
"Unexpected non-error,
result %+v"
,
result
)
}
}
else
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
return
}
if
test
.
expectedHost
!=
machine
{
t
.
Errorf
(
"Expected: %s, Saw: %s"
,
test
.
expectedHost
,
machine
)
if
!
reflect
.
DeepEqual
(
result
,
test
.
expectedResult
)
{
t
.
Errorf
(
"Expected: %+v, Saw: %+v"
,
test
.
expectedResult
,
result
)
}
}
})
...
...
pkg/scheduler/core/generic_scheduler.go
View file @
3e696387
...
...
@@ -104,7 +104,7 @@ func (f *FitError) Error() string {
// onto machines.
// TODO: Rename this type.
type
ScheduleAlgorithm
interface
{
Schedule
(
*
v1
.
Pod
,
algorithm
.
NodeLister
)
(
s
electedMachine
string
,
err
error
)
Schedule
(
*
v1
.
Pod
,
algorithm
.
NodeLister
)
(
s
cheduleResult
ScheduleResult
,
err
error
)
// Preempt receives scheduling errors for a pod and tries to create room for
// the pod by preempting lower priority pods if possible.
// It returns the node where preemption happened, a list of preempted pods, a
...
...
@@ -118,6 +118,17 @@ type ScheduleAlgorithm interface {
Prioritizers
()
[]
algorithm
.
PriorityConfig
}
// ScheduleResult represents the result of one pod scheduled. It will contain
// the final selected Node, along with the selected intermediate information.
type
ScheduleResult
struct
{
// Name of the scheduler suggest host
SuggestedHost
string
// Number of nodes scheduler evaluated on one pod scheduled
EvaluatedNodes
int
// Number of feasible nodes on one pod scheduled
FeasibleNodes
int
}
type
genericScheduler
struct
{
cache
schedulerinternalcache
.
Cache
schedulingQueue
internalqueue
.
SchedulingQueue
...
...
@@ -147,36 +158,35 @@ func (g *genericScheduler) snapshot() error {
// Schedule tries to schedule the given pod to one of the nodes in the node list.
// If it succeeds, it will return the name of the node.
// If it fails, it will return a FitError error with reasons.
func
(
g
*
genericScheduler
)
Schedule
(
pod
*
v1
.
Pod
,
nodeLister
algorithm
.
NodeLister
)
(
string
,
error
)
{
func
(
g
*
genericScheduler
)
Schedule
(
pod
*
v1
.
Pod
,
nodeLister
algorithm
.
NodeLister
)
(
result
ScheduleResult
,
err
error
)
{
trace
:=
utiltrace
.
New
(
fmt
.
Sprintf
(
"Scheduling %s/%s"
,
pod
.
Namespace
,
pod
.
Name
))
defer
trace
.
LogIfLong
(
100
*
time
.
Millisecond
)
if
err
:=
podPassesBasicChecks
(
pod
,
g
.
pvcLister
);
err
!=
nil
{
return
""
,
err
return
result
,
err
}
nodes
,
err
:=
nodeLister
.
List
()
if
err
!=
nil
{
return
""
,
err
return
result
,
err
}
if
len
(
nodes
)
==
0
{
return
""
,
ErrNoNodesAvailable
return
result
,
ErrNoNodesAvailable
}
err
=
g
.
snapshot
()
if
err
!=
nil
{
return
""
,
err
if
err
:=
g
.
snapshot
();
err
!=
nil
{
return
result
,
err
}
trace
.
Step
(
"Computing predicates"
)
startPredicateEvalTime
:=
time
.
Now
()
filteredNodes
,
failedPredicateMap
,
err
:=
g
.
findNodesThatFit
(
pod
,
nodes
)
if
err
!=
nil
{
return
""
,
err
return
result
,
err
}
if
len
(
filteredNodes
)
==
0
{
return
""
,
&
FitError
{
return
result
,
&
FitError
{
Pod
:
pod
,
NumAllNodes
:
len
(
nodes
),
FailedPredicates
:
failedPredicateMap
,
...
...
@@ -190,19 +200,29 @@ func (g *genericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister
// When only one node after predicate, just use it.
if
len
(
filteredNodes
)
==
1
{
metrics
.
SchedulingAlgorithmPriorityEvaluationDuration
.
Observe
(
metrics
.
SinceInMicroseconds
(
startPriorityEvalTime
))
return
filteredNodes
[
0
]
.
Name
,
nil
return
ScheduleResult
{
SuggestedHost
:
filteredNodes
[
0
]
.
Name
,
EvaluatedNodes
:
1
+
len
(
failedPredicateMap
),
FeasibleNodes
:
1
,
},
nil
}
metaPrioritiesInterface
:=
g
.
priorityMetaProducer
(
pod
,
g
.
cachedNodeInfoMap
)
priorityList
,
err
:=
PrioritizeNodes
(
pod
,
g
.
cachedNodeInfoMap
,
metaPrioritiesInterface
,
g
.
prioritizers
,
filteredNodes
,
g
.
extenders
)
if
err
!=
nil
{
return
""
,
err
return
result
,
err
}
metrics
.
SchedulingAlgorithmPriorityEvaluationDuration
.
Observe
(
metrics
.
SinceInMicroseconds
(
startPriorityEvalTime
))
metrics
.
SchedulingLatency
.
WithLabelValues
(
metrics
.
PriorityEvaluation
)
.
Observe
(
metrics
.
SinceInSeconds
(
startPriorityEvalTime
))
trace
.
Step
(
"Selecting host"
)
return
g
.
selectHost
(
priorityList
)
host
,
err
:=
g
.
selectHost
(
priorityList
)
return
ScheduleResult
{
SuggestedHost
:
host
,
EvaluatedNodes
:
len
(
filteredNodes
)
+
len
(
failedPredicateMap
),
FeasibleNodes
:
len
(
filteredNodes
),
},
err
}
// Prioritizers returns a slice containing all the scheduler's priority
...
...
pkg/scheduler/core/generic_scheduler_test.go
View file @
3e696387
...
...
@@ -482,13 +482,13 @@ func TestGenericScheduler(t *testing.T) {
test
.
alwaysCheckAllPredicates
,
false
,
schedulerapi
.
DefaultPercentageOfNodesToScore
)
machine
,
err
:=
scheduler
.
Schedule
(
test
.
pod
,
schedulertesting
.
FakeNodeLister
(
makeNodeList
(
test
.
nodes
)))
result
,
err
:=
scheduler
.
Schedule
(
test
.
pod
,
schedulertesting
.
FakeNodeLister
(
makeNodeList
(
test
.
nodes
)))
if
!
reflect
.
DeepEqual
(
err
,
test
.
wErr
)
{
t
.
Errorf
(
"Unexpected error: %v, expected: %v"
,
err
,
test
.
wErr
)
}
if
test
.
expectedHosts
!=
nil
&&
!
test
.
expectedHosts
.
Has
(
machine
)
{
t
.
Errorf
(
"Expected: %s, got: %s"
,
test
.
expectedHosts
,
machine
)
if
test
.
expectedHosts
!=
nil
&&
!
test
.
expectedHosts
.
Has
(
result
.
SuggestedHost
)
{
t
.
Errorf
(
"Expected: %s, got: %s"
,
test
.
expectedHosts
,
result
.
SuggestedHost
)
}
})
}
...
...
pkg/scheduler/scheduler.go
View file @
3e696387
...
...
@@ -291,15 +291,16 @@ func (sched *Scheduler) recordSchedulingFailure(pod *v1.Pod, err error, reason s
})
}
// schedule implements the scheduling algorithm and returns the suggested host.
func
(
sched
*
Scheduler
)
schedule
(
pod
*
v1
.
Pod
)
(
string
,
error
)
{
host
,
err
:=
sched
.
config
.
Algorithm
.
Schedule
(
pod
,
sched
.
config
.
NodeLister
)
// schedule implements the scheduling algorithm and returns the suggested result(host,
// evaluated nodes number,feasible nodes number).
func
(
sched
*
Scheduler
)
schedule
(
pod
*
v1
.
Pod
)
(
core
.
ScheduleResult
,
error
)
{
result
,
err
:=
sched
.
config
.
Algorithm
.
Schedule
(
pod
,
sched
.
config
.
NodeLister
)
if
err
!=
nil
{
pod
=
pod
.
DeepCopy
()
sched
.
recordSchedulingFailure
(
pod
,
err
,
v1
.
PodReasonUnschedulable
,
err
.
Error
())
return
""
,
err
return
core
.
ScheduleResult
{}
,
err
}
return
hos
t
,
err
return
resul
t
,
err
}
// preempt tries to create room for a pod that has failed to schedule, by preempting lower priority pods if possible.
...
...
@@ -468,7 +469,7 @@ func (sched *Scheduler) scheduleOne() {
// Synchronously attempt to find a fit for the pod.
start
:=
time
.
Now
()
s
uggestedHos
t
,
err
:=
sched
.
schedule
(
pod
)
s
cheduleResul
t
,
err
:=
sched
.
schedule
(
pod
)
if
err
!=
nil
{
// schedule() may have failed because the pod would not fit on any host, so we try to
// preempt, with the expectation that the next time the pod is tried for scheduling it
...
...
@@ -507,7 +508,7 @@ func (sched *Scheduler) scheduleOne() {
// Otherwise, binding of volumes is started after the pod is assumed, but before pod binding.
//
// This function modifies 'assumedPod' if volume binding is required.
allBound
,
err
:=
sched
.
assumeVolumes
(
assumedPod
,
suggestedHost
)
allBound
,
err
:=
sched
.
assumeVolumes
(
assumedPod
,
s
cheduleResult
.
S
uggestedHost
)
if
err
!=
nil
{
klog
.
Errorf
(
"error assuming volumes: %v"
,
err
)
metrics
.
PodScheduleErrors
.
Inc
()
...
...
@@ -516,7 +517,7 @@ func (sched *Scheduler) scheduleOne() {
// Run "reserve" plugins.
for
_
,
pl
:=
range
plugins
.
ReservePlugins
()
{
if
err
:=
pl
.
Reserve
(
plugins
,
assumedPod
,
suggestedHost
);
err
!=
nil
{
if
err
:=
pl
.
Reserve
(
plugins
,
assumedPod
,
s
cheduleResult
.
S
uggestedHost
);
err
!=
nil
{
klog
.
Errorf
(
"error while running %v reserve plugin for pod %v: %v"
,
pl
.
Name
(),
assumedPod
.
Name
,
err
)
sched
.
recordSchedulingFailure
(
assumedPod
,
err
,
SchedulerError
,
fmt
.
Sprintf
(
"reserve plugin %v failed"
,
pl
.
Name
()))
...
...
@@ -524,8 +525,8 @@ func (sched *Scheduler) scheduleOne() {
return
}
}
// assume modifies `assumedPod` by setting NodeName=suggestedHost
err
=
sched
.
assume
(
assumedPod
,
suggestedHost
)
// assume modifies `assumedPod` by setting NodeName=s
cheduleResult.S
uggestedHost
err
=
sched
.
assume
(
assumedPod
,
s
cheduleResult
.
S
uggestedHost
)
if
err
!=
nil
{
klog
.
Errorf
(
"error assuming pod: %v"
,
err
)
metrics
.
PodScheduleErrors
.
Inc
()
...
...
@@ -545,7 +546,7 @@ func (sched *Scheduler) scheduleOne() {
// Run "prebind" plugins.
for
_
,
pl
:=
range
plugins
.
PrebindPlugins
()
{
approved
,
err
:=
pl
.
Prebind
(
plugins
,
assumedPod
,
suggestedHost
)
approved
,
err
:=
pl
.
Prebind
(
plugins
,
assumedPod
,
s
cheduleResult
.
S
uggestedHost
)
if
err
!=
nil
{
approved
=
false
klog
.
Errorf
(
"error while running %v prebind plugin for pod %v: %v"
,
pl
.
Name
(),
assumedPod
.
Name
,
err
)
...
...
@@ -571,7 +572,7 @@ func (sched *Scheduler) scheduleOne() {
ObjectMeta
:
metav1
.
ObjectMeta
{
Namespace
:
assumedPod
.
Namespace
,
Name
:
assumedPod
.
Name
,
UID
:
assumedPod
.
UID
},
Target
:
v1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
suggestedHost
,
Name
:
s
cheduleResult
.
S
uggestedHost
,
},
})
metrics
.
E2eSchedulingLatency
.
Observe
(
metrics
.
SinceInMicroseconds
(
start
))
...
...
@@ -579,6 +580,7 @@ func (sched *Scheduler) scheduleOne() {
klog
.
Errorf
(
"error binding pod: %v"
,
err
)
metrics
.
PodScheduleErrors
.
Inc
()
}
else
{
klog
.
V
(
2
)
.
Infof
(
"pod %v/%v is bound successfully on node %v, %d nodes evaluated, %d nodes were found feasible"
,
assumedPod
.
Namespace
,
assumedPod
.
Name
,
scheduleResult
.
SuggestedHost
,
scheduleResult
.
EvaluatedNodes
,
scheduleResult
.
FeasibleNodes
)
metrics
.
PodScheduleSuccesses
.
Inc
()
}
}()
...
...
pkg/scheduler/scheduler_test.go
View file @
3e696387
...
...
@@ -145,12 +145,12 @@ func PriorityOne(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeI
}
type
mockScheduler
struct
{
machine
string
err
error
result
core
.
ScheduleResult
err
error
}
func
(
es
mockScheduler
)
Schedule
(
pod
*
v1
.
Pod
,
ml
algorithm
.
NodeLister
)
(
string
,
error
)
{
return
es
.
machine
,
es
.
err
func
(
es
mockScheduler
)
Schedule
(
pod
*
v1
.
Pod
,
ml
algorithm
.
NodeLister
)
(
core
.
ScheduleResult
,
error
)
{
return
es
.
result
,
es
.
err
}
func
(
es
mockScheduler
)
Predicates
()
map
[
string
]
predicates
.
FitPredicate
{
...
...
@@ -222,7 +222,7 @@ func TestScheduler(t *testing.T) {
{
name
:
"bind assumed pod scheduled"
,
sendPod
:
podWithID
(
"foo"
,
""
),
algo
:
mockScheduler
{
testNode
.
Name
,
nil
},
algo
:
mockScheduler
{
core
.
ScheduleResult
{
SuggestedHost
:
testNode
.
Name
,
EvaluatedNodes
:
1
,
FeasibleNodes
:
1
}
,
nil
},
expectBind
:
&
v1
.
Binding
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"foo"
,
UID
:
types
.
UID
(
"foo"
)},
Target
:
v1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
testNode
.
Name
}},
expectAssumedPod
:
podWithID
(
"foo"
,
testNode
.
Name
),
eventReason
:
"Scheduled"
,
...
...
@@ -230,7 +230,7 @@ func TestScheduler(t *testing.T) {
{
name
:
"error pod failed scheduling"
,
sendPod
:
podWithID
(
"foo"
,
""
),
algo
:
mockScheduler
{
testNode
.
Name
,
errS
},
algo
:
mockScheduler
{
core
.
ScheduleResult
{
SuggestedHost
:
testNode
.
Name
,
EvaluatedNodes
:
1
,
FeasibleNodes
:
1
}
,
errS
},
expectError
:
errS
,
expectErrorPod
:
podWithID
(
"foo"
,
""
),
eventReason
:
"FailedScheduling"
,
...
...
@@ -238,7 +238,7 @@ func TestScheduler(t *testing.T) {
{
name
:
"error bind forget pod failed scheduling"
,
sendPod
:
podWithID
(
"foo"
,
""
),
algo
:
mockScheduler
{
testNode
.
Name
,
nil
},
algo
:
mockScheduler
{
core
.
ScheduleResult
{
SuggestedHost
:
testNode
.
Name
,
EvaluatedNodes
:
1
,
FeasibleNodes
:
1
}
,
nil
},
expectBind
:
&
v1
.
Binding
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"foo"
,
UID
:
types
.
UID
(
"foo"
)},
Target
:
v1
.
ObjectReference
{
Kind
:
"Node"
,
Name
:
testNode
.
Name
}},
expectAssumedPod
:
podWithID
(
"foo"
,
testNode
.
Name
),
injectBindError
:
errB
,
...
...
@@ -248,7 +248,7 @@ func TestScheduler(t *testing.T) {
eventReason
:
"FailedScheduling"
,
},
{
sendPod
:
deletingPod
(
"foo"
),
algo
:
mockScheduler
{
""
,
nil
},
algo
:
mockScheduler
{
core
.
ScheduleResult
{}
,
nil
},
eventReason
:
"FailedScheduling"
,
},
}
...
...
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