Skip to content

Commit fe3bb1d

Browse files
committed
Address next set of comments
1 parent 05e1fe1 commit fe3bb1d

File tree

7 files changed

+57
-62
lines changed

7 files changed

+57
-62
lines changed

cluster-autoscaler/core/scaledown/actuation/actuator.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func NewActuator(ctx *context.AutoscalingContext, csr *clusterstate.ClusterState
6262
clusterState: csr,
6363
nodeDeletionTracker: ndt,
6464
nodeDeletionScheduler: NewGroupDeletionScheduler(ctx, ndt, ndb, NewDefaultEvictor(deleteOptions, ndt)),
65-
budgetProcessor: budgets.NewScaleDownBudgetProcessor(ctx, ndt),
65+
budgetProcessor: budgets.NewScaleDownBudgetProcessor(ctx),
6666
deleteOptions: deleteOptions,
6767
}
6868
}
@@ -85,7 +85,7 @@ func (a *Actuator) StartDeletion(empty, drain []*apiv1.Node) (*status.ScaleDownS
8585
results, ts := a.nodeDeletionTracker.DeletionResults()
8686
scaleDownStatus := &status.ScaleDownStatus{NodeDeleteResults: results, NodeDeleteResultsAsOf: ts}
8787

88-
emptyToDelete, drainToDelete := a.budgetProcessor.CropNodes(empty, drain)
88+
emptyToDelete, drainToDelete := a.budgetProcessor.CropNodes(a.nodeDeletionTracker, empty, drain)
8989
if len(emptyToDelete) == 0 && len(drainToDelete) == 0 {
9090
scaleDownStatus.Result = status.ScaleDownNoNodeDeleted
9191
return scaleDownStatus, nil

cluster-autoscaler/core/scaledown/actuation/actuator_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,7 @@ func TestStartDeletion(t *testing.T) {
834834
actuator := Actuator{
835835
ctx: &ctx, clusterState: csr, nodeDeletionTracker: ndt,
836836
nodeDeletionScheduler: NewGroupDeletionScheduler(&ctx, ndt, ndb, evictor),
837-
budgetProcessor: budgets.NewScaleDownBudgetProcessor(&ctx, ndt),
837+
budgetProcessor: budgets.NewScaleDownBudgetProcessor(&ctx),
838838
}
839839
gotStatus, gotErr := actuator.StartDeletion(allEmptyNodes, allDrainNodes)
840840
if diff := cmp.Diff(tc.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
@@ -1068,7 +1068,7 @@ func TestStartDeletionInBatchBasic(t *testing.T) {
10681068
actuator := Actuator{
10691069
ctx: &ctx, clusterState: csr, nodeDeletionTracker: ndt,
10701070
nodeDeletionScheduler: NewGroupDeletionScheduler(&ctx, ndt, ndb, evictor),
1071-
budgetProcessor: budgets.NewScaleDownBudgetProcessor(&ctx, ndt),
1071+
budgetProcessor: budgets.NewScaleDownBudgetProcessor(&ctx),
10721072
}
10731073

10741074
for _, nodes := range deleteNodes {

cluster-autoscaler/core/scaledown/budgets/budgets.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,23 @@ type NodeGroupView struct {
3535

3636
// ScaleDownBudgetProcessor is responsible for keeping the number of nodes deleted in parallel within defined limits.
3737
type ScaleDownBudgetProcessor struct {
38-
ctx *context.AutoscalingContext
39-
actuationStatus scaledown.ActuationStatus
38+
ctx *context.AutoscalingContext
4039
}
4140

4241
// NewScaleDownBudgetProcessor creates a ScaleDownBudgetProcessor instance.
43-
func NewScaleDownBudgetProcessor(ctx *context.AutoscalingContext, as scaledown.ActuationStatus) *ScaleDownBudgetProcessor {
42+
func NewScaleDownBudgetProcessor(ctx *context.AutoscalingContext) *ScaleDownBudgetProcessor {
4443
return &ScaleDownBudgetProcessor{
45-
ctx: ctx,
46-
actuationStatus: as,
44+
ctx: ctx,
4745
}
4846
}
4947

5048
// CropNodes crops the provided node lists to respect scale-down max parallelism budgets.
5149
// The returned nodes are grouped by a node group.
52-
func (bp *ScaleDownBudgetProcessor) CropNodes(empty, drain []*apiv1.Node) (emptyToDelete, drainToDelete []*NodeGroupView) {
50+
func (bp *ScaleDownBudgetProcessor) CropNodes(as scaledown.ActuationStatus, empty, drain []*apiv1.Node) (emptyToDelete, drainToDelete []*NodeGroupView) {
5351
emptyIndividual, emptyAtomic := bp.categorize(bp.group(empty))
5452
drainIndividual, drainAtomic := bp.categorize(bp.group(drain))
5553

56-
emptyInProgress, drainInProgress := bp.actuationStatus.DeletionsInProgress()
54+
emptyInProgress, drainInProgress := as.DeletionsInProgress()
5755
parallelismBudget := bp.ctx.MaxScaleDownParallelism - len(emptyInProgress) - len(drainInProgress)
5856
drainBudget := bp.ctx.MaxDrainParallelism - len(drainInProgress)
5957

cluster-autoscaler/core/scaledown/budgets/budgets_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ func TestCropNodesToBudgets(t *testing.T) {
335335
drainList = append(drainList, bucket.Nodes...)
336336
}
337337

338-
budgeter := NewScaleDownBudgetProcessor(ctx, ndt)
339-
gotEmpty, gotDrain := budgeter.CropNodes(emptyList, drainList)
338+
budgeter := NewScaleDownBudgetProcessor(ctx)
339+
gotEmpty, gotDrain := budgeter.CropNodes(ndt, emptyList, drainList)
340340
if diff := cmp.Diff(tc.wantEmpty, gotEmpty, cmpopts.EquateEmpty(), transformNodeGroupView); diff != "" {
341341
t.Errorf("cropNodesToBudgets empty nodes diff (-want +got):\n%s", diff)
342342
}

cluster-autoscaler/core/scaledown/planner/planner.go

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
apiv1 "k8s.io/api/core/v1"
2525
policyv1 "k8s.io/api/policy/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
2827
"k8s.io/autoscaler/cluster-autoscaler/context"
2928
"k8s.io/autoscaler/cluster-autoscaler/core/scaledown"
3029
"k8s.io/autoscaler/cluster-autoscaler/core/scaledown/eligibility"
@@ -169,51 +168,9 @@ func (p *Planner) NodesToDelete(_ time.Time) (empty, needDrain []*apiv1.Node) {
169168
}
170169
}
171170

172-
empty, filteredOut := p.filterOutIncompleteAtomicNodeGroups(empty)
173-
needDrain, _ = p.filterOutIncompleteAtomicNodeGroups(append(needDrain, filteredOut...))
174171
return empty, needDrain
175172
}
176173

177-
func (p *Planner) filterOutIncompleteAtomicNodeGroups(nodes []*apiv1.Node) ([]*apiv1.Node, []*apiv1.Node) {
178-
nodesByGroup := map[cloudprovider.NodeGroup][]*apiv1.Node{}
179-
result := []*apiv1.Node{}
180-
filteredOut := []*apiv1.Node{}
181-
for _, node := range nodes {
182-
nodeGroup, err := p.context.CloudProvider.NodeGroupForNode(node)
183-
if err != nil {
184-
klog.Errorf("Node %v will not scale down, failed to get node info: %s", node.Name, err)
185-
continue
186-
}
187-
autoscalingOptions, err := nodeGroup.GetOptions(p.context.NodeGroupDefaults)
188-
if err != nil {
189-
klog.Errorf("Failed to get autoscaling options for node group %s: %v", nodeGroup.Id(), err)
190-
continue
191-
}
192-
if autoscalingOptions != nil && autoscalingOptions.AtomicScaling {
193-
klog.V(2).Infof("Considering node %s for atomic scale down", node.Name)
194-
nodesByGroup[nodeGroup] = append(nodesByGroup[nodeGroup], node)
195-
} else {
196-
klog.V(2).Infof("Considering node %s for standard scale down", node.Name)
197-
result = append(result, node)
198-
}
199-
}
200-
for nodeGroup, nodes := range nodesByGroup {
201-
ngSize, err := nodeGroup.TargetSize()
202-
if err != nil {
203-
klog.Errorf("Nodes from group %s will not scale down, failed to get target size: %s", nodeGroup.Id(), err)
204-
continue
205-
}
206-
if ngSize == len(nodes) {
207-
klog.V(2).Infof("Scheduling atomic scale down for all %v nodes from node group %s", len(nodes), nodeGroup.Id())
208-
result = append(result, nodes...)
209-
} else {
210-
klog.V(2).Infof("Skipping scale down for %v nodes from node group %s, all %v nodes have to be scaled down atomically", len(nodes), nodeGroup.Id(), ngSize)
211-
filteredOut = append(filteredOut, nodes...)
212-
}
213-
}
214-
return result, filteredOut
215-
}
216-
217174
func allNodes(s clustersnapshot.ClusterSnapshot) ([]*apiv1.Node, error) {
218175
nodeInfos, err := s.NodeInfos().List()
219176
if err != nil {

cluster-autoscaler/core/scaledown/planner/planner_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,6 @@ func TestUpdateClusterStatUnneededNodesLimit(t *testing.T) {
623623
}
624624

625625
func TestNodesToDelete(t *testing.T) {
626-
627626
testCases := []struct {
628627
name string
629628
nodes map[cloudprovider.NodeGroup][]simulator.NodeToBeRemoved
@@ -695,10 +694,11 @@ func TestNodesToDelete(t *testing.T) {
695694
buildRemovableNode("node-3", 1),
696695
},
697696
},
698-
wantEmpty: []*apiv1.Node{},
699-
wantDrain: []*apiv1.Node{
697+
wantEmpty: []*apiv1.Node{
700698
buildRemovableNode("node-1", 0).Node,
701699
buildRemovableNode("node-2", 0).Node,
700+
},
701+
wantDrain: []*apiv1.Node{
702702
buildRemovableNode("node-3", 1).Node,
703703
},
704704
},
@@ -743,14 +743,14 @@ func TestNodesToDelete(t *testing.T) {
743743
buildRemovableNode("node-10", 0).Node,
744744
buildRemovableNode("node-11", 0).Node,
745745
buildRemovableNode("node-12", 0).Node,
746+
buildRemovableNode("node-13", 0).Node,
746747
},
747748
wantDrain: []*apiv1.Node{
748749
buildRemovableNode("node-4", 0).Node,
749750
buildRemovableNode("node-5", 0).Node,
750751
buildRemovableNode("node-6", 0).Node,
751752
buildRemovableNode("node-8", 0).Node,
752753
buildRemovableNode("node-9", 0).Node,
753-
buildRemovableNode("node-13", 0).Node,
754754
buildRemovableNode("node-14", 0).Node,
755755
buildRemovableNode("node-15", 0).Node,
756756
},

cluster-autoscaler/processors/nodes/post_filtering_processor.go

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,23 @@ limitations under the License.
1717
package nodes
1818

1919
import (
20+
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
2021
"k8s.io/autoscaler/cluster-autoscaler/context"
2122
"k8s.io/autoscaler/cluster-autoscaler/simulator"
23+
klog "k8s.io/klog/v2"
2224
)
2325

2426
// PostFilteringScaleDownNodeProcessor selects first maxCount nodes (if possible) to be removed
2527
type PostFilteringScaleDownNodeProcessor struct {
2628
}
2729

2830
// GetNodesToRemove selects up to maxCount nodes for deletion, by selecting a first maxCount candidates
29-
func (n *PostFilteringScaleDownNodeProcessor) GetNodesToRemove(ctx *context.AutoscalingContext, candidates []simulator.NodeToBeRemoved, maxCount int) []simulator.NodeToBeRemoved {
31+
func (p *PostFilteringScaleDownNodeProcessor) GetNodesToRemove(ctx *context.AutoscalingContext, candidates []simulator.NodeToBeRemoved, maxCount int) []simulator.NodeToBeRemoved {
3032
end := len(candidates)
3133
if len(candidates) > maxCount {
3234
end = maxCount
3335
}
34-
return candidates[:end]
36+
return p.filterOutIncompleteAtomicNodeGroups(ctx, candidates[:end])
3537
}
3638

3739
// CleanUp is called at CA termination
@@ -42,3 +44,41 @@ func (n *PostFilteringScaleDownNodeProcessor) CleanUp() {
4244
func NewPostFilteringScaleDownNodeProcessor() *PostFilteringScaleDownNodeProcessor {
4345
return &PostFilteringScaleDownNodeProcessor{}
4446
}
47+
48+
func (p *PostFilteringScaleDownNodeProcessor) filterOutIncompleteAtomicNodeGroups(ctx *context.AutoscalingContext, nodes []simulator.NodeToBeRemoved) []simulator.NodeToBeRemoved {
49+
nodesByGroup := map[cloudprovider.NodeGroup][]simulator.NodeToBeRemoved{}
50+
result := []simulator.NodeToBeRemoved{}
51+
for _, node := range nodes {
52+
nodeGroup, err := ctx.CloudProvider.NodeGroupForNode(node.Node)
53+
if err != nil {
54+
klog.Errorf("Node %v will not scale down, failed to get node info: %s", node.Node.Name, err)
55+
continue
56+
}
57+
autoscalingOptions, err := nodeGroup.GetOptions(ctx.NodeGroupDefaults)
58+
if err != nil {
59+
klog.Errorf("Failed to get autoscaling options for node group %s: %v", nodeGroup.Id(), err)
60+
continue
61+
}
62+
if autoscalingOptions != nil && autoscalingOptions.AtomicScaling {
63+
klog.V(2).Infof("Considering node %s for atomic scale down", node.Node.Name)
64+
nodesByGroup[nodeGroup] = append(nodesByGroup[nodeGroup], node)
65+
} else {
66+
klog.V(2).Infof("Considering node %s for standard scale down", node.Node.Name)
67+
result = append(result, node)
68+
}
69+
}
70+
for nodeGroup, nodes := range nodesByGroup {
71+
ngSize, err := nodeGroup.TargetSize()
72+
if err != nil {
73+
klog.Errorf("Nodes from group %s will not scale down, failed to get target size: %s", nodeGroup.Id(), err)
74+
continue
75+
}
76+
if ngSize == len(nodes) {
77+
klog.V(2).Infof("Scheduling atomic scale down for all %v nodes from node group %s", len(nodes), nodeGroup.Id())
78+
result = append(result, nodes...)
79+
} else {
80+
klog.V(2).Infof("Skipping scale down for %v nodes from node group %s, all %v nodes have to be scaled down atomically", len(nodes), nodeGroup.Id(), ngSize)
81+
}
82+
}
83+
return result
84+
}

0 commit comments

Comments
 (0)