Skip to content

Commit 3ac2b95

Browse files
authored
Merge pull request #8744 from jackfrancis/listPods-simplified
CA: optimized pod list and classification
2 parents 503bdff + 6684df5 commit 3ac2b95

File tree

2 files changed

+37
-57
lines changed

2 files changed

+37
-57
lines changed

cluster-autoscaler/core/static_autoscaler.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) caerrors.AutoscalerErr
292292
return err
293293
}
294294

295-
originalScheduledPods, unschedulablePods, schedulerUnprocessed, err := listPods(podLister, a.BypassedSchedulers)
295+
podsBySchedulability, err := listPods(podLister, a.BypassedSchedulers)
296296
if err != nil {
297297
return caerrors.ToAutoscalerError(caerrors.ApiCallError, err)
298298
}
@@ -338,7 +338,7 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) caerrors.AutoscalerErr
338338
} else {
339339
metrics.UpdateMaxNodesCount(maxNodesCount)
340340
}
341-
nonExpendableScheduledPods := core_utils.FilterOutExpendablePods(originalScheduledPods, a.ExpendablePodsPriorityCutoff)
341+
nonExpendableScheduledPods := core_utils.FilterOutExpendablePods(podsBySchedulability.Scheduled, a.ExpendablePodsPriorityCutoff)
342342

343343
if err := a.ClusterSnapshot.SetClusterState(allNodes, nonExpendableScheduledPods, draSnapshot); err != nil {
344344
return caerrors.ToAutoscalerError(caerrors.InternalError, err).AddPrefix("failed to initialize ClusterSnapshot: ")
@@ -439,9 +439,9 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) caerrors.AutoscalerErr
439439
metrics.UpdateLastTime(metrics.Autoscaling, time.Now())
440440

441441
// SchedulerUnprocessed might be zero here if it was disabled
442-
metrics.UpdateUnschedulablePodsCount(len(unschedulablePods), len(schedulerUnprocessed))
442+
metrics.UpdateUnschedulablePodsCount(len(podsBySchedulability.Unschedulable), len(podsBySchedulability.Unprocessed))
443443
// Treat unknown pods as unschedulable, pod list processor will remove schedulable pods
444-
unschedulablePods = append(unschedulablePods, schedulerUnprocessed...)
444+
podsBySchedulability.Unschedulable = append(podsBySchedulability.Unschedulable, podsBySchedulability.Unprocessed...)
445445
// Upcoming nodes are recently created nodes that haven't registered in the cluster yet, or haven't become ready yet.
446446
upcomingCounts, registeredUpcoming := a.clusterStateRegistry.GetUpcomingNodes()
447447
// For each upcoming node we inject a placeholder node faked to appear ready into the cluster snapshot, so that we can pack unschedulable pods on
@@ -480,7 +480,7 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) caerrors.AutoscalerErr
480480
a.AutoscalingContext.DebuggingSnapshotter.SetClusterNodes(l)
481481
}
482482

483-
unschedulablePodsToHelp, err := a.processors.PodListProcessor.Process(a.AutoscalingContext, unschedulablePods)
483+
unschedulablePodsToHelp, err := a.processors.PodListProcessor.Process(a.AutoscalingContext, podsBySchedulability.Unschedulable)
484484

