Skip to content

Commit a4d6119

Browse files
authored
Merge pull request #1645 from ingvagabund/nodeutilization-refactoring
nodeutilization: make the node classification more generic
2 parents 17d9b15 + 57bb31d commit a4d6119

File tree

4 files changed

+260
-141
lines changed

4 files changed

+260
-141
lines changed

pkg/framework/plugins/nodeutilization/highnodeutilization.go

+43-12
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,50 @@ func (h *HighNodeUtilization) Balance(ctx context.Context, nodes []*v1.Node) *fr
101101
}
102102
}
103103

104-
sourceNodes, highNodes := classifyNodes(
105-
getNodeUsage(nodes, h.usageClient),
106-
getNodeThresholds(nodes, h.args.Thresholds, h.targetThresholds, h.resourceNames, false, h.usageClient),
107-
func(node *v1.Node, usage NodeUsage, threshold NodeThresholds) bool {
108-
return isNodeWithLowUtilization(usage, threshold.lowResourceThreshold)
104+
nodesMap, nodesUsageMap, podListMap := getNodeUsageSnapshot(nodes, h.usageClient)
105+
nodeThresholdsMap := getStaticNodeThresholds(nodes, h.args.Thresholds, h.targetThresholds)
106+
nodesUsageAsNodeThresholdsMap := nodeUsageToResourceThresholds(nodesUsageMap, nodesMap)
107+
nodeGroups := classifyNodeUsage(
108+
nodesUsageAsNodeThresholdsMap,
109+
nodeThresholdsMap,
110+
[]classifierFnc{
111+
// underutilized nodes
112+
func(nodeName string, usage, threshold api.ResourceThresholds) bool {
113+
return isNodeBelowThreshold(usage, threshold)
114+
},
115+
// every other node that is schedulable
116+
func(nodeName string, usage, threshold api.ResourceThresholds) bool {
117+
if nodeutil.IsNodeUnschedulable(nodesMap[nodeName]) {
118+
klog.V(2).InfoS("Node is unschedulable", "node", klog.KObj(nodesMap[nodeName]))
119+
return false
120+
}
121+
return true
122+
},
109123
},
110-
func(node *v1.Node, usage NodeUsage, threshold NodeThresholds) bool {
111-
if nodeutil.IsNodeUnschedulable(node) {
112-
klog.V(2).InfoS("Node is unschedulable", "node", klog.KObj(node))
113-
return false
114-
}
115-
return !isNodeWithLowUtilization(usage, threshold.lowResourceThreshold)
116-
})
124+
)
125+
126+
// convert groups node []NodeInfo
127+
nodeInfos := make([][]NodeInfo, 2)
128+
category := []string{"underutilized", "overutilized"}
129+
for i := range nodeGroups {
130+
for nodeName := range nodeGroups[i] {
131+
klog.InfoS("Node is "+category[i], "node", klog.KObj(nodesMap[nodeName]), "usage", nodesUsageMap[nodeName], "usagePercentage", resourceUsagePercentages(nodesUsageMap[nodeName], nodesMap[nodeName], true))
132+
nodeInfos[i] = append(nodeInfos[i], NodeInfo{
133+
NodeUsage: NodeUsage{
134+
node: nodesMap[nodeName],
135+
usage: nodesUsageMap[nodeName], // get back the original node usage
136+
allPods: podListMap[nodeName],
137+
},
138+
thresholds: NodeThresholds{
139+
lowResourceThreshold: resourceThresholdsToNodeUsage(nodeThresholdsMap[nodeName][0], nodesMap[nodeName]),
140+
highResourceThreshold: resourceThresholdsToNodeUsage(nodeThresholdsMap[nodeName][1], nodesMap[nodeName]),
141+
},
142+
})
143+
}
144+
}
145+
146+
sourceNodes := nodeInfos[0]
147+
highNodes := nodeInfos[1]
117148

118149
// log message in one line
119150
klog.V(1).InfoS("Criteria for a node below target utilization", h.underutilizationCriteria...)

pkg/framework/plugins/nodeutilization/lownodeutilization.go

+55-13
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,64 @@ func (l *LowNodeUtilization) Balance(ctx context.Context, nodes []*v1.Node) *fra
122122
}
123123
}
124124

