diff --git a/cluster-autoscaler/core/scaleup/orchestrator/orchestrator.go b/cluster-autoscaler/core/scaleup/orchestrator/orchestrator.go index 6c6b229bcc..e9d1e4085b 100644 --- a/cluster-autoscaler/core/scaleup/orchestrator/orchestrator.go +++ b/cluster-autoscaler/core/scaleup/orchestrator/orchestrator.go @@ -177,9 +177,11 @@ func (o *ScaleUpOrchestrator) ScaleUp( // Pick some expansion option. bestOption := o.autoscalingContext.ExpanderStrategy.BestOption(options, nodeInfos) if bestOption == nil || bestOption.NodeCount <= 0 { + klog.Infof("Expander filtered out all options, valid options: %d", len(options)) + podEquivalenceGroups = markAllGroupsAsUnschedulable(podEquivalenceGroups, ExpansionOptionsFilteredOutReason) return &status.ScaleUpStatus{ Result: status.ScaleUpNoOptionsAvailable, - PodsRemainUnschedulable: GetRemainingPods(podEquivalenceGroups, skippedNodeGroups), + PodsRemainUnschedulable: allPodsAsNoScaleUpInfo(podEquivalenceGroups, skippedNodeGroups), ConsideredNodeGroups: nodeGroups, }, nil } @@ -814,6 +816,23 @@ func GetRemainingPods(egs []*equivalence.PodGroup, skipped map[string]status.Rea return remaining } +// allPodsAsNoScaleUpInfo flattens all equivalence groups into a list of NoScaleUpInfo +func allPodsAsNoScaleUpInfo(egs []*equivalence.PodGroup, skipped map[string]status.Reasons) []status.NoScaleUpInfo { + noScaleUpInfos := make([]status.NoScaleUpInfo, 0, len(egs)) + for _, eg := range egs { + for _, pod := range eg.Pods { + noScaleUpInfo := status.NoScaleUpInfo{ + Pod: pod, + RejectedNodeGroups: eg.SchedulingErrors, + SkippedNodeGroups: skipped, + } + noScaleUpInfos = append(noScaleUpInfos, noScaleUpInfo) + } + } + + return noScaleUpInfos +} + // GetPodsAwaitingEvaluation returns list of pods for which CA was unable to help // this scale up loop (but should be able to help). func GetPodsAwaitingEvaluation(egs []*equivalence.PodGroup, bestOption string) []*apiv1.Pod { diff --git a/cluster-autoscaler/core/scaleup/orchestrator/rejectedreasons.go b/cluster-autoscaler/core/scaleup/orchestrator/rejectedreasons.go index b5e0ab9239..8935ac704e 100644 --- a/cluster-autoscaler/core/scaleup/orchestrator/rejectedreasons.go +++ b/cluster-autoscaler/core/scaleup/orchestrator/rejectedreasons.go @@ -34,4 +34,7 @@ func (sr *RejectedReasons) Reasons() []string { var ( // AllOrNothingReason means the node group was rejected because not all pods would fit it when using all-or-nothing strategy. AllOrNothingReason = NewRejectedReasons("not all pods would fit and scale-up is using all-or-nothing strategy") + // ExpansionOptionsFilteredOutReason means the node groups were considered as a scale-up candidates but got filtered + // out by the expander strategy. + ExpansionOptionsFilteredOutReason = NewRejectedReasons("expansion options filtered out and no longer considered") )