Skip to content

Commit b477b39

Browse files
refactor: use shared functions to reduce redundancy in estimator pkg
Signed-off-by: changzhen <changzhen5@huawei.com>
1 parent 5d72d49 commit b477b39

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

pkg/estimator/scheduling_simulator_components.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package estimator
1818

1919
import (
2020
corev1 "k8s.io/api/core/v1"
21+
"k8s.io/component-helpers/scheduling/corev1/nodeaffinity"
2122

2223
"github.com/karmada-io/karmada/pkg/estimator/pb"
2324
nodeutil "github.com/karmada-io/karmada/pkg/estimator/server/nodes"
@@ -76,10 +77,10 @@ func (s *SchedulingSimulator) scheduleComponent(component pb.Component) bool {
7677
requiredPerReplica := util.NewResource(component.ReplicaRequirements.ResourceRequest)
7778
requiredPerReplica.AllowedPodNumber = 1
7879
remaining := component.Replicas
79-
nodeClaim := component.ReplicaRequirements.NodeClaim
80+
affinity, tolerations := GetAffinityAndTolerations(component.ReplicaRequirements.NodeClaim)
8081

8182
for _, node := range s.nodes {
82-
if !matchNode(nodeClaim, node) {
83+
if !MatchNode(node, affinity, tolerations) {
8384
continue
8485
}
8586

@@ -102,19 +103,22 @@ func (s *SchedulingSimulator) scheduleComponent(component pb.Component) bool {
102103
return remaining == 0
103104
}
104105

105-
// matchNode checks whether the node matches the scheduling constraints defined in the replica requirements.
106-
func matchNode(nodeClaim *pb.NodeClaim, node *schedulerframework.NodeInfo) bool {
107-
if node.Node() == nil {
108-
// Always match since we lack node affinity/toleration info, so we skip these checks.
109-
return true
110-
}
111-
106+
// GetAffinityAndTolerations extracts node affinity and tolerations from a NodeClaim.
107+
func GetAffinityAndTolerations(nodeClaim *pb.NodeClaim) (nodeaffinity.RequiredNodeAffinity, []corev1.Toleration) {
112108
affinity := nodeutil.GetRequiredNodeAffinity(pb.ReplicaRequirements{NodeClaim: nodeClaim})
113109
var tolerations []corev1.Toleration
114-
115110
if nodeClaim != nil {
116111
tolerations = nodeClaim.Tolerations
117112
}
113+
return affinity, tolerations
114+
}
115+
116+
// MatchNode checks whether the node matches the node affinity and tolerations specified in the component's replica requirements.
117+
func MatchNode(node *schedulerframework.NodeInfo, affinity nodeaffinity.RequiredNodeAffinity, tolerations []corev1.Toleration) bool {
118+
if node.Node() == nil {
119+
// Always match since we lack node affinity/toleration info, so we skip these checks.
120+
return true
121+
}
118122

119123
return nodeutil.IsNodeAffinityMatched(node.Node(), affinity) && nodeutil.IsTolerationMatched(node.Node(), tolerations)
120124
}

pkg/estimator/scheduling_simulator_components_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,10 @@ func TestMatchNode(t *testing.T) {
144144

145145
for _, tt := range tests {
146146
t.Run(tt.name, func(t *testing.T) {
147-
result := matchNode(tt.replicaRequirements.NodeClaim, tt.node)
147+
affinity, tolerations := GetAffinityAndTolerations(tt.replicaRequirements.NodeClaim)
148+
result := MatchNode(tt.node, affinity, tolerations)
148149
if result != tt.expected {
149-
t.Errorf("matchNode() = %v, expected %v", result, tt.expected)
150+
t.Errorf("MatchNode() = %v, expected %v", result, tt.expected)
150151
}
151152
})
152153
}

pkg/estimator/server/framework/plugins/noderesource/noderesource.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"github.com/karmada-io/karmada/pkg/estimator"
2929
"github.com/karmada-io/karmada/pkg/estimator/pb"
3030
"github.com/karmada-io/karmada/pkg/estimator/server/framework"
31-
nodeutil "github.com/karmada-io/karmada/pkg/estimator/server/nodes"
3231
"github.com/karmada-io/karmada/pkg/util"
3332
schedcache "github.com/karmada-io/karmada/pkg/util/lifted/scheduler/cache"
3433
schedulerframework "github.com/karmada-io/karmada/pkg/util/lifted/scheduler/framework"
@@ -70,27 +69,20 @@ func (pl *nodeResourceEstimator) Name() string {
7069
// Estimate the replica allowed by the node resources for a given pb.ReplicaRequirements.
7170
func (pl *nodeResourceEstimator) Estimate(ctx context.Context, snapshot *schedcache.Snapshot, requirements *pb.ReplicaRequirements) (int32, *framework.Result) {
7271
if !pl.enabled {
73-
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
74-
return noNodeConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s is disabled", pl.Name()))
72+
return pl.disabledResult()
7573
}
7674

7775
allNodes, err := snapshot.NodeInfos().List()
7876
if err != nil {
7977
return 0, framework.AsResult(err)
8078
}
81-
var (
82-
affinity = nodeutil.GetRequiredNodeAffinity(*requirements)
83-
tolerations []corev1.Toleration
84-
)
8579

86-
if requirements.NodeClaim != nil {
87-
tolerations = requirements.NodeClaim.Tolerations
88-
}
80+
affinity, tolerations := estimator.GetAffinityAndTolerations(requirements.NodeClaim)
8981

9082
var res int32
9183
processNode := func(i int) {
92-
node := allNodes[i]
93-
if !nodeutil.IsNodeAffinityMatched(node.Node(), affinity) || !nodeutil.IsTolerationMatched(node.Node(), tolerations) {
84+
node := allNodes[i].Clone()
85+
if !estimator.MatchNode(node, affinity, tolerations) {
9486
return
9587
}
9688
maxReplica := pl.nodeMaxAvailableReplica(node, requirements.ResourceRequest)
@@ -102,21 +94,28 @@ func (pl *nodeResourceEstimator) Estimate(ctx context.Context, snapshot *schedca
10294
}
10395

10496
func (pl *nodeResourceEstimator) nodeMaxAvailableReplica(node *schedulerframework.NodeInfo, rl corev1.ResourceList) int32 {
105-
rest := node.Allocatable.Clone().SubResource(node.Requested)
97+
rest := getNodeAvailableResource(node)
98+
return int32(rest.MaxDivided(rl)) // #nosec G115: integer overflow conversion int64 -> int32
99+
}
100+
101+
// getNodeAvailableResource calculates a node's available resources after deducting requested resources
102+
// and adjusting the pod-count capacity, which isn't included in node.Requested.
103+
func getNodeAvailableResource(node *schedulerframework.NodeInfo) *util.Resource {
104+
rest := node.Allocatable
105+
rest = rest.SubResource(node.Requested)
106106
// The number of pods in a node is a kind of resource in node allocatable resources.
107107
// However, total requested resources of all pods on this node, i.e. `node.Requested`,
108108
// do not contain pod resources. So after subtraction, we should cope with allowed pod
109109
// number manually which is the upper bound of this node available replicas.
110110
rest.AllowedPodNumber = util.MaxInt64(rest.AllowedPodNumber-int64(len(node.Pods)), 0)
111-
return int32(rest.MaxDivided(rl)) // #nosec G115: integer overflow conversion int64 -> int32
111+
return rest
112112
}
113113

114114
// EstimateComponents estimates the maximum number of complete component sets that can be scheduled.
115115
// It returns the number of sets that can fit on the available node resources.
116116
func (pl *nodeResourceEstimator) EstimateComponents(_ context.Context, snapshot *schedcache.Snapshot, components []pb.Component, _ string) (int32, *framework.Result) {
117117
if !pl.enabled {
118-
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
119-
return noNodeConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s is disabled", pl.Name()))
118+
return pl.disabledResult()
120119
}
121120

122121
if len(components) == 0 {
@@ -136,6 +135,11 @@ func (pl *nodeResourceEstimator) EstimateComponents(_ context.Context, snapshot
136135
return sets, framework.NewResult(framework.Success)
137136
}
138137

138+
func (pl *nodeResourceEstimator) disabledResult() (int32, *framework.Result) {
139+
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
140+
return noNodeConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s is disabled", pl.Name()))
141+
}
142+
139143
// getNodesAvailableResources retrieves and prepares the list of node information from the snapshot.
140144
// It clones each node's info and adjusts the allocatable resources by subtracting the requested resources.
141145
// So that the returned node infos reflect the actual available resources for scheduling.
@@ -148,8 +152,7 @@ func getNodesAvailableResources(snapshot *schedcache.Snapshot) ([]*schedulerfram
148152
rest := make([]*schedulerframework.NodeInfo, 0, len(allNodes))
149153
for _, node := range allNodes {
150154
n := node.Clone()
151-
n.Allocatable.SubResource(n.Requested)
152-
n.Allocatable.AllowedPodNumber = util.MaxInt64(n.Allocatable.AllowedPodNumber-int64(len(node.Pods)), 0)
155+
n.Allocatable = getNodeAvailableResource(n)
153156
rest = append(rest, n)
154157
}
155158

0 commit comments

Comments
 (0)