485485
if err != nil {
486486
klog.Warningf("Failed to process unschedulable pods: %v", err)
@@ -1156,22 +1156,18 @@ func nodeNames(ns []*apiv1.Node) []string {
11561156
return names
11571157
}
11581158

1159-
func listPods(podLister kube_util.PodLister, bypassedSchedulers map[string]bool) (scheduled, unschedulable, unprocessed []*apiv1.Pod, err error) {
1159+
func listPods(podLister kube_util.PodLister, bypassedSchedulers map[string]bool) (podsBySchedulability kube_util.PodsBySchedulability, err error) {
11601160
pods, err := podLister.List()
11611161
if err != nil {
11621162
klog.Errorf("Failed to list pods: %v", err)
1163-
return nil, nil, nil, err
1164-
}
1165-
scheduled = kube_util.ScheduledPods(pods)
1166-
unschedulable = kube_util.UnschedulablePods(pods)
1167-
if len(bypassedSchedulers) > 0 {
1168-
unprocessed = kube_util.SchedulerUnprocessedPods(pods, bypassedSchedulers)
1163+
return podsBySchedulability, err
11691164
}
1165+
podsBySchedulability = kube_util.ArrangePodsBySchedulability(pods, bypassedSchedulers)
11701166
// Skip logging in case of the boring scenario, when all pods are scheduled.
1171-
if len(pods) != len(scheduled) {
1172-
ignored := len(pods) - len(scheduled) - len(unschedulable) - len(unprocessed)
1167+
if len(pods) != len(podsBySchedulability.Scheduled) {
1168+
ignored := len(pods) - len(podsBySchedulability.Scheduled) - len(podsBySchedulability.Unschedulable) - len(podsBySchedulability.Unprocessed)
11731169
klog.Infof("Found %d pods in the cluster: %d scheduled, %d unschedulable, %d unprocessed by scheduler, %d ignored (most likely using custom scheduler)",
1174-
len(pods), len(scheduled), len(unschedulable), len(unprocessed), ignored)
1170+
len(pods), len(podsBySchedulability.Scheduled), len(podsBySchedulability.Unschedulable), len(podsBySchedulability.Unprocessed), ignored)
11751171
}
11761172
return
11771173
}

cluster-autoscaler/utils/kubernetes/listers.go

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ type listerRegistryImpl struct {
5858
statefulSetLister v1appslister.StatefulSetLister
5959
}
6060

61+
// PodsBySchedulability arranges pods by their schedulability
62+
type PodsBySchedulability struct {
63+
Scheduled []*apiv1.Pod
64+
Unschedulable []*apiv1.Pod
65+
Unprocessed []*apiv1.Pod
66+
}
67+
6168
// NewListerRegistry returns a registry providing various listers to list pods or nodes matching conditions
6269
func NewListerRegistry(allNode NodeLister, readyNode NodeLister, allPodLister PodLister, podDisruptionBudgetLister PodDisruptionBudgetLister,
6370
daemonSetLister v1appslister.DaemonSetLister, replicationControllerLister v1lister.ReplicationControllerLister,
@@ -139,7 +146,7 @@ func (r listerRegistryImpl) StatefulSetLister() v1appslister.StatefulSetLister {
139146
}
140147

141148
// PodLister lists all pods.
142-
// To filter out the scheduled or unschedulable pods the helper methods ScheduledPods and UnschedulablePods should be used.
149+
// To filter out scheduled, unschedulable, or unprocessed pods the helper method ArrangePodsBySchedulability should be used.
143150
type PodLister interface {
144151
List() ([]*apiv1.Pod, error)
145152
}
@@ -156,19 +163,6 @@ func isDeleted(pod *apiv1.Pod) bool {
156163
return pod.GetDeletionTimestamp() != nil
157164
}
158165

159-
// isUnschedulable checks whether a pod is unschedulable or not
160-
// This method doesn't check for nil ptr, it's the responsibility of the caller
161-
func isUnschedulable(pod *apiv1.Pod) bool {
162-
if isScheduled(pod) || isDeleted(pod) {
163-
return false
164-
}
165-
_, condition := podv1.GetPodCondition(&pod.Status, apiv1.PodScheduled)
166-
if condition == nil || condition.Status != apiv1.ConditionFalse || condition.Reason != apiv1.PodReasonUnschedulable {
167-
return false
168-
}
169-
return true
170-
}
171-
172166
// ScheduledPods is a helper method that returns all scheduled pods from given pod list.
173167
func ScheduledPods(allPods []*apiv1.Pod) []*apiv1.Pod {
174168
var scheduledPods []*apiv1.Pod
@@ -181,27 +175,29 @@ func ScheduledPods(allPods []*apiv1.Pod) []*apiv1.Pod {
181175
return scheduledPods
182176
}
183177

184-
// SchedulerUnprocessedPods is a helper method that returns all pods which are not yet processed by the specified bypassed schedulers
185-
func SchedulerUnprocessedPods(allPods []*apiv1.Pod, bypassedSchedulers map[string]bool) []*apiv1.Pod {
186-
var unprocessedPods []*apiv1.Pod
187-
178+
// ArrangePodsBySchedulability is a helper method that arranges pods by schedulability:
179+
// scheduled, unschedulable, and unprocessed by any any bypassed schedulers.
180+
func ArrangePodsBySchedulability(allPods []*apiv1.Pod, bypassedSchedulers map[string]bool) (podsBySchedulability PodsBySchedulability) {
188181
for _, pod := range allPods {
189-
if canBypass := bypassedSchedulers[pod.Spec.SchedulerName]; !canBypass {
182+
if isScheduled(pod) {
183+
podsBySchedulability.Scheduled = append(podsBySchedulability.Scheduled, pod)
190184
continue
191-
}
192-
// Make sure it's not scheduled or deleted
193-
if isScheduled(pod) || isDeleted(pod) || isUnschedulable(pod) {
185+
} else if isDeleted(pod) {
194186
continue
195-
}
196-
// Make sure that if it's not scheduled it's either
197-
// Not processed (condition is nil)
198-
// Or Reason is empty (not schedulerError, terminated, ...etc)
199-
_, condition := podv1.GetPodCondition(&pod.Status, apiv1.PodScheduled)
200-
if condition == nil || (condition.Status == apiv1.ConditionFalse && condition.Reason == "") {
201-
unprocessedPods = append(unprocessedPods, pod)
187+
} else {
188+
_, condition := podv1.GetPodCondition(&pod.Status, apiv1.PodScheduled)
189+
if condition != nil && condition.Status == apiv1.ConditionFalse && condition.Reason == apiv1.PodReasonUnschedulable {
190+
podsBySchedulability.Unschedulable = append(podsBySchedulability.Unschedulable, pod)
191+
} else {
192+
if canBypass := bypassedSchedulers[pod.Spec.SchedulerName]; canBypass {
193+
if condition == nil || (condition.Status == apiv1.ConditionFalse && condition.Reason == "") {
194+
podsBySchedulability.Unprocessed = append(podsBySchedulability.Unprocessed, pod)
195+
}
196+
}
197+
}
202198
}
203199
}
204-
return unprocessedPods
200+
return
205201
}
206202

207203
// SchedulingGatedPods is a helper method that returns all pods which has scheduling gate
@@ -228,18 +224,6 @@ func isSchedulingGated(pod *apiv1.Pod) bool {
228224
return false
229225
}
230226

231-
// UnschedulablePods is a helper method that returns all unschedulable pods from given pod list.
232-
func UnschedulablePods(allPods []*apiv1.Pod) []*apiv1.Pod {
233-
var unschedulablePods []*apiv1.Pod
234-
for _, pod := range allPods {
235-
if !isUnschedulable(pod) {
236-
continue
237-
}
238-
unschedulablePods = append(unschedulablePods, pod)
239-
}
240-
return unschedulablePods
241-
}
242-
243227
// AllPodLister lists all pods.
244228
type AllPodLister struct {
245229
podLister v1lister.PodLister

0 commit comments

Comments
 (0)