Skip to content

Commit d4d3d4b

Browse files
authored
Merge pull request kubernetes#86875 from ahg-g/ahg1-cleanup
Move RequestedToCapacityRatio argument processing to its plugin
2 parents dc084fe + b9e2389 commit d4d3d4b

File tree

10 files changed

+113
-180
lines changed

10 files changed

+113
-180
lines changed

pkg/scheduler/framework/plugins/BUILD

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ go_library(
3232
"//pkg/scheduler/framework/plugins/volumezone:go_default_library",
3333
"//pkg/scheduler/framework/v1alpha1:go_default_library",
3434
"//pkg/scheduler/volumebinder:go_default_library",
35-
"//staging/src/k8s.io/api/core/v1:go_default_library",
3635
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
3736
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
3837
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
@@ -82,9 +81,6 @@ go_test(
8281
embed = [":go_default_library"],
8382
deps = [
8483
"//pkg/scheduler/apis/config:go_default_library",
85-
"//pkg/scheduler/framework/plugins/noderesources:go_default_library",
86-
"//staging/src/k8s.io/api/core/v1:go_default_library",
8784
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
88-
"//vendor/github.com/stretchr/testify/assert:go_default_library",
8985
],
9086
)

pkg/scheduler/framework/plugins/legacy_registry.go

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"encoding/json"
2121
"fmt"
2222

23-
"k8s.io/api/core/v1"
2423
"k8s.io/apimachinery/pkg/runtime"
2524
"k8s.io/apimachinery/pkg/util/sets"
2625
utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -46,7 +45,6 @@ import (
4645
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumebinding"
4746
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions"
4847
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumezone"
49-
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
5048
)
5149

5250
// LegacyRegistry is used to store current state of registered predicates and priorities.
@@ -504,10 +502,8 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co
504502
}
505503

