Skip to content

Commit bbb3443

Browse files
committed
Add NodeMetadata scoring plugin
Signed-off-by: Alik Khilazhev <7482065+alikhil@users.noreply.github.com>
1 parent d21b970 commit bbb3443

20 files changed

+2205
-0
lines changed

apis/config/register.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
4545
&NetworkOverheadArgs{},
4646
&SySchedArgs{},
4747
&PeaksArgs{},
48+
&NodeMetadataArgs{},
4849
)
4950
return nil
5051
}

apis/config/scheme/scheme_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,78 @@ profiles:
231231
},
232232
},
233233
},
234+
{
235+
name: "v1 NodeMetadata plugin args",
236+
data: []byte(`
237+
apiVersion: kubescheduler.config.k8s.io/v1
238+
kind: KubeSchedulerConfiguration
239+
profiles:
240+
- schedulerName: scheduler-plugins
241+
pluginConfig:
242+
- name: NodeMetadata
243+
args:
244+
metadataKey: "priority"
245+
metadataSource: "Label"
246+
metadataType: "Number"
247+
scoringStrategy: "Highest"
248+
`),
249+
wantProfiles: []schedconfig.KubeSchedulerProfile{
250+
{
251+
SchedulerName: "scheduler-plugins",
252+
Plugins: defaults.PluginsV1,
253+
PluginConfig: []schedconfig.PluginConfig{
254+
{
255+
Name: "NodeMetadata",
256+
Args: &config.NodeMetadataArgs{
257+
MetadataKey: "priority",
258+
MetadataSource: config.MetadataSourceLabel,
259+
MetadataType: config.MetadataTypeNumber,
260+
ScoringStrategy: config.ScoringStrategyHighest,
261+
},
262+
},
263+
{
264+
Name: "DefaultPreemption",
265+
Args: &schedconfig.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
266+
},
267+
{
268+
Name: "DynamicResources",
269+
Args: &schedconfig.DynamicResourcesArgs{
270+
FilterTimeout: ptr.To(metav1.Duration{Duration: 10 * time.Second}),
271+
},
272+
},
273+
{
274+
Name: "InterPodAffinity",
275+
Args: &schedconfig.InterPodAffinityArgs{HardPodAffinityWeight: 1},
276+
},
277+
{
278+
Name: "NodeAffinity",
279+
Args: &schedconfig.NodeAffinityArgs{},
280+
},
281+
{
282+
Name: "NodeResourcesBalancedAllocation",
283+
Args: &schedconfig.NodeResourcesBalancedAllocationArgs{Resources: []schedconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}}},
284+
},
285+
{
286+
Name: "NodeResourcesFit",
287+
Args: &schedconfig.NodeResourcesFitArgs{
288+
ScoringStrategy: &schedconfig.ScoringStrategy{
289+
Type: schedconfig.LeastAllocated,
290+
Resources: []schedconfig.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}},
291+
},
292+
},
293+
},
294+
{
295+
Name: "PodTopologySpread",
296+
Args: &schedconfig.PodTopologySpreadArgs{DefaultingType: schedconfig.SystemDefaulting},
297+
},
298+
{
299+
Name: "VolumeBinding",
300+
Args: &schedconfig.VolumeBindingArgs{BindTimeoutSeconds: 600},
301+
},
302+
},
303+
},
304+
},
305+
},
234306
}
235307
decoder := Codecs.UniversalDecoder()
236308
for _, tt := range testCases {
@@ -348,6 +420,15 @@ func TestCodecsEncodePluginConfig(t *testing.T) {
348420
NetworkTopologyName: "net-topology-v1",
349421
},
350422
},
423+
{
424+
Name: "NodeMetadata",
425+
Args: &config.NodeMetadataArgs{
426+
MetadataKey: "priority",
427+
MetadataSource: config.MetadataSourceLabel,
428+
MetadataType: config.MetadataTypeNumber,
429+
ScoringStrategy: config.ScoringStrategyHighest,
430+
},
431+
},
351432
},
352433
},
353434
},
@@ -445,6 +526,15 @@ profiles:
445526
networkTopologyName: net-topology-v1
446527
weightsName: netCosts
447528
name: NetworkOverhead
529+
- args:
530+
apiVersion: kubescheduler.config.k8s.io/v1
531+
kind: NodeMetadataArgs
532+
metadataKey: priority
533+
metadataSource: Label
534+
metadataType: Number
535+
scoringStrategy: Highest
536+
timestampFormat: ""
537+
name: NodeMetadata
448538
schedulerName: scheduler-plugins
449539
`,
450540
},

apis/config/types.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,69 @@ type PowerModel struct {
298298
// Power = K0 + K1 * e ^(K2 * x) : where x is utilisation
299299
// Idle power of node will be K0 + K1
300300
}
301+
302+
// MetadataSourceType defines where to look for metadata
303+
type MetadataSourceType string
304+
305+
const (
306+
// MetadataSourceLabel indicates metadata should be read from node labels
307+
MetadataSourceLabel MetadataSourceType = "Label"
308+
// MetadataSourceAnnotation indicates metadata should be read from node annotations
309+
MetadataSourceAnnotation MetadataSourceType = "Annotation"
310+
)
311+
312+
// MetadataValueType defines the type of metadata value
313+
type MetadataValueType string
314+
315+
const (
316+
// MetadataTypeNumber indicates the metadata value is a numeric value
317+
MetadataTypeNumber MetadataValueType = "Number"
318+
// MetadataTypeTimestamp indicates the metadata value is a timestamp
319+
MetadataTypeTimestamp MetadataValueType = "Timestamp"
320+
)
321+
322+
// MetadataScoringStrategy defines how to score nodes based on metadata values
323+
type MetadataScoringStrategy string
324+
325+
const (
326+
// ScoringStrategyHighest favors nodes with highest numeric values
327+
ScoringStrategyHighest MetadataScoringStrategy = "Highest"
328+
// ScoringStrategyLowest favors nodes with lowest numeric values
329+
ScoringStrategyLowest MetadataScoringStrategy = "Lowest"
330+
// ScoringStrategyNewest favors nodes with newest (most recent) timestamps
331+
ScoringStrategyNewest MetadataScoringStrategy = "Newest"
332+
// ScoringStrategyOldest favors nodes with oldest timestamps
333+
ScoringStrategyOldest MetadataScoringStrategy = "Oldest"
334+
)
335+
336+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
337+
338+
// NodeMetadataArgs holds arguments used to configure the NodeMetadata plugin.
339+
type NodeMetadataArgs struct {
340+
metav1.TypeMeta
341+
342+
// MetadataKey is the name of the label or annotation to use for scoring
343+
MetadataKey string `json:"metadataKey"`
344+
345+
// MetadataSource indicates whether to read from labels or annotations
346+
// Valid values: "Label", "Annotation"
347+
MetadataSource MetadataSourceType `json:"metadataSource"`
348+
349+
// MetadataType indicates the type of value in the metadata
350+
// Valid values: "Number", "Timestamp"
351+
MetadataType MetadataValueType `json:"metadataType"`
352+
353+
// ScoringStrategy defines how nodes should be scored
354+
// For Number type: "Highest" or "Lowest"
355+
// For Timestamp type: "Newest" or "Oldest"
356+
ScoringStrategy MetadataScoringStrategy `json:"scoringStrategy"`
357+
358+
// TimestampFormat is the Go time format string for parsing timestamps
359+
// Only used when MetadataType is "Timestamp"
360+
// Default: time.RFC3339 ("2006-01-02T15:04:05Z07:00")
361+
// Examples:
362+
// - RFC3339: "2006-01-02T15:04:05Z07:00"
363+
// - Unix timestamp: Use MetadataType "Number" instead
364+
// - Custom: "2006-01-02 15:04:05"
365+
TimestampFormat string `json:"timestampFormat,omitempty"`
366+
}

apis/config/v1/conversion.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,31 @@ func Convert_config_NodeResourceTopologyMatchArgs_To_v1_NodeResourceTopologyMatc
4242
out.ScoringStrategy = (*ScoringStrategy)(unsafe.Pointer(&in.ScoringStrategy))
4343
return nil
4444
}
45+
46+
func Convert_v1_NodeMetadataArgs_To_config_NodeMetadataArgs(in *NodeMetadataArgs, out *config.NodeMetadataArgs, s conversion.Scope) error {
47+
if err := autoConvert_v1_NodeMetadataArgs_To_config_NodeMetadataArgs(in, out, s); err != nil {
48+
return err
49+
}
50+
// Manual conversions for enum types.
51+
if in.MetadataSource != nil {
52+
out.MetadataSource = *(*config.MetadataSourceType)(unsafe.Pointer(in.MetadataSource))
53+
}
54+
if in.MetadataType != nil {
55+
out.MetadataType = *(*config.MetadataValueType)(unsafe.Pointer(in.MetadataType))
56+
}
57+
if in.ScoringStrategy != nil {
58+
out.ScoringStrategy = *(*config.MetadataScoringStrategy)(unsafe.Pointer(in.ScoringStrategy))
59+
}
60+
return nil
61+
}
62+
63+
func Convert_config_NodeMetadataArgs_To_v1_NodeMetadataArgs(in *config.NodeMetadataArgs, out *NodeMetadataArgs, s conversion.Scope) error {
64+
if err := autoConvert_config_NodeMetadataArgs_To_v1_NodeMetadataArgs(in, out, s); err != nil {
65+
return err
66+
}
67+
// Manual conversions for enum types.
68+
out.MetadataSource = (*MetadataSourceType)(unsafe.Pointer(&in.MetadataSource))
69+
out.MetadataType = (*MetadataValueType)(unsafe.Pointer(&in.MetadataType))
70+
out.ScoringStrategy = (*MetadataScoringStrategy)(unsafe.Pointer(&in.ScoringStrategy))
71+
return nil
72+
}

apis/config/v1/defaults.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ package v1
1818

1919
import (
2020
"strconv"
21+
"time"
2122

2223
v1 "k8s.io/api/core/v1"
2324
"k8s.io/apimachinery/pkg/api/resource"
2425
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/utils/ptr"
27+
2528
schedulerconfigv1 "k8s.io/kube-scheduler/config/v1"
2629
k8sschedulerconfigv1 "k8s.io/kubernetes/pkg/scheduler/apis/config/v1"
2730
)
@@ -250,3 +253,10 @@ func SetDefaults_SySchedArgs(obj *SySchedArgs) {
250253
obj.DefaultProfileName = &DefaultSySchedProfileName
251254
}
252255
}
256+
257+
// SetDefaults_NodeMetadataArgs sets the default parameters for NodeMetadataArgs plugin.
258+
func SetDefaults_NodeMetadataArgs(obj *NodeMetadataArgs) {
259+
if obj.TimestampFormat == nil && obj.MetadataType != nil && *obj.MetadataType == MetadataTypeTimestamp {
260+
obj.TimestampFormat = ptr.To(time.RFC3339)
261+
}
262+
}

apis/config/v1/register.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
4747
&NetworkOverheadArgs{},
4848
&SySchedArgs{},
4949
&PeaksArgs{},
50+
&NodeMetadataArgs{},
5051
)
5152
return nil
5253
}

apis/config/v1/types.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,69 @@ type PowerModel struct {
297297
// Power = K0 + K1 * e ^(K2 * x) : where x is utilisation
298298
// Idle power of node will be K0 + K1
299299
}
300+
301+
// MetadataSourceType defines where to look for metadata
302+
type MetadataSourceType string
303+
304+
const (
305+
// MetadataSourceLabel indicates metadata should be read from node labels
306+
MetadataSourceLabel MetadataSourceType = "Label"
307+
// MetadataSourceAnnotation indicates metadata should be read from node annotations
308+
MetadataSourceAnnotation MetadataSourceType = "Annotation"
309+
)
310+
311+
// MetadataValueType defines the type of metadata value
312+
type MetadataValueType string
313+
314+
const (
315+
// MetadataTypeNumber indicates the metadata value is a numeric value
316+
MetadataTypeNumber MetadataValueType = "Number"
317+
// MetadataTypeTimestamp indicates the metadata value is a timestamp
318+
MetadataTypeTimestamp MetadataValueType = "Timestamp"
319+
)
320+
321+
// MetadataScoringStrategy defines how to score nodes based on metadata values
322+
type MetadataScoringStrategy string
323+
324+
const (
325+
// ScoringStrategyHighest favors nodes with highest numeric values
326+
ScoringStrategyHighest MetadataScoringStrategy = "Highest"
327+
// ScoringStrategyLowest favors nodes with lowest numeric values
328+
ScoringStrategyLowest MetadataScoringStrategy = "Lowest"
329+
// ScoringStrategyNewest favors nodes with newest (most recent) timestamps
330+
ScoringStrategyNewest MetadataScoringStrategy = "Newest"
331+
// ScoringStrategyOldest favors nodes with oldest timestamps
332+
ScoringStrategyOldest MetadataScoringStrategy = "Oldest"
333+
)
334+
335+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
336+
337+
// NodeMetadataArgs holds arguments used to configure the NodeMetadata plugin.
338+
type NodeMetadataArgs struct {
339+
metav1.TypeMeta `json:",inline"`
340+
341+
// MetadataKey is the name of the label or annotation to use for scoring
342+
MetadataKey *string `json:"metadataKey,omitempty"`
343+
344+
// MetadataSource indicates whether to read from labels or annotations
345+
// Valid values: "Label", "Annotation"
346+
MetadataSource *MetadataSourceType `json:"metadataSource,omitempty"`
347+
348+
// MetadataType indicates the type of value in the metadata
349+
// Valid values: "Number", "Timestamp"
350+
MetadataType *MetadataValueType `json:"metadataType,omitempty"`
351+
352+
// ScoringStrategy defines how nodes should be scored
353+
// For Number type: "Highest" or "Lowest"
354+
// For Timestamp type: "Newest" or "Oldest"
355+
ScoringStrategy *MetadataScoringStrategy `json:"scoringStrategy,omitempty"`
356+
357+
// TimestampFormat is the Go time format string for parsing timestamps
358+
// Only used when MetadataType is "Timestamp"
359+
// Default: time.RFC3339 ("2006-01-02T15:04:05Z07:00")
360+
// Examples:
361+
// - RFC3339: "2006-01-02T15:04:05Z07:00"
362+
// - Unix timestamp: Use MetadataType "Number" instead
363+
// - Custom: "2006-01-02 15:04:05"
364+
TimestampFormat *string `json:"timestampFormat,omitempty"`
365+
}

apis/config/v1/zz_generated.conversion.go

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)