125-
lowNodes, sourceNodes := classifyNodes(
126-
getNodeUsage(nodes, l.usageClient),
127-
getNodeThresholds(nodes, l.args.Thresholds, l.args.TargetThresholds, l.resourceNames, l.args.UseDeviationThresholds, l.usageClient),
128-
// The node has to be schedulable (to be able to move workload there)
129-
func(node *v1.Node, usage NodeUsage, threshold NodeThresholds) bool {
130-
if nodeutil.IsNodeUnschedulable(node) {
131-
klog.V(2).InfoS("Node is unschedulable, thus not considered as underutilized", "node", klog.KObj(node))
132-
return false
133-
}
134-
return isNodeWithLowUtilization(usage, threshold.lowResourceThreshold)
135-
},
136-
func(node *v1.Node, usage NodeUsage, threshold NodeThresholds) bool {
137-
return isNodeAboveTargetUtilization(usage, threshold.highResourceThreshold)
125+
nodesMap, nodesUsageMap, podListMap := getNodeUsageSnapshot(nodes, l.usageClient)
126+
var nodeThresholdsMap map[string][]api.ResourceThresholds
127+
if l.args.UseDeviationThresholds {
128+
nodeThresholdsMap = getNodeThresholdsFromAverageNodeUsage(nodes, l.usageClient, l.args.Thresholds, l.args.TargetThresholds)
129+
} else {
130+
nodeThresholdsMap = getStaticNodeThresholds(nodes, l.args.Thresholds, l.args.TargetThresholds)
131+
}
132+
nodesUsageAsNodeThresholdsMap := nodeUsageToResourceThresholds(nodesUsageMap, nodesMap)
133+
134+
nodeGroups := classifyNodeUsage(
135+
nodesUsageAsNodeThresholdsMap,
136+
nodeThresholdsMap,
137+
[]classifierFnc{
138+
// underutilization
139+
func(nodeName string, usage, threshold api.ResourceThresholds) bool {
140+
if nodeutil.IsNodeUnschedulable(nodesMap[nodeName]) {
141+
klog.V(2).InfoS("Node is unschedulable, thus not considered as underutilized", "node", klog.KObj(nodesMap[nodeName]))
142+
return false
143+
}
144+
return isNodeBelowThreshold(usage, threshold)
145+
},
146+
// overutilization
147+
func(nodeName string, usage, threshold api.ResourceThresholds) bool {
148+
return isNodeAboveThreshold(usage, threshold)
149+
},
138150
},
139151
)
140152

153+
// convert groups node []NodeInfo
154+
nodeInfos := make([][]NodeInfo, 2)
155+
category := []string{"underutilized", "overutilized"}
156+
listedNodes := map[string]struct{}{}
157+
for i := range nodeGroups {
158+
for nodeName := range nodeGroups[i] {
159+
klog.InfoS("Node is "+category[i], "node", klog.KObj(nodesMap[nodeName]), "usage", nodesUsageMap[nodeName], "usagePercentage", resourceUsagePercentages(nodesUsageMap[nodeName], nodesMap[nodeName], true))
160+
listedNodes[nodeName] = struct{}{}
161+
nodeInfos[i] = append(nodeInfos[i], NodeInfo{
162+
NodeUsage: NodeUsage{
163+
node: nodesMap[nodeName],
164+
usage: nodesUsageMap[nodeName], // get back the original node usage
165+
allPods: podListMap[nodeName],
166+
},
167+
thresholds: NodeThresholds{
168+
lowResourceThreshold: resourceThresholdsToNodeUsage(nodeThresholdsMap[nodeName][0], nodesMap[nodeName]),
169+
highResourceThreshold: resourceThresholdsToNodeUsage(nodeThresholdsMap[nodeName][1], nodesMap[nodeName]),
170+
},
171+
})
172+
}
173+
}
174+
for nodeName := range nodesMap {
175+
if _, ok := listedNodes[nodeName]; !ok {
176+
klog.InfoS("Node is appropriately utilized", "node", klog.KObj(nodesMap[nodeName]), "usage", nodesUsageMap[nodeName], "usagePercentage", resourceUsagePercentages(nodesUsageMap[nodeName], nodesMap[nodeName], true))
177+
}
178+
}
179+
180+
lowNodes := nodeInfos[0]
181+
sourceNodes := nodeInfos[1]
182+
141183
// log message for nodes with low utilization
142184
klog.V(1).InfoS("Criteria for a node under utilization", l.underutilizationCriteria...)
143185
klog.V(1).InfoS("Number of underutilized nodes", "totalNumber", len(lowNodes))

0 commit comments

Comments
 (0)