forked from kubernetes-sigs/kube-scheduler-simulator
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplugin.go
146 lines (122 loc) · 4.07 KB
/
plugin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package nodenumber
import (
"context"
"errors"
"strconv"
"golang.org/x/xerrors"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/scheduler/framework"
frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
)
// NodeNumber is an example plugin that favors nodes that have the number suffix which is the same as the number suffix of the pod name.
// But if a reverse option is true, it favors nodes that have the number suffix which **isn't** the same as the number suffix of pod name.
//
// For example:
// With reverse option false, when schedule a pod named Pod1, a Node named Node1 gets a lower score than a node named Node9.
//
// NOTE: this plugin only handle single digit numbers only.
type NodeNumber struct {
// if reverse is true, it favors nodes that doesn't have the same number suffix.
//
// For example:
// When schedule a pod named Pod1, a Node named Node1 gets a lower score than a node named Node9.
reverse bool
}
var (
_ framework.ScorePlugin = &NodeNumber{}
_ framework.PreScorePlugin = &NodeNumber{}
)
const (
// Name is the name of the plugin used in the plugin registry and configurations.
Name = "NodeNumber"
preScoreStateKey = "PreScore" + Name
)
// Name returns the name of the plugin. It is used in logs, etc.
func (pl *NodeNumber) Name() string {
return Name
}
// preScoreState computed at PreScore and used at Score.
type preScoreState struct {
podSuffixNumber int
}
// Clone implements the mandatory Clone interface. We don't really copy the data since
// there is no need for that.
func (s *preScoreState) Clone() framework.StateData {
return s
}
func (pl *NodeNumber) PreScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
podNameLastChar := pod.Name[len(pod.Name)-1:]
podnum, err := strconv.Atoi(podNameLastChar)
if err != nil {
// return success even if its suffix is non-number.
return nil
}
s := &preScoreState{
podSuffixNumber: podnum,
}
state.Write(preScoreStateKey, s)
return nil
}
func (pl *NodeNumber) EventsToRegister() []framework.ClusterEvent {
return []framework.ClusterEvent{
{Resource: framework.Node, ActionType: framework.Add},
}
}
var ErrNotExpectedPreScoreState = errors.New("unexpected pre score state")
// Score invoked at the score extension point.
func (pl *NodeNumber) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
data, err := state.Read(preScoreStateKey)
if err != nil {
// return success even if there is no value in preScoreStateKey, since the
// suffix of pod name maybe non-number.
return 0, nil
}
s, ok := data.(*preScoreState)
if !ok {
err = xerrors.Errorf("fetched pre score state is not *preScoreState, but %T, %w", data, ErrNotExpectedPreScoreState)
return 0, framework.AsStatus(err)
}
nodeNameLastChar := nodeName[len(nodeName)-1:]
nodenum, err := strconv.Atoi(nodeNameLastChar)
if err != nil {
// return success even if its suffix is non-number.
return 0, nil
}
var matchScore int64 = 10
var nonMatchScore int64 = 0 //nolint:revive // for better readability.
if pl.reverse {
matchScore = 0
nonMatchScore = 10
}
if s.podSuffixNumber == nodenum {
// if match, node get high score.
return matchScore, nil
}
return nonMatchScore, nil
}
// ScoreExtensions of the Score plugin.
func (pl *NodeNumber) ScoreExtensions() framework.ScoreExtensions {
return nil
}
// New initializes a new plugin and returns it.
func New(arg runtime.Object, h framework.Handle) (framework.Plugin, error) {
typedArg := NodeNumberArgs{Reverse: false}
if arg != nil {
err := frameworkruntime.DecodeInto(arg, &typedArg)
if err != nil {
return nil, xerrors.Errorf("decode arg into NodeNumberArgs: %w", err)
}
klog.Info("NodeNumberArgs is successfully applied")
}
return &NodeNumber{reverse: typedArg.Reverse}, nil
}
// NodeNumberArgs is arguments for node number plugin.
//
//nolint:revive
type NodeNumberArgs struct {
metav1.TypeMeta
Reverse bool `json:"reverse"`
}