Skip to content

Commit dfc19d4

Browse files
amuraruclaude
andcommitted
fix(kraft): filter controller-only nodes from Cruise Control remove_broker
The add_broker and rebalance branches of the Cruise Control task controller already drop controller-only nodes before calling Cruise Control (CC has no knowledge of them in KRaft mode), but the remove_broker branch did not. It relied entirely on the upstream invariant that controller-only nodes never receive a GracefulDownscaleRequired state. If that invariant ever regressed, a controller-only broker id would be sent to CC's remove_broker unfiltered and error out / stall the operation. Apply util.FilterControllerOnlyNodes in the remove_broker branch too, so all three broker-id CC operations are symmetrically guarded, and only issue the CC request when the filtered id list is non-empty. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit f626ded)
1 parent 000f861 commit dfc19d4

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

‎controllers/cruisecontroltask_controller.go‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,30 @@ func (r *CruiseControlTaskReconciler) Reconcile(ctx context.Context, request ctr
177177
brokerIDs = append(brokerIDs, task.BrokerID)
178178
}
179179

180-
cruiseControlOpRef, err := r.removeBrokers(ctx, instance, operationTTLSecondsAfterFinished, brokerIDs)
181-
if err != nil {
182-
return requeueWithError(log, fmt.Sprintf("creating CruiseControlOperation for downscale has failed, brokerIDs: %s", brokerIDs), err)
180+
if instance.Spec.KRaftMode {
181+
// In KRaft mode, CC has no information about the controller-only nodes, so a remove_broker
182+
// request for one would fail in CC. Controller-only nodes are downscaled by deleting their
183+
// pod directly (see reconcileKafkaPodDelete) and never receive a GracefulDownscaleRequired
184+
// state, so this filter is defense-in-depth to keep the three broker-id CC operations
185+
// (add_broker, remove_broker, rebalance) symmetric.
186+
brokerIDs, err = util.FilterControllerOnlyNodes(brokerIDs, instance.Spec)
187+
if err != nil {
188+
return requeueWithError(log, fmt.Sprintf("failed to filter out controller-only nodes from the Kafka cluster, "+
189+
"clusterName: %s, clusterNamespace: %s", instance.GetName(), instance.GetNamespace()), err)
190+
}
183191
}
184192

185-
// map the CC broker removal operation with each broker status
186-
for _, task := range tasksAndStates.GetActiveTasksByOp(banzaiv1alpha1.OperationRemoveBroker) {
187-
task.SetCruiseControlOperationRef(cruiseControlOpRef)
188-
task.SetStateScheduled()
193+
if len(brokerIDs) != 0 {
194+
cruiseControlOpRef, err := r.removeBrokers(ctx, instance, operationTTLSecondsAfterFinished, brokerIDs)
195+
if err != nil {
196+
return requeueWithError(log, fmt.Sprintf("creating CruiseControlOperation for downscale has failed, brokerIDs: %s", brokerIDs), err)
197+
}
198+
199+
// map the CC broker removal operation with each broker status
200+
for _, task := range tasksAndStates.GetActiveTasksByOp(banzaiv1alpha1.OperationRemoveBroker) {
201+
task.SetCruiseControlOperationRef(cruiseControlOpRef)
202+
task.SetStateScheduled()
203+
}
189204
}
190205

191206
case tasksAndStates.NumActiveTasksByOp(banzaiv1alpha1.OperationRemoveDisks) > 0:

0 commit comments

Comments
 (0)