mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Merge pull request #80901 from draveness/feature/use-map-instead-of-array
feat: use named array instead of array in normalizing score
This commit is contained in:
commit
1906650d92
@ -804,11 +804,9 @@ func PrioritizeNodes(
|
||||
for j := range priorityConfigs {
|
||||
result[i].Score += results[j][i].Score * priorityConfigs[j].Weight
|
||||
}
|
||||
}
|
||||
|
||||
for _, scoreList := range scoresMap {
|
||||
for i := range nodes {
|
||||
result[i].Score += scoreList[i]
|
||||
for j := range scoresMap {
|
||||
result[i].Score += scoresMap[j][i].Score
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,25 +349,29 @@ func (f *framework) RunPostFilterPlugins(
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunScorePlugins runs the set of configured scoring plugins. It returns a map that
|
||||
// RunScorePlugins runs the set of configured scoring plugins. It returns a list that
|
||||
// stores for each scoring plugin name the corresponding NodeScoreList(s).
|
||||
// It also returns *Status, which is set to non-success if any of the plugins returns
|
||||
// a non-success status.
|
||||
func (f *framework) RunScorePlugins(pc *PluginContext, pod *v1.Pod, nodes []*v1.Node) (PluginToNodeScoreMap, *Status) {
|
||||
pluginToNodeScoreMap := make(PluginToNodeScoreMap, len(f.scorePlugins))
|
||||
func (f *framework) RunScorePlugins(pc *PluginContext, pod *v1.Pod, nodes []*v1.Node) (PluginToNodeScores, *Status) {
|
||||
pluginToNodeScores := make(PluginToNodeScores, len(f.scorePlugins))
|
||||
for _, pl := range f.scorePlugins {
|
||||
pluginToNodeScoreMap[pl.Name()] = make(NodeScoreList, len(nodes))
|
||||
pluginToNodeScores[pl.Name()] = make(NodeScoreList, len(nodes))
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
errCh := schedutil.NewErrorChannel()
|
||||
workqueue.ParallelizeUntil(ctx, 16, len(nodes), func(index int) {
|
||||
for _, pl := range f.scorePlugins {
|
||||
score, status := pl.Score(pc, pod, nodes[index].Name)
|
||||
nodeName := nodes[index].Name
|
||||
score, status := pl.Score(pc, pod, nodeName)
|
||||
if !status.IsSuccess() {
|
||||
errCh.SendErrorWithCancel(fmt.Errorf(status.Message()), cancel)
|
||||
return
|
||||
}
|
||||
pluginToNodeScoreMap[pl.Name()][index] = score
|
||||
pluginToNodeScores[pl.Name()][index] = NodeScore{
|
||||
Name: nodeName,
|
||||
Score: score,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -377,21 +381,21 @@ func (f *framework) RunScorePlugins(pc *PluginContext, pod *v1.Pod, nodes []*v1.
|
||||
return nil, NewStatus(Error, msg)
|
||||
}
|
||||
|
||||
return pluginToNodeScoreMap, nil
|
||||
return pluginToNodeScores, nil
|
||||
}
|
||||
|
||||
// RunNormalizeScorePlugins runs the NormalizeScore function of Score plugins.
|
||||
// It should be called after RunScorePlugins with the PluginToNodeScoreMap result.
|
||||
// It then modifies the map with normalized scores. It returns a non-success Status
|
||||
// It should be called after RunScorePlugins with the PluginToNodeScores result.
|
||||
// It then modifies the list with normalized scores. It returns a non-success Status
|
||||
// if any of the NormalizeScore functions returns a non-success status.
|
||||
func (f *framework) RunNormalizeScorePlugins(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScoreMap) *Status {
|
||||
func (f *framework) RunNormalizeScorePlugins(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScores) *Status {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
errCh := schedutil.NewErrorChannel()
|
||||
workqueue.ParallelizeUntil(ctx, 16, len(f.scoreWithNormalizePlugins), func(index int) {
|
||||
pl := f.scoreWithNormalizePlugins[index]
|
||||
nodeScoreList, ok := scores[pl.Name()]
|
||||
if !ok {
|
||||
err := fmt.Errorf("normalize score plugin %q has no corresponding scores in the PluginToNodeScoreMap", pl.Name())
|
||||
err := fmt.Errorf("normalize score plugin %q has no corresponding scores in the PluginToNodeScores", pl.Name())
|
||||
errCh.SendErrorWithCancel(err, cancel)
|
||||
return
|
||||
}
|
||||
@ -414,7 +418,7 @@ func (f *framework) RunNormalizeScorePlugins(pc *PluginContext, pod *v1.Pod, sco
|
||||
|
||||
// ApplyScoreWeights applies weights to the score results. It should be called after
|
||||
// RunNormalizeScorePlugins.
|
||||
func (f *framework) ApplyScoreWeights(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScoreMap) *Status {
|
||||
func (f *framework) ApplyScoreWeights(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScores) *Status {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
errCh := schedutil.NewErrorChannel()
|
||||
workqueue.ParallelizeUntil(ctx, 16, len(f.scorePlugins), func(index int) {
|
||||
@ -423,12 +427,12 @@ func (f *framework) ApplyScoreWeights(pc *PluginContext, pod *v1.Pod, scores Plu
|
||||
weight := f.pluginNameToWeightMap[pl.Name()]
|
||||
nodeScoreList, ok := scores[pl.Name()]
|
||||
if !ok {
|
||||
err := fmt.Errorf("score plugin %q has no corresponding scores in the PluginToNodeScoreMap", pl.Name())
|
||||
err := fmt.Errorf("score plugin %q has no corresponding scores in the PluginToNodeScores", pl.Name())
|
||||
errCh.SendErrorWithCancel(err, cancel)
|
||||
return
|
||||
}
|
||||
for i := range nodeScoreList {
|
||||
nodeScoreList[i] = nodeScoreList[i] * weight
|
||||
nodeScoreList[i].Score = nodeScoreList[i].Score * weight
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
)
|
||||
@ -67,7 +67,7 @@ func (pl *TestScorePlugin1) NormalizeScore(pc *PluginContext, pod *v1.Pod, score
|
||||
}
|
||||
// Simply decrease each node score by 1.
|
||||
for i := range scores {
|
||||
scores[i] = scores[i] - 1
|
||||
scores[i].Score = scores[i].Score - 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -91,7 +91,7 @@ func (pl *TestScorePlugin2) Name() string {
|
||||
func (pl *TestScorePlugin2) NormalizeScore(pc *PluginContext, pod *v1.Pod, scores NodeScoreList) *Status {
|
||||
// Simply force each node score to 5.
|
||||
for i := range scores {
|
||||
scores[i] = 5
|
||||
scores[i].Score = 5
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -256,8 +256,8 @@ func TestRunNormalizeScorePlugins(t *testing.T) {
|
||||
name string
|
||||
registry Registry
|
||||
plugins *config.Plugins
|
||||
input PluginToNodeScoreMap
|
||||
want PluginToNodeScoreMap
|
||||
input PluginToNodeScores
|
||||
want PluginToNodeScores
|
||||
// If err is true, we expect RunNormalizeScorePlugin to fail.
|
||||
err bool
|
||||
}{
|
||||
@ -265,54 +265,162 @@ func TestRunNormalizeScorePlugins(t *testing.T) {
|
||||
name: "no NormalizeScore plugins",
|
||||
plugins: plugin3,
|
||||
registry: registry,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
// No NormalizeScore plugin, map should be untouched.
|
||||
want: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
want: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "single Score plugin, single NormalizeScore plugin",
|
||||
registry: registry,
|
||||
plugins: plugin1,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: PluginToNodeScoreMap{
|
||||
want: PluginToNodeScores{
|
||||
// For plugin1, want=input-1.
|
||||
scorePlugin1: {1, 2},
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 1,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2 Score plugins, 2 NormalizeScore plugins",
|
||||
registry: registry,
|
||||
plugins: plugin1And2,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
scorePlugin2: {2, 4},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: PluginToNodeScoreMap{
|
||||
want: PluginToNodeScores{
|
||||
// For plugin1, want=input-1.
|
||||
scorePlugin1: {1, 2},
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 1,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 2,
|
||||
},
|
||||
},
|
||||
// For plugin2, want=5.
|
||||
scorePlugin2: {5, 5},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 5,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2 Score plugins, 1 NormalizeScore plugin",
|
||||
registry: registry,
|
||||
plugins: plugin1And3,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
scorePlugin3: {2, 4},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: PluginToNodeScoreMap{
|
||||
want: PluginToNodeScores{
|
||||
// For plugin1, want=input-1.
|
||||
scorePlugin1: {1, 2},
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 1,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 2,
|
||||
},
|
||||
},
|
||||
// No NormalizeScore for plugin 3. The node scores are untouched.
|
||||
scorePlugin3: {2, 4},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -322,9 +430,27 @@ func TestRunNormalizeScorePlugins(t *testing.T) {
|
||||
scorePlugin2: NewScorePlugin2,
|
||||
},
|
||||
plugins: plugin1And2,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
scorePlugin2: {2, 4},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
@ -332,8 +458,17 @@ func TestRunNormalizeScorePlugins(t *testing.T) {
|
||||
name: "2 plugins but score map only contains plugin1",
|
||||
registry: registry,
|
||||
plugins: plugin1And2,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
@ -368,41 +503,104 @@ func TestApplyScoreWeights(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
plugins *config.Plugins
|
||||
input PluginToNodeScoreMap
|
||||
want PluginToNodeScoreMap
|
||||
input PluginToNodeScores
|
||||
want PluginToNodeScores
|
||||
// If err is true, we expect ApplyScoreWeights to fail.
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "single Score plugin, single nodeScoreList",
|
||||
plugins: plugin1,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: PluginToNodeScoreMap{
|
||||
want: PluginToNodeScores{
|
||||
// For plugin1, want=input*weight1.
|
||||
scorePlugin1: {4, 6},
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 4,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2 Score plugins, 2 nodeScoreLists in scoreMap",
|
||||
plugins: plugin1And2,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
scorePlugin2: {2, 4},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: PluginToNodeScoreMap{
|
||||
want: PluginToNodeScores{
|
||||
// For plugin1, want=input*weight1.
|
||||
scorePlugin1: {4, 6},
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 4,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 6,
|
||||
},
|
||||
},
|
||||
// For plugin2, want=input*weight2.
|
||||
scorePlugin2: {6, 12},
|
||||
scorePlugin2: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 6,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2 Score plugins, 1 without corresponding nodeScoreList in the score map",
|
||||
plugins: plugin1And2,
|
||||
input: PluginToNodeScoreMap{
|
||||
scorePlugin1: {2, 3},
|
||||
input: PluginToNodeScores{
|
||||
scorePlugin1: {
|
||||
{
|
||||
Name: "node1",
|
||||
Score: 2,
|
||||
},
|
||||
{
|
||||
Name: "node2",
|
||||
Score: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
|
@ -31,10 +31,16 @@ import (
|
||||
type Code int
|
||||
|
||||
// NodeScoreList declares a list of nodes and their scores.
|
||||
type NodeScoreList []int
|
||||
type NodeScoreList []NodeScore
|
||||
|
||||
// PluginToNodeScoreMap declares a map from plugin name to its NodeScoreList.
|
||||
type PluginToNodeScoreMap map[string]NodeScoreList
|
||||
// NodeScore is a struct with node name and score.
|
||||
type NodeScore struct {
|
||||
Name string
|
||||
Score int
|
||||
}
|
||||
|
||||
// PluginToNodeScores declares a map from plugin name to its NodeScoreList.
|
||||
type PluginToNodeScores map[string]NodeScoreList
|
||||
|
||||
// NodeToStatusMap declares map from node name to its status.
|
||||
type NodeToStatusMap map[string]*Status
|
||||
@ -294,17 +300,17 @@ type Framework interface {
|
||||
// stores for each scoring plugin name the corresponding NodeScoreList(s).
|
||||
// It also returns *Status, which is set to non-success if any of the plugins returns
|
||||
// a non-success status.
|
||||
RunScorePlugins(pc *PluginContext, pod *v1.Pod, nodes []*v1.Node) (PluginToNodeScoreMap, *Status)
|
||||
RunScorePlugins(pc *PluginContext, pod *v1.Pod, nodes []*v1.Node) (PluginToNodeScores, *Status)
|
||||
|
||||
// RunNormalizeScorePlugins runs the normalize score plugins. It should be called after
|
||||
// RunScorePlugins with the PluginToNodeScoreMap result. It then modifies the map with
|
||||
// RunScorePlugins with the PluginToNodeScores result. It then modifies the map with
|
||||
// normalized scores. It returns a non-success Status if any of the normalize score plugins
|
||||
// returns a non-success status.
|
||||
RunNormalizeScorePlugins(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScoreMap) *Status
|
||||
RunNormalizeScorePlugins(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScores) *Status
|
||||
|
||||
// ApplyScoreWeights applies weights to the score results. It should be called after
|
||||
// RunNormalizeScorePlugins.
|
||||
ApplyScoreWeights(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScoreMap) *Status
|
||||
ApplyScoreWeights(pc *PluginContext, pod *v1.Pod, scores PluginToNodeScores) *Status
|
||||
|
||||
// RunPrebindPlugins runs the set of configured prebind plugins. It returns
|
||||
// *Status and its code is set to non-success if any of the plugins returns
|
||||
|
@ -175,15 +175,15 @@ func (*fakeFramework) RunFilterPlugins(pc *framework.PluginContext, pod *v1.Pod,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*fakeFramework) RunScorePlugins(pc *framework.PluginContext, pod *v1.Pod, nodes []*v1.Node) (framework.PluginToNodeScoreMap, *framework.Status) {
|
||||
func (*fakeFramework) RunScorePlugins(pc *framework.PluginContext, pod *v1.Pod, nodes []*v1.Node) (framework.PluginToNodeScores, *framework.Status) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (*fakeFramework) RunNormalizeScorePlugins(pc *framework.PluginContext, pod *v1.Pod, scores framework.PluginToNodeScoreMap) *framework.Status {
|
||||
func (*fakeFramework) RunNormalizeScorePlugins(pc *framework.PluginContext, pod *v1.Pod, scores framework.PluginToNodeScores) *framework.Status {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*fakeFramework) ApplyScoreWeights(pc *framework.PluginContext, pod *v1.Pod, scores framework.PluginToNodeScoreMap) *framework.Status {
|
||||
func (*fakeFramework) ApplyScoreWeights(pc *framework.PluginContext, pod *v1.Pod, scores framework.PluginToNodeScores) *framework.Status {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user