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
4aa92bac
Commit
4aa92bac
authored
Nov 02, 2017
by
Gavin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactoring of priority function(CaculateSpreadPriority) by using map/reduce pattern
parent
ce910f24
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
82 additions
and
98 deletions
+82
-98
selector_spreading.go
.../pkg/scheduler/algorithm/priorities/selector_spreading.go
+82
-98
No files found.
plugin/pkg/scheduler/algorithm/priorities/selector_spreading.go
View file @
4aa92bac
...
@@ -17,12 +17,10 @@ limitations under the License.
...
@@ -17,12 +17,10 @@ limitations under the License.
package
priorities
package
priorities
import
(
import
(
"
sync
"
"
fmt
"
"k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/util/workqueue"
utilnode
"k8s.io/kubernetes/pkg/util/node"
utilnode
"k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
schedulerapi
"k8s.io/kubernetes/plugin/pkg/scheduler/api"
schedulerapi
"k8s.io/kubernetes/plugin/pkg/scheduler/api"
...
@@ -46,149 +44,135 @@ func NewSelectorSpreadPriority(
...
@@ -46,149 +44,135 @@ func NewSelectorSpreadPriority(
serviceLister
algorithm
.
ServiceLister
,
serviceLister
algorithm
.
ServiceLister
,
controllerLister
algorithm
.
ControllerLister
,
controllerLister
algorithm
.
ControllerLister
,
replicaSetLister
algorithm
.
ReplicaSetLister
,
replicaSetLister
algorithm
.
ReplicaSetLister
,
statefulSetLister
algorithm
.
StatefulSetLister
)
algorithm
.
PriorityFunction
{
statefulSetLister
algorithm
.
StatefulSetLister
)
(
algorithm
.
PriorityMapFunction
,
algorithm
.
PriorityReduceFunction
)
{
selectorSpread
:=
&
SelectorSpread
{
selectorSpread
:=
&
SelectorSpread
{
serviceLister
:
serviceLister
,
serviceLister
:
serviceLister
,
controllerLister
:
controllerLister
,
controllerLister
:
controllerLister
,
replicaSetLister
:
replicaSetLister
,
replicaSetLister
:
replicaSetLister
,
statefulSetLister
:
statefulSetLister
,
statefulSetLister
:
statefulSetLister
,
}
}
return
selectorSpread
.
CalculateSpreadPriority
return
selectorSpread
.
CalculateSpreadPriority
Map
,
selectorSpread
.
CalculateSpreadPriorityReduce
}
}
// Returns selectors of services, RCs and RSs matching the given pod.
// CalculateSpreadPriorityMap spreads pods across hosts, considering pods belonging to the same service or replication controller.
func
getSelectors
(
pod
*
v1
.
Pod
,
sl
algorithm
.
ServiceLister
,
cl
algorithm
.
ControllerLister
,
rsl
algorithm
.
ReplicaSetLister
,
ssl
algorithm
.
StatefulSetLister
)
[]
labels
.
Selector
{
// When a pod is scheduled, it looks for services, RCs or RSs that match the pod, then finds existing pods that match those selectors.
// It favors nodes that have fewer existing matching pods.
// i.e. it pushes the scheduler towards a node where there's the smallest number of
// pods which match the same service, RC or RS selectors as the pod being scheduled.
func
(
s
*
SelectorSpread
)
CalculateSpreadPriorityMap
(
pod
*
v1
.
Pod
,
meta
interface
{},
nodeInfo
*
schedulercache
.
NodeInfo
)
(
schedulerapi
.
HostPriority
,
error
)
{
var
selectors
[]
labels
.
Selector
var
selectors
[]
labels
.
Selector
if
services
,
err
:=
sl
.
GetPodServices
(
pod
);
err
==
nil
{
node
:=
nodeInfo
.
Node
()
for
_
,
service
:=
range
services
{
if
node
==
nil
{
selectors
=
append
(
selectors
,
labels
.
SelectorFromSet
(
service
.
Spec
.
Selector
))
return
schedulerapi
.
HostPriority
{},
fmt
.
Errorf
(
"node not found"
)
}
}
}
if
rcs
,
err
:=
cl
.
GetPodControllers
(
pod
);
err
==
nil
{
for
_
,
rc
:=
range
rcs
{
priorityMeta
,
ok
:=
meta
.
(
*
priorityMetadata
)
selectors
=
append
(
selectors
,
labels
.
SelectorFromSet
(
rc
.
Spec
.
Selector
))
if
ok
{
}
selectors
=
priorityMeta
.
podSelectors
}
else
{
selectors
=
getSelectors
(
pod
,
s
.
serviceLister
,
s
.
controllerLister
,
s
.
replicaSetLister
,
s
.
statefulSetLister
)
}
}
if
rss
,
err
:=
rsl
.
GetPodReplicaSets
(
pod
);
err
==
nil
{
for
_
,
rs
:=
range
rss
{
if
len
(
selectors
)
==
0
{
if
selector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
rs
.
Spec
.
Selector
);
err
==
nil
{
return
schedulerapi
.
HostPriority
{
selectors
=
append
(
selectors
,
selector
)
Host
:
node
.
Name
,
}
Score
:
int
(
0
),
}
}
,
nil
}
}
if
sss
,
err
:=
ssl
.
GetPodStatefulSets
(
pod
);
err
==
nil
{
for
_
,
ss
:=
range
sss
{
count
:=
float64
(
0
)
if
selector
,
err
:=
metav1
.
LabelSelectorAsSelector
(
ss
.
Spec
.
Selector
);
err
==
nil
{
for
_
,
nodePod
:=
range
nodeInfo
.
Pods
()
{
selectors
=
append
(
selectors
,
selector
)
if
pod
.
Namespace
!=
nodePod
.
Namespace
{
continue
}
// When we are replacing a failed pod, we often see the previous
// deleted version while scheduling the replacement.
// Ignore the previous deleted version for spreading purposes
// (it can still be considered for resource restrictions etc.)
if
nodePod
.
DeletionTimestamp
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"skipping pending-deleted pod: %s/%s"
,
nodePod
.
Namespace
,
nodePod
.
Name
)
continue
}
matches
:=
false
for
_
,
selector
:=
range
selectors
{
if
selector
.
Matches
(
labels
.
Set
(
nodePod
.
ObjectMeta
.
Labels
))
{
matches
=
true
break
}
}
}
}
if
matches
{
count
++
}
}
}
return
selectors
return
schedulerapi
.
HostPriority
{
}
Host
:
node
.
Name
,
Score
:
int
(
count
),
func
(
s
*
SelectorSpread
)
getSelectors
(
pod
*
v1
.
Pod
)
[]
labels
.
Selector
{
},
nil
return
getSelectors
(
pod
,
s
.
serviceLister
,
s
.
controllerLister
,
s
.
replicaSetLister
,
s
.
statefulSetLister
)
}
}
// CalculateSpreadPriority spreads pods across hosts and zones, considering pods belonging to the same service or replication controller.
// CalculateSpreadPriorityReduce calculates the source of each node based on the number of existing matching pods on the node
// When a pod is scheduled, it looks for services, RCs or RSs that match the pod, then finds existing pods that match those selectors.
// where zone information is included on the nodes, it favors nodes in zones with fewer existing matching pods.
// It favors nodes that have fewer existing matching pods.
func
(
s
*
SelectorSpread
)
CalculateSpreadPriorityReduce
(
pod
*
v1
.
Pod
,
meta
interface
{},
nodeNameToInfo
map
[
string
]
*
schedulercache
.
NodeInfo
,
result
schedulerapi
.
HostPriorityList
)
error
{
// i.e. it pushes the scheduler towards a node where there's the smallest number of
var
selectors
[]
labels
.
Selector
// pods which match the same service, RC or RS selectors as the pod being scheduled.
countsByZone
:=
make
(
map
[
string
]
int
,
10
)
// Where zone information is included on the nodes, it favors nodes in zones with fewer existing matching pods.
maxCountByZone
:=
int
(
0
)
func
(
s
*
SelectorSpread
)
CalculateSpreadPriority
(
pod
*
v1
.
Pod
,
nodeNameToInfo
map
[
string
]
*
schedulercache
.
NodeInfo
,
nodes
[]
*
v1
.
Node
)
(
schedulerapi
.
HostPriorityList
,
error
)
{
maxCountByNodeName
:=
int
(
0
)
selectors
:=
s
.
getSelectors
(
pod
)
// Count similar pods by node
priorityMeta
,
ok
:=
meta
.
(
*
priorityMetadata
)
countsByNodeName
:=
make
(
map
[
string
]
float64
,
len
(
nodes
))
if
ok
{
countsByZone
:=
make
(
map
[
string
]
float64
,
10
)
selectors
=
priorityMeta
.
podSelectors
maxCountByNodeName
:=
float64
(
0
)
}
else
{
countsByNodeNameLock
:=
sync
.
Mutex
{}
selectors
=
getSelectors
(
pod
,
s
.
serviceLister
,
s
.
controllerLister
,
s
.
replicaSetLister
,
s
.
statefulSetLister
)
}
if
len
(
selectors
)
>
0
{
if
len
(
selectors
)
>
0
{
processNodeFunc
:=
func
(
i
int
)
{
for
i
:=
range
result
{
nodeName
:=
nodes
[
i
]
.
Name
if
result
[
i
]
.
Score
>
maxCountByNodeName
{
count
:=
float64
(
0
)
maxCountByNodeName
=
result
[
i
]
.
Score
for
_
,
nodePod
:=
range
nodeNameToInfo
[
nodeName
]
.
Pods
()
{
if
pod
.
Namespace
!=
nodePod
.
Namespace
{
continue
}
// When we are replacing a failed pod, we often see the previous
// deleted version while scheduling the replacement.
// Ignore the previous deleted version for spreading purposes
// (it can still be considered for resource restrictions etc.)
if
nodePod
.
DeletionTimestamp
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"skipping pending-deleted pod: %s/%s"
,
nodePod
.
Namespace
,
nodePod
.
Name
)
continue
}
matches
:=
false
for
_
,
selector
:=
range
selectors
{
if
selector
.
Matches
(
labels
.
Set
(
nodePod
.
ObjectMeta
.
Labels
))
{
matches
=
true
break
}
}
if
matches
{
count
++
}
}
zoneId
:=
utilnode
.
GetZoneKey
(
nodes
[
i
])
countsByNodeNameLock
.
Lock
()
defer
countsByNodeNameLock
.
Unlock
()
countsByNodeName
[
nodeName
]
=
count
if
count
>
maxCountByNodeName
{
maxCountByNodeName
=
count
}
}
if
zoneId
!=
""
{
zoneId
:=
utilnode
.
GetZoneKey
(
nodeNameToInfo
[
result
[
i
]
.
Host
]
.
Node
())
countsByZone
[
zoneId
]
+=
count
if
zoneId
==
""
{
continue
}
}
countsByZone
[
zoneId
]
+=
result
[
i
]
.
Score
}
}
workqueue
.
Parallelize
(
16
,
len
(
nodes
),
processNodeFunc
)
}
}
// Aggregate by-zone information
for
zoneId
:=
range
countsByZone
{
// Compute the maximum number of pods hosted in any zone
if
countsByZone
[
zoneId
]
>
maxCountByZone
{
haveZones
:=
len
(
countsByZone
)
!=
0
maxCountByZone
=
countsByZone
[
zoneId
]
maxCountByZone
:=
float64
(
0
)
for
_
,
count
:=
range
countsByZone
{
if
count
>
maxCountByZone
{
maxCountByZone
=
count
}
}
}
}
result
:=
make
(
schedulerapi
.
HostPriorityList
,
0
,
len
(
nodes
))
haveZones
:=
len
(
countsByZone
)
!=
0
//score int - scale of 0-maxPriority
// 0 being the lowest priority and maxPriority being the highest
for
i
:=
range
result
{
for
_
,
node
:=
range
nodes
{
// initializing to the default/max node score of maxPriority
// initializing to the default/max node score of maxPriority
fScore
:=
float64
(
schedulerapi
.
MaxPriority
)
fScore
:=
float64
(
schedulerapi
.
MaxPriority
)
if
maxCountByNodeName
>
0
{
if
maxCountByNodeName
>
0
{
fScore
=
float64
(
schedulerapi
.
MaxPriority
)
*
(
(
maxCountByNodeName
-
countsByNodeName
[
node
.
Name
])
/
maxCountByNodeName
)
fScore
=
float64
(
schedulerapi
.
MaxPriority
)
*
(
float64
(
maxCountByNodeName
-
result
[
i
]
.
Score
)
/
float64
(
maxCountByNodeName
)
)
}
}
// If there is zone information present, incorporate it
// If there is zone information present, incorporate it
if
haveZones
{
if
haveZones
{
zoneId
:=
utilnode
.
GetZoneKey
(
node
)
zoneId
:=
utilnode
.
GetZoneKey
(
node
NameToInfo
[
result
[
i
]
.
Host
]
.
Node
()
)
if
zoneId
!=
""
{
if
zoneId
!=
""
{
zoneScore
:=
float64
(
schedulerapi
.
MaxPriority
)
zoneScore
:=
float64
(
schedulerapi
.
MaxPriority
)
if
maxCountByZone
>
0
{
if
maxCountByZone
>
0
{
zoneScore
=
float64
(
schedulerapi
.
MaxPriority
)
*
(
(
maxCountByZone
-
countsByZone
[
zoneId
])
/
maxCountByZone
)
zoneScore
=
float64
(
schedulerapi
.
MaxPriority
)
*
(
float64
(
maxCountByZone
-
countsByZone
[
zoneId
])
/
float64
(
maxCountByZone
)
)
}
}
fScore
=
(
fScore
*
(
1.0
-
zoneWeighting
))
+
(
zoneWeighting
*
zoneScore
)
fScore
=
(
fScore
*
(
1.0
-
zoneWeighting
))
+
(
zoneWeighting
*
zoneScore
)
}
}
}
}
result
[
i
]
.
Score
=
int
(
fScore
)
result
=
append
(
result
,
schedulerapi
.
HostPriority
{
Host
:
node
.
Name
,
Score
:
int
(
fScore
)})
if
glog
.
V
(
10
)
{
if
glog
.
V
(
10
)
{
// We explicitly don't do glog.V(10).Infof() to avoid computing all the parameters if this is
// We explicitly don't do glog.V(10).Infof() to avoid computing all the parameters if this is
// not logged. There is visible performance gain from it.
// not logged. There is visible performance gain from it.
glog
.
V
(
10
)
.
Infof
(
glog
.
V
(
10
)
.
Infof
(
"%v -> %v: SelectorSpreadPriority, Score: (%d)"
,
pod
.
Name
,
node
.
Name
,
int
(
fScore
),
"%v -> %v: SelectorSpreadPriority, Score: (%d)"
,
pod
.
Name
,
result
[
i
]
.
Host
,
int
(
fScore
),
)
)
}
}
}
}
return
result
,
nil
return
nil
}
}
type
ServiceAntiAffinity
struct
{
type
ServiceAntiAffinity
struct
{
...
...
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