fix(controller): pre-filter BindDefinitions by RoleBindings in namespace event fan-out#276
Open
MaxRink wants to merge 4 commits intotelekom:mainfrom
Open
fix(controller): pre-filter BindDefinitions by RoleBindings in namespace event fan-out#276MaxRink wants to merge 4 commits intotelekom:mainfrom
MaxRink wants to merge 4 commits intotelekom:mainfrom
Conversation
…ace fan-out namespaceToBindDefinitionRequests listed ALL BindDefinitions on every Namespace event and ran in-memory selector matching for each, O(N) work where N is total BindDefinitions. BindDefinitions with only ClusterRoleBindings were fetched only to be skipped inside the loop. Add BindDefinitionHasRoleBindingsField field index to pkg/indexer and use client.MatchingFields to restrict the List to only BindDefinitions with at least one RoleBinding, eliminating cluster-only BDs from the fan-out scan.
There was a problem hiding this comment.
Pull request overview
This PR optimizes namespace event fan-out in the BindDefinition controller by using a controller-runtime cache field index to pre-filter BindDefinitions that can actually be affected by namespace changes (i.e., those with namespace-scoped roleBindings).
Changes:
- Add a new cache field index (
BindDefinitionHasRoleBindingsField) to efficiently identify BindDefinitions with at least onespec.roleBindingsentry. - Update
namespaceToBindDefinitionRequeststoListBindDefinitions usingclient.MatchingFieldsagainst the new index, avoiding full scans. - Remove the now-dead per-item “cluster-only” skip branch inside the in-memory filtering loop.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
pkg/indexer/indexer.go |
Adds and registers the new BindDefinition “has roleBindings” field index + extractor function. |
internal/controller/authorization/binddefinition_controller.go |
Switches namespace fan-out listing to use the new field index, reducing per-event work. |
Comments suppressed due to low confidence (1)
internal/controller/authorization/binddefinition_controller.go:203
namespaceToBindDefinitionRequestsnow usesclient.MatchingFieldswithindexer.BindDefinitionHasRoleBindingsField. The controller-runtime fake client requires the corresponding index to be registered viafake.NewClientBuilder().WithIndex(...); otherwiseListreturns an error and this mapper returns no requests. The existing unit tests for this function build a fake client without this index, so they will start failing unless updated to registerindexer.BindDefinitionHasRoleBindingsFuncforauthorizationv1alpha1.BindDefinition{}.
// List only BindDefinitions with at least one RoleBinding — cluster-only
// BindDefinitions (no RoleBindings) never need reconciliation on namespace
// events because they produce no namespace-scoped RBAC objects.
bindDefList := &authorizationv1alpha1.BindDefinitionList{}
err := r.client.List(ctx, bindDefList,
client.MatchingFields{indexer.BindDefinitionHasRoleBindingsField: indexer.BindDefinitionHasRoleBindingsTrue},
)
if err != nil {
logger.Error(err, "failed to list BindDefinition resources", "namespace", namespace.Name)
return nil
}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
namespaceToBindDefinitionRequestslisted all BindDefinitions on every Namespace event, then performed in-memory selector matching to skip cluster-only ones. This meant O(N) cache reads and filter work for every namespace create/update/delete, where N is the total number of BindDefinitions in the cluster — including those with onlyclusterRoleBindingsthat can never be triggered by a namespace event.Root Cause
The
client.Listcall had no field selector, so the cache returned every BindDefinition regardless of whether it had anyroleBindings. The in-loop checklen(bindDef.Spec.RoleBindings) == 0was the only guard, applied after the full list was materialised.Fix
BindDefinitionHasRoleBindingsField = ".spec.hasRoleBindings"field index topkg/indexer(constants, extractor funcBindDefinitionHasRoleBindingsFunc, andSetupIndexesregistration).client.MatchingFields{indexer.BindDefinitionHasRoleBindingsField: indexer.BindDefinitionHasRoleBindingsTrue}on theListcall so the controller-runtime cache index is used instead of a full scan.len(bindDef.Spec.RoleBindings) == 0branch from the in-loop filter.The index lookup is in-process O(1) against the informer cache — no API server calls.
Impact
roleBindings— they are still enqueued exactly as before.pkg/indexerindex is registered alongside the existingBindDefinitionTargetNameFieldandWebhookAuthorizerHasNamespaceSelectorFieldindexes — same registration pattern.Notes
namespace_validating_webhook.go).BindDefinitionHasRoleBindingsFieldtopkg/indexer/indexer.go— they will conflict on merge. Merge fix(webhook): pre-filter BindDefinitions by RoleBindings via field index #275 first and rebase this branch if needed.