506504
if policy.Argument.RequestedToCapacityRatioArguments != nil {
507-
scoringFunctionShape, resources := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(policy.Argument.RequestedToCapacityRatioArguments)
508505
configProducerArgs.RequestedToCapacityRatioArgs = &noderesources.RequestedToCapacityRatioArgs{
509-
FunctionShape: scoringFunctionShape,
510-
ResourceToWeightMap: resources,
506+
RequestedToCapacityRatioArguments: *policy.Argument.RequestedToCapacityRatioArguments,
511507
}
512508
// We do not allow specifying the name for custom plugins, see #83472
513509
priorityName = noderesources.RequestedToCapacityRatioName
@@ -516,37 +512,6 @@ func (lr *LegacyRegistry) ProcessPriorityPolicy(policy config.PriorityPolicy, co
516512
return priorityName
517513
}
518514

519-
// TODO(ahg-g): move to RequestedToCapacityRatio plugin.
520-
func buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(arguments *config.RequestedToCapacityRatioArguments) (noderesources.FunctionShape, noderesources.ResourceToWeightMap) {
521-
n := len(arguments.Shape)
522-
points := make([]noderesources.FunctionShapePoint, 0, n)
523-
for _, point := range arguments.Shape {
524-
points = append(points, noderesources.FunctionShapePoint{
525-
Utilization: int64(point.Utilization),
526-
// MaxCustomPriorityScore may diverge from the max score used in the scheduler and defined by MaxNodeScore,
527-
// therefore we need to scale the score returned by requested to capacity ratio to the score range
528-
// used by the scheduler.
529-
Score: int64(point.Score) * (framework.MaxNodeScore / config.MaxCustomPriorityScore),
530-
})
531-
}
532-
shape, err := noderesources.NewFunctionShape(points)
533-
if err != nil {
534-
klog.Fatalf("invalid RequestedToCapacityRatioPriority arguments: %s", err.Error())
535-
}
536-
resourceToWeightMap := make(noderesources.ResourceToWeightMap)
537-
if len(arguments.Resources) == 0 {
538-
resourceToWeightMap = noderesources.DefaultRequestedRatioResources
539-
return shape, resourceToWeightMap
540-
}
541-
for _, resource := range arguments.Resources {
542-
resourceToWeightMap[v1.ResourceName(resource.Name)] = resource.Weight
543-
if resource.Weight == 0 {
544-
resourceToWeightMap[v1.ResourceName(resource.Name)] = 1
545-
}
546-
}
547-
return shape, resourceToWeightMap
548-
}
549-
550515
func validatePredicateOrDie(predicate config.PredicatePolicy) {
551516
if predicate.Argument != nil {
552517
numArgs := 0

pkg/scheduler/framework/plugins/legacy_registry_test.go

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,61 +22,9 @@ import (
2222

2323
"github.com/google/go-cmp/cmp"
2424

25-
"github.com/stretchr/testify/assert"
26-
v1 "k8s.io/api/core/v1"
2725
"k8s.io/kubernetes/pkg/scheduler/apis/config"
28-
schedulerapi "k8s.io/kubernetes/pkg/scheduler/apis/config"
29-
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
3026
)
3127

32-
func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArguments(t *testing.T) {
33-
arguments := schedulerapi.RequestedToCapacityRatioArguments{
34-
Shape: []schedulerapi.UtilizationShapePoint{
35-
{Utilization: 10, Score: 1},
36-
{Utilization: 30, Score: 5},
37-
{Utilization: 70, Score: 2},
38-
},
39-
Resources: []schedulerapi.ResourceSpec{
40-
{Name: string(v1.ResourceCPU)},
41-
{Name: string(v1.ResourceMemory)},
42-
},
43-
}
44-
builtShape, resources := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(&arguments)
45-
expectedShape, _ := noderesources.NewFunctionShape([]noderesources.FunctionShapePoint{
46-
{Utilization: 10, Score: 10},
47-
{Utilization: 30, Score: 50},
48-
{Utilization: 70, Score: 20},
49-
})
50-
expectedResources := noderesources.ResourceToWeightMap{
51-
v1.ResourceCPU: 1,
52-
v1.ResourceMemory: 1,
53-
}
54-
assert.Equal(t, expectedShape, builtShape)
55-
assert.Equal(t, expectedResources, resources)
56-
}
57-
58-
func TestBuildScoringFunctionShapeFromRequestedToCapacityRatioArgumentsNilResourceToWeightMap(t *testing.T) {
59-
arguments := schedulerapi.RequestedToCapacityRatioArguments{
60-
Shape: []schedulerapi.UtilizationShapePoint{
61-
{Utilization: 10, Score: 1},
62-
{Utilization: 30, Score: 5},
63-
{Utilization: 70, Score: 2},
64-
},
65-
}
66-
builtShape, resources := buildScoringFunctionShapeFromRequestedToCapacityRatioArguments(&arguments)
67-
expectedShape, _ := noderesources.NewFunctionShape([]noderesources.FunctionShapePoint{
68-
{Utilization: 10, Score: 10},
69-
{Utilization: 30, Score: 50},
70-
{Utilization: 70, Score: 20},
71-
})
72-
expectedResources := noderesources.ResourceToWeightMap{
73-
v1.ResourceCPU: 1,
74-
v1.ResourceMemory: 1,
75-
}
76-
assert.Equal(t, expectedShape, builtShape)
77-
assert.Equal(t, expectedResources, resources)
78-
}
79-
8028
func produceConfig(keys []string, producersMap map[string]ConfigProducer, args ConfigProducerArgs) (*config.Plugins, []config.PluginConfig, error) {
8129
var plugins config.Plugins
8230
var pluginConfig []config.PluginConfig

pkg/scheduler/framework/plugins/noderesources/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ go_library(
1919
"//pkg/features:go_default_library",
2020
"//pkg/scheduler/algorithm/predicates:go_default_library",
2121
"//pkg/scheduler/algorithm/priorities/util:go_default_library",
22+
"//pkg/scheduler/apis/config:go_default_library",
2223
"//pkg/scheduler/framework/plugins/migration:go_default_library",
2324
"//pkg/scheduler/framework/v1alpha1:go_default_library",
2425
"//pkg/scheduler/nodeinfo:go_default_library",

pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func NewBalancedAllocation(_ *runtime.Unknown, h framework.FrameworkHandle) (fra
7474
resourceAllocationScorer: resourceAllocationScorer{
7575
BalancedAllocationName,
7676
balancedResourceScorer,
77-
DefaultRequestedRatioResources,
77+
defaultRequestedRatioResources,
7878
},
7979
}, nil
8080
}

pkg/scheduler/framework/plugins/noderesources/least_allocated.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ func NewLeastAllocated(_ *runtime.Unknown, h framework.FrameworkHandle) (framewo
6969
resourceAllocationScorer: resourceAllocationScorer{
7070
LeastAllocatedName,
7171
leastResourceScorer,
72-
DefaultRequestedRatioResources,
72+
defaultRequestedRatioResources,
7373
},
7474
}, nil
7575
}
7676

7777
func leastResourceScorer(requested, allocable resourceToValueMap, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 {
7878
var nodeScore, weightSum int64
79-
for resource, weight := range DefaultRequestedRatioResources {
79+
for resource, weight := range defaultRequestedRatioResources {
8080
resourceScore := leastRequestedScore(requested[resource], allocable[resource])
8181
nodeScore += resourceScore * weight
8282
weightSum += weight

pkg/scheduler/framework/plugins/noderesources/most_allocated.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ func NewMostAllocated(_ *runtime.Unknown, h framework.FrameworkHandle) (framewor
6767
resourceAllocationScorer: resourceAllocationScorer{
6868
MostAllocatedName,
6969
mostResourceScorer,
70-
DefaultRequestedRatioResources,
70+
defaultRequestedRatioResources,
7171
},
7272
}, nil
7373
}
7474

7575
func mostResourceScorer(requested, allocable resourceToValueMap, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64 {
7676
var nodeScore, weightSum int64
77-
for resource, weight := range DefaultRequestedRatioResources {
77+
for resource, weight := range defaultRequestedRatioResources {
7878
resourceScore := mostRequestedScore(requested[resource], allocable[resource])
7979
nodeScore += resourceScore * weight
8080
weightSum += weight

pkg/scheduler/framework/plugins/noderesources/requested_to_capacity_ratio.go

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
v1 "k8s.io/api/core/v1"
2525
"k8s.io/apimachinery/pkg/runtime"
2626
"k8s.io/klog"
27+
"k8s.io/kubernetes/pkg/scheduler/apis/config"
2728
framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
2829
)
2930

@@ -36,37 +37,61 @@ const (
3637
maxScore = framework.MaxNodeScore
3738
)
3839

39-
// FunctionShape represents shape of scoring function.
40-
// For safety use NewFunctionShape which performs precondition checks for struct creation.
41-
type FunctionShape []FunctionShapePoint
40+
// RequestedToCapacityRatioArgs holds the args that are used to configure the plugin.
41+
type RequestedToCapacityRatioArgs struct {
42+
config.RequestedToCapacityRatioArguments
43+
}
4244

43-
// FunctionShapePoint represents single point in scoring function shape.
44-
type FunctionShapePoint struct {
45+
type functionShape []functionShapePoint
46+
47+
type functionShapePoint struct {
4548
// Utilization is function argument.
46-
Utilization int64
49+
utilization int64
4750
// Score is function value.
48-
Score int64
49-
}
50-
51-
// RequestedToCapacityRatioArgs holds the args that are used to configure the plugin.
52-
type RequestedToCapacityRatioArgs struct {
53-
FunctionShape FunctionShape
54-
ResourceToWeightMap ResourceToWeightMap
51+
score int64
5552
}
5653

5754
// NewRequestedToCapacityRatio initializes a new plugin and returns it.
5855
func NewRequestedToCapacityRatio(plArgs *runtime.Unknown, handle framework.FrameworkHandle) (framework.Plugin, error) {
59-
args := &RequestedToCapacityRatioArgs{}
56+
args := &config.RequestedToCapacityRatioArguments{}
6057
if err := framework.DecodeInto(plArgs, args); err != nil {
6158
return nil, err
6259
}
6360

61+
shape := make([]functionShapePoint, 0, len(args.Shape))
62+
for _, point := range args.Shape {
63+
shape = append(shape, functionShapePoint{
64+
utilization: int64(point.Utilization),
65+
// MaxCustomPriorityScore may diverge from the max score used in the scheduler and defined by MaxNodeScore,
66+
// therefore we need to scale the score returned by requested to capacity ratio to the score range
67+
// used by the scheduler.
68+
score: int64(point.Score) * (framework.MaxNodeScore / config.MaxCustomPriorityScore),
69+
})
70+
}
71+
72+
if err := validateFunctionShape(shape); err != nil {
73+
return nil, err
74+
}
75+
76+
resourceToWeightMap := make(resourceToWeightMap)
77+
for _, resource := range args.Resources {
78+
resourceToWeightMap[v1.ResourceName(resource.Name)] = resource.Weight
79+
if resource.Weight == 0 {
80+
// Apply the default weight.
81+
resourceToWeightMap[v1.ResourceName(resource.Name)] = 1
82+
}
83+
}
84+
if len(args.Resources) == 0 {
85+
// If no resources specified, used the default set.
86+
resourceToWeightMap = defaultRequestedRatioResources
87+
}
88+
6489
return &RequestedToCapacityRatio{
6590
handle: handle,
6691
resourceAllocationScorer: resourceAllocationScorer{
6792
RequestedToCapacityRatioName,
68-
buildRequestedToCapacityRatioScorerFunction(args.FunctionShape, args.ResourceToWeightMap),
69-
args.ResourceToWeightMap,
93+
buildRequestedToCapacityRatioScorerFunction(shape, resourceToWeightMap),
94+
resourceToWeightMap,
7095
},
7196
}, nil
7297
}
@@ -99,44 +124,36 @@ func (pl *RequestedToCapacityRatio) ScoreExtensions() framework.ScoreExtensions
99124
return nil
100125
}
101126

102-
// NewFunctionShape creates instance of FunctionShape in a safe way performing all
103-
// necessary sanity checks.
104-
func NewFunctionShape(points []FunctionShapePoint) (FunctionShape, error) {
105-
106-
n := len(points)
107-
108-
if n == 0 {
109-
return nil, fmt.Errorf("at least one point must be specified")
127+
func validateFunctionShape(shape functionShape) error {
128+
if len(shape) == 0 {
129+
return fmt.Errorf("at least one point must be specified")
110130
}
111131

112-
for i := 1; i < n; i++ {
113-
if points[i-1].Utilization >= points[i].Utilization {
114-
return nil, fmt.Errorf("utilization values must be sorted. Utilization[%d]==%d >= Utilization[%d]==%d", i-1, points[i-1].Utilization, i, points[i].Utilization)
132+
for i := 1; i < len(shape); i++ {
133+
if shape[i-1].utilization >= shape[i].utilization {
134+
return fmt.Errorf("utilization values must be sorted. Utilization[%d]==%d >= Utilization[%d]==%d", i-1, shape[i-1].utilization, i, shape[i].utilization)
115135
}
116136
}
117137

118-
for i, point := range points {
119-
if point.Utilization < minUtilization {
120-
return nil, fmt.Errorf("utilization values must not be less than %d. Utilization[%d]==%d", minUtilization, i, point.Utilization)
138+
for i, point := range shape {
139+
if point.utilization < minUtilization {
140+
return fmt.Errorf("utilization values must not be less than %d. Utilization[%d]==%d", minUtilization, i, point.utilization)
121141
}
122-
if point.Utilization > maxUtilization {
123-
return nil, fmt.Errorf("utilization values must not be greater than %d. Utilization[%d]==%d", maxUtilization, i, point.Utilization)
142+
if point.utilization > maxUtilization {
143+
return fmt.Errorf("utilization values must not be greater than %d. Utilization[%d]==%d", maxUtilization, i, point.utilization)
124144
}
125-
if point.Score < minScore {
126-
return nil, fmt.Errorf("score values must not be less than %d. Score[%d]==%d", minScore, i, point.Score)
145+
if point.score < minScore {
146+
return fmt.Errorf("score values must not be less than %d. Score[%d]==%d", minScore, i, point.score)
127147
}
128-
if point.Score > maxScore {
129-
return nil, fmt.Errorf("score valuses not be greater than %d. Score[%d]==%d", maxScore, i, point.Score)
148+
if int64(point.score) > maxScore {
149+
return fmt.Errorf("score values not be greater than %d. Score[%d]==%d", maxScore, i, point.score)
130150
}
131151
}
132152

133-
// We make defensive copy so we make no assumption if array passed as argument is not changed afterwards
134-
pointsCopy := make(FunctionShape, n)
135-
copy(pointsCopy, points)
136-
return pointsCopy, nil
153+
return nil
137154
}
138155

139-
func validateResourceWeightMap(resourceToWeightMap ResourceToWeightMap) error {
156+
func validateResourceWeightMap(resourceToWeightMap resourceToWeightMap) error {
140157
if len(resourceToWeightMap) == 0 {
141158
return fmt.Errorf("resourceToWeightMap cannot be nil")
142159
}
@@ -149,7 +166,7 @@ func validateResourceWeightMap(resourceToWeightMap ResourceToWeightMap) error {
149166
return nil
150167
}
151168

152-
func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionShape, resourceToWeightMap ResourceToWeightMap) func(resourceToValueMap, resourceToValueMap, bool, int, int) int64 {
169+
func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape functionShape, resourceToWeightMap resourceToWeightMap) func(resourceToValueMap, resourceToValueMap, bool, int, int) int64 {
153170
rawScoringFunction := buildBrokenLinearFunction(scoringFunctionShape)
154171
err := validateResourceWeightMap(resourceToWeightMap)
155172
if err != nil {
@@ -179,25 +196,24 @@ func buildRequestedToCapacityRatioScorerFunction(scoringFunctionShape FunctionSh
179196
}
180197

181198
// Creates a function which is built using linear segments. Segments are defined via shape array.
182-
// Shape[i].Utilization slice represents points on "utilization" axis where different segments meet.
183-
// Shape[i].Score represents function values at meeting points.
199+
// Shape[i].utilization slice represents points on "utilization" axis where different segments meet.
200+
// Shape[i].score represents function values at meeting points.
184201
//
185202
// function f(p) is defined as:
186-
// shape[0].Score for p < f[0].Utilization
187-
// shape[i].Score for p == shape[i].Utilization
188-
// shape[n-1].Score for p > shape[n-1].Utilization
189-
// and linear between points (p < shape[i].Utilization)
190-
func buildBrokenLinearFunction(shape FunctionShape) func(int64) int64 {
191-
n := len(shape)
203+
// shape[0].score for p < f[0].utilization
204+
// shape[i].score for p == shape[i].utilization
205+
// shape[n-1].score for p > shape[n-1].utilization
206+
// and linear between points (p < shape[i].utilization)
207+
func buildBrokenLinearFunction(shape functionShape) func(int64) int64 {
192208
return func(p int64) int64 {
193-
for i := 0; i < n; i++ {
194-
if p <= shape[i].Utilization {
209+
for i := 0; i < len(shape); i++ {
210+
if p <= int64(shape[i].utilization) {
195211
if i == 0 {
196-
return shape[0].Score
212+
return shape[0].score
197213
}
198-
return shape[i-1].Score + (shape[i].Score-shape[i-1].Score)*(p-shape[i-1].Utilization)/(shape[i].Utilization-shape[i-1].Utilization)
214+
return shape[i-1].score + (shape[i].score-shape[i-1].score)*(p-shape[i-1].utilization)/(shape[i].utilization-shape[i-1].utilization)
199215
}
200216
}
201-
return shape[n-1].Score
217+
return shape[len(shape)-1].score
202218
}
203219
}

0 commit comments

Comments
 (0)