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
1a1b0699
Commit
1a1b0699
authored
Oct 08, 2014
by
Daniel Smith
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1604 from brendandburns/resource
Add a least-requested priority function
parents
e3d47a3a
4230a8ca
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
218 additions
and
25 deletions
+218
-25
generic_scheduler.go
pkg/scheduler/generic_scheduler.go
+9
-9
generic_scheduler_test.go
pkg/scheduler/generic_scheduler_test.go
+14
-4
listers.go
pkg/scheduler/listers.go
+4
-4
priorities.go
pkg/scheduler/priorities.go
+63
-0
priorities_test.go
pkg/scheduler/priorities_test.go
+114
-0
spreading.go
pkg/scheduler/spreading.go
+2
-2
spreading_test.go
pkg/scheduler/spreading_test.go
+1
-1
factory.go
plugin/pkg/scheduler/factory/factory.go
+2
-2
factory_test.go
plugin/pkg/scheduler/factory/factory_test.go
+5
-1
scheduler_test.go
plugin/pkg/scheduler/scheduler_test.go
+4
-2
No files found.
pkg/scheduler/generic_scheduler.go
View file @
1a1b0699
...
@@ -63,18 +63,18 @@ func (g *genericScheduler) selectHost(priorityList HostPriorityList) (string, er
...
@@ -63,18 +63,18 @@ func (g *genericScheduler) selectHost(priorityList HostPriorityList) (string, er
return
hosts
[
ix
],
nil
return
hosts
[
ix
],
nil
}
}
func
findNodesThatFit
(
pod
api
.
Pod
,
podLister
PodLister
,
predicates
[]
FitPredicate
,
nodes
[]
string
)
([]
string
,
error
)
{
func
findNodesThatFit
(
pod
api
.
Pod
,
podLister
PodLister
,
predicates
[]
FitPredicate
,
nodes
api
.
MinionList
)
(
api
.
MinionList
,
error
)
{
filtered
:=
[]
string
{}
filtered
:=
[]
api
.
Minion
{}
machineToPods
,
err
:=
MapPodsToMachines
(
podLister
)
machineToPods
,
err
:=
MapPodsToMachines
(
podLister
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
api
.
MinionList
{}
,
err
}
}
for
_
,
node
:=
range
nodes
{
for
_
,
node
:=
range
nodes
.
Items
{
fits
:=
true
fits
:=
true
for
_
,
predicate
:=
range
predicates
{
for
_
,
predicate
:=
range
predicates
{
fit
,
err
:=
predicate
(
pod
,
machineToPods
[
node
],
node
)
fit
,
err
:=
predicate
(
pod
,
machineToPods
[
node
.
ID
],
node
.
ID
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
api
.
MinionList
{}
,
err
}
}
if
!
fit
{
if
!
fit
{
fits
=
false
fits
=
false
...
@@ -85,7 +85,7 @@ func findNodesThatFit(pod api.Pod, podLister PodLister, predicates []FitPredicat
...
@@ -85,7 +85,7 @@ func findNodesThatFit(pod api.Pod, podLister PodLister, predicates []FitPredicat
filtered
=
append
(
filtered
,
node
)
filtered
=
append
(
filtered
,
node
)
}
}
}
}
return
filtered
,
nil
return
api
.
MinionList
{
Items
:
filtered
}
,
nil
}
}
func
getMinHosts
(
list
HostPriorityList
)
[]
string
{
func
getMinHosts
(
list
HostPriorityList
)
[]
string
{
...
@@ -109,9 +109,9 @@ func EqualPriority(pod api.Pod, podLister PodLister, minionLister MinionLister)
...
@@ -109,9 +109,9 @@ func EqualPriority(pod api.Pod, podLister PodLister, minionLister MinionLister)
fmt
.
Errorf
(
"failed to list nodes: %v"
,
err
)
fmt
.
Errorf
(
"failed to list nodes: %v"
,
err
)
return
[]
HostPriority
{},
err
return
[]
HostPriority
{},
err
}
}
for
_
,
minion
:=
range
nodes
{
for
_
,
minion
:=
range
nodes
.
Items
{
result
=
append
(
result
,
HostPriority
{
result
=
append
(
result
,
HostPriority
{
host
:
minion
,
host
:
minion
.
ID
,
score
:
1
,
score
:
1
,
})
})
}
}
...
...
pkg/scheduler/generic_scheduler_test.go
View file @
1a1b0699
...
@@ -45,19 +45,29 @@ func numericPriority(pod api.Pod, podLister PodLister, minionLister MinionLister
...
@@ -45,19 +45,29 @@ func numericPriority(pod api.Pod, podLister PodLister, minionLister MinionLister
fmt
.
Errorf
(
"failed to list nodes: %v"
,
err
)
fmt
.
Errorf
(
"failed to list nodes: %v"
,
err
)
return
nil
,
err
return
nil
,
err
}
}
for
_
,
minion
:=
range
nodes
{
for
_
,
minion
:=
range
nodes
.
Items
{
score
,
err
:=
strconv
.
Atoi
(
minion
)
score
,
err
:=
strconv
.
Atoi
(
minion
.
ID
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
result
=
append
(
result
,
HostPriority
{
result
=
append
(
result
,
HostPriority
{
host
:
minion
,
host
:
minion
.
ID
,
score
:
score
,
score
:
score
,
})
})
}
}
return
result
,
nil
return
result
,
nil
}
}
func
makeMinionList
(
nodeNames
[]
string
)
api
.
MinionList
{
result
:=
api
.
MinionList
{
Items
:
make
([]
api
.
Minion
,
len
(
nodeNames
)),
}
for
ix
:=
range
nodeNames
{
result
.
Items
[
ix
]
.
ID
=
nodeNames
[
ix
]
}
return
result
}
func
TestGenericScheduler
(
t
*
testing
.
T
)
{
func
TestGenericScheduler
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
tests
:=
[]
struct
{
predicates
[]
FitPredicate
predicates
[]
FitPredicate
...
@@ -112,7 +122,7 @@ func TestGenericScheduler(t *testing.T) {
...
@@ -112,7 +122,7 @@ func TestGenericScheduler(t *testing.T) {
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
random
:=
rand
.
New
(
rand
.
NewSource
(
0
))
random
:=
rand
.
New
(
rand
.
NewSource
(
0
))
scheduler
:=
NewGenericScheduler
(
test
.
predicates
,
test
.
prioritizer
,
FakePodLister
([]
api
.
Pod
{}),
random
)
scheduler
:=
NewGenericScheduler
(
test
.
predicates
,
test
.
prioritizer
,
FakePodLister
([]
api
.
Pod
{}),
random
)
machine
,
err
:=
scheduler
.
Schedule
(
test
.
pod
,
FakeMinionLister
(
test
.
nodes
))
machine
,
err
:=
scheduler
.
Schedule
(
test
.
pod
,
FakeMinionLister
(
makeMinionList
(
test
.
nodes
)
))
if
test
.
expectsErr
{
if
test
.
expectsErr
{
if
err
==
nil
{
if
err
==
nil
{
t
.
Error
(
"Unexpected non-error"
)
t
.
Error
(
"Unexpected non-error"
)
...
...
pkg/scheduler/listers.go
View file @
1a1b0699
...
@@ -23,15 +23,15 @@ import (
...
@@ -23,15 +23,15 @@ import (
// MinionLister interface represents anything that can list minions for a scheduler.
// MinionLister interface represents anything that can list minions for a scheduler.
type
MinionLister
interface
{
type
MinionLister
interface
{
List
()
(
machines
[]
string
,
err
error
)
List
()
(
list
api
.
MinionList
,
err
error
)
}
}
// FakeMinionLister implements MinionLister on a []string for test purposes.
// FakeMinionLister implements MinionLister on a []string for test purposes.
type
FakeMinionLister
[]
string
type
FakeMinionLister
api
.
MinionList
// List returns minions as a []string.
// List returns minions as a []string.
func
(
f
FakeMinionLister
)
List
()
(
[]
string
,
error
)
{
func
(
f
FakeMinionLister
)
List
()
(
api
.
MinionList
,
error
)
{
return
[]
string
(
f
),
nil
return
api
.
MinionList
(
f
),
nil
}
}
// PodLister interface represents anything that can list pods for a scheduler.
// PodLister interface represents anything that can list pods for a scheduler.
...
...
pkg/scheduler/priorities.go
0 → 100644
View file @
1a1b0699
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
scheduler
import
(
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/resources"
"github.com/golang/glog"
)
// Calculate the occupancy on a node. 'node' has information about the resources on the node.
// 'pods' is a list of pods currently scheduled on the node.
func
calculateOccupancy
(
node
api
.
Minion
,
pods
[]
api
.
Pod
)
HostPriority
{
totalCPU
:=
0
totalMemory
:=
0
for
ix
:=
range
pods
{
for
cIx
:=
range
pods
[
ix
]
.
DesiredState
.
Manifest
.
Containers
{
container
:=
&
(
pods
[
ix
]
.
DesiredState
.
Manifest
.
Containers
[
cIx
])
totalCPU
+=
container
.
CPU
totalMemory
+=
container
.
Memory
}
}
percentageCPU
:=
(
totalCPU
*
100
)
/
resources
.
GetIntegerResource
(
node
.
NodeResources
.
Capacity
,
resources
.
CPU
,
0
)
percentageMemory
:=
(
totalMemory
*
100
)
/
resources
.
GetIntegerResource
(
node
.
NodeResources
.
Capacity
,
resources
.
Memory
,
0
)
glog
.
V
(
4
)
.
Infof
(
"Least Requested Priority, AbsoluteRequested: (%d, %d) Percentage:(%d
\\
%m, %d
\\
%)"
,
totalCPU
,
totalMemory
,
percentageCPU
,
percentageMemory
)
return
HostPriority
{
host
:
node
.
ID
,
score
:
int
((
percentageCPU
+
percentageMemory
)
/
2
),
}
}
// LeastRequestedPriority is a priority function that favors nodes with fewer requested resources.
// It calculates the percentage of memory and CPU requested by pods scheduled on the node, and prioritizes
// based on the minimum of the average of the fraction of requested to capacity.
// Details: (Sum(requested cpu) / Capacity + Sum(requested memory) / Capacity) * 50
func
LeastRequestedPriority
(
pod
api
.
Pod
,
podLister
PodLister
,
minionLister
MinionLister
)
(
HostPriorityList
,
error
)
{
nodes
,
err
:=
minionLister
.
List
()
if
err
!=
nil
{
return
HostPriorityList
{},
err
}
podsToMachines
,
err
:=
MapPodsToMachines
(
podLister
)
list
:=
HostPriorityList
{}
for
_
,
node
:=
range
nodes
.
Items
{
list
=
append
(
list
,
calculateOccupancy
(
node
,
podsToMachines
[
node
.
ID
]))
}
return
list
,
nil
}
pkg/scheduler/priorities_test.go
0 → 100644
View file @
1a1b0699
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
scheduler
import
(
"reflect"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/resources"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func
makeMinion
(
node
string
,
cpu
,
memory
int
)
api
.
Minion
{
return
api
.
Minion
{
TypeMeta
:
api
.
TypeMeta
{
ID
:
node
},
NodeResources
:
api
.
NodeResources
{
Capacity
:
api
.
ResourceList
{
resources
.
CPU
:
util
.
NewIntOrStringFromInt
(
cpu
),
resources
.
Memory
:
util
.
NewIntOrStringFromInt
(
memory
),
},
},
}
}
func
TestLeastRequested
(
t
*
testing
.
T
)
{
labels1
:=
map
[
string
]
string
{
"foo"
:
"bar"
,
"baz"
:
"blah"
,
}
labels2
:=
map
[
string
]
string
{
"bar"
:
"foo"
,
"baz"
:
"blah"
,
}
machine1State
:=
api
.
PodState
{
Host
:
"machine1"
,
}
machine2State
:=
api
.
PodState
{
Host
:
"machine2"
,
}
cpuOnly
:=
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
CPU
:
1000
},
{
CPU
:
2000
},
},
},
}
cpuAndMemory
:=
api
.
PodState
{
Manifest
:
api
.
ContainerManifest
{
Containers
:
[]
api
.
Container
{
{
CPU
:
1000
,
Memory
:
2000
},
{
CPU
:
2000
,
Memory
:
3000
},
},
},
}
tests
:=
[]
struct
{
pod
api
.
Pod
pods
[]
api
.
Pod
nodes
[]
api
.
Minion
expectedList
HostPriorityList
test
string
}{
{
nodes
:
[]
api
.
Minion
{
makeMinion
(
"machine1"
,
4000
,
10000
),
makeMinion
(
"machine2"
,
4000
,
10000
)},
expectedList
:
[]
HostPriority
{{
"machine1"
,
0
},
{
"machine2"
,
0
}},
test
:
"nothing scheduled"
,
},
{
nodes
:
[]
api
.
Minion
{
makeMinion
(
"machine1"
,
4000
,
10000
),
makeMinion
(
"machine2"
,
4000
,
10000
)},
expectedList
:
[]
HostPriority
{{
"machine1"
,
0
},
{
"machine2"
,
0
}},
test
:
"no resources requested"
,
pods
:
[]
api
.
Pod
{
{
CurrentState
:
machine1State
,
Labels
:
labels2
},
{
CurrentState
:
machine1State
,
Labels
:
labels1
},
{
CurrentState
:
machine2State
,
Labels
:
labels1
},
{
CurrentState
:
machine2State
,
Labels
:
labels1
},
},
},
{
nodes
:
[]
api
.
Minion
{
makeMinion
(
"machine1"
,
4000
,
10000
),
makeMinion
(
"machine2"
,
4000
,
10000
)},
expectedList
:
[]
HostPriority
{{
"machine1"
,
37
/* int(75% / 2) */
},
{
"machine2"
,
62
/* int( 75% + 50% / 2) */
}},
test
:
"no resources requested"
,
pods
:
[]
api
.
Pod
{
{
DesiredState
:
cpuOnly
,
CurrentState
:
machine1State
},
{
DesiredState
:
cpuAndMemory
,
CurrentState
:
machine2State
},
},
},
}
for
_
,
test
:=
range
tests
{
list
,
err
:=
LeastRequestedPriority
(
test
.
pod
,
FakePodLister
(
test
.
pods
),
FakeMinionLister
(
api
.
MinionList
{
Items
:
test
.
nodes
}))
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
if
!
reflect
.
DeepEqual
(
test
.
expectedList
,
list
)
{
t
.
Errorf
(
"%s: expected %#v, got %#v"
,
test
.
test
,
test
.
expectedList
,
list
)
}
}
}
pkg/scheduler/spreading.go
View file @
1a1b0699
...
@@ -43,8 +43,8 @@ func CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister Mini
...
@@ -43,8 +43,8 @@ func CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister Mini
}
}
result
:=
[]
HostPriority
{}
result
:=
[]
HostPriority
{}
for
_
,
minion
:=
range
minions
{
for
_
,
minion
:=
range
minions
.
Items
{
result
=
append
(
result
,
HostPriority
{
host
:
minion
,
score
:
counts
[
minion
]})
result
=
append
(
result
,
HostPriority
{
host
:
minion
.
ID
,
score
:
counts
[
minion
.
ID
]})
}
}
return
result
,
nil
return
result
,
nil
}
}
...
...
pkg/scheduler/spreading_test.go
View file @
1a1b0699
...
@@ -100,7 +100,7 @@ func TestSpreadPriority(t *testing.T) {
...
@@ -100,7 +100,7 @@ func TestSpreadPriority(t *testing.T) {
}
}
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
list
,
err
:=
CalculateSpreadPriority
(
test
.
pod
,
FakePodLister
(
test
.
pods
),
FakeMinionLister
(
test
.
nodes
))
list
,
err
:=
CalculateSpreadPriority
(
test
.
pod
,
FakePodLister
(
test
.
pods
),
FakeMinionLister
(
makeMinionList
(
test
.
nodes
)
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
}
...
...
plugin/pkg/scheduler/factory/factory.go
View file @
1a1b0699
...
@@ -202,9 +202,9 @@ type storeToMinionLister struct {
...
@@ -202,9 +202,9 @@ type storeToMinionLister struct {
cache
.
Store
cache
.
Store
}
}
func
(
s
*
storeToMinionLister
)
List
()
(
machines
[]
string
,
err
error
)
{
func
(
s
*
storeToMinionLister
)
List
()
(
machines
api
.
MinionList
,
err
error
)
{
for
_
,
m
:=
range
s
.
Store
.
List
()
{
for
_
,
m
:=
range
s
.
Store
.
List
()
{
machines
=
append
(
machines
,
m
.
(
*
api
.
Minion
)
.
ID
)
machines
.
Items
=
append
(
machines
.
Items
,
*
(
m
.
(
*
api
.
Minion
))
)
}
}
return
machines
,
nil
return
machines
,
nil
}
}
...
...
plugin/pkg/scheduler/factory/factory_test.go
View file @
1a1b0699
...
@@ -223,10 +223,14 @@ func TestStoreToMinionLister(t *testing.T) {
...
@@ -223,10 +223,14 @@ func TestStoreToMinionLister(t *testing.T) {
}
}
sml
:=
storeToMinionLister
{
store
}
sml
:=
storeToMinionLister
{
store
}
got
,
err
:=
sml
.
List
()
got
Nodes
,
err
:=
sml
.
List
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
t
.
Fatalf
(
"Unexpected error: %v"
,
err
)
}
}
got
:=
make
([]
string
,
len
(
gotNodes
.
Items
))
for
ix
:=
range
gotNodes
.
Items
{
got
[
ix
]
=
gotNodes
.
Items
[
ix
]
.
ID
}
if
!
ids
.
HasAll
(
got
...
)
||
len
(
got
)
!=
len
(
ids
)
{
if
!
ids
.
HasAll
(
got
...
)
||
len
(
got
)
!=
len
(
ids
)
{
t
.
Errorf
(
"Expected %v, got %v"
,
ids
,
got
)
t
.
Errorf
(
"Expected %v, got %v"
,
ids
,
got
)
}
}
...
...
plugin/pkg/scheduler/scheduler_test.go
View file @
1a1b0699
...
@@ -81,8 +81,10 @@ func TestScheduler(t *testing.T) {
...
@@ -81,8 +81,10 @@ func TestScheduler(t *testing.T) {
var
gotPod
*
api
.
Pod
var
gotPod
*
api
.
Pod
var
gotBinding
*
api
.
Binding
var
gotBinding
*
api
.
Binding
c
:=
&
Config
{
c
:=
&
Config
{
MinionLister
:
scheduler
.
FakeMinionLister
{
"machine1"
},
MinionLister
:
scheduler
.
FakeMinionLister
(
Algorithm
:
item
.
algo
,
api
.
MinionList
{
Items
:
[]
api
.
Minion
{{
TypeMeta
:
api
.
TypeMeta
{
ID
:
"machine1"
}}}},
),
Algorithm
:
item
.
algo
,
Binder
:
fakeBinder
{
func
(
b
*
api
.
Binding
)
error
{
Binder
:
fakeBinder
{
func
(
b
*
api
.
Binding
)
error
{
gotBinding
=
b
gotBinding
=
b
return
item
.
injectBindError
return
item
.
injectBindError
...
...
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