✨ fix(boxcutter): cache Secrets only in olmv1-system namespace to ensure better performance#2609
✨ fix(boxcutter): cache Secrets only in olmv1-system namespace to ensure better performance#2609camilamacedo86 wants to merge 1 commit intooperator-framework:mainfrom
Conversation
✅ Deploy Preview for olmv1 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
This PR switches ClusterObjectSet Secret lookups from the cached controller-runtime client to the uncached API reader to avoid creating a cluster-wide Secret informer (reducing memory/network/cache-sync overhead on large clusters).
Changes:
- Add an
APIReaderfield toClusterObjectSetReconciler. - Update
resolveObjectRefto read Secrets viaAPIReader.Getinstead ofClient.Get. - Wire
mgr.GetAPIReader()incmd/operator-controller/main.goand update unit tests accordingly.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/operator-controller/controllers/clusterobjectset_controller.go | Introduces APIReader and uses it for Secret retrieval in resolveObjectRef. |
| cmd/operator-controller/main.go | Wires APIReader from the manager into the reconciler. |
| internal/operator-controller/controllers/resolve_ref_test.go | Updates tests to set APIReader on the reconciler. |
| internal/operator-controller/controllers/clusterobjectset_controller_test.go | Updates controller tests to set APIReader. |
| internal/operator-controller/controllers/clusterobjectset_controller_internal_test.go | Updates internal tests to set APIReader. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
internal/operator-controller/controllers/clusterobjectset_controller.go
Outdated
Show resolved
Hide resolved
pedjak
left a comment
There was a problem hiding this comment.
Given that we have switched to secret-based approach for all bundles, this is going to add at least one more API call per reconcile round. If this is really needed, I would still suggest to use cache-based client, but either:
- disable caching of secrets:
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
Client: client.Options{
Cache: &client.CacheOptions{
DisableFor: []client.Object{
&corev1.Secret{},
},
},
},
})- or, restrict caching for only olmv1-system namespace
I would prefer the later because it does not add additional API calls for most of bundles.
927f5d2 to
8427453
Compare
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Configure cache to watch Secrets exclusively in olmv1-system, avoiding a cluster-wide Secret informer while maintaining performance for bundle Secret lookups via the cached client
8427453 to
d4523d9
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2609 +/- ##
===========================================
+ Coverage 53.50% 66.97% +13.47%
===========================================
Files 139 139
Lines 9872 9878 +6
===========================================
+ Hits 5282 6616 +1334
+ Misses 4210 2773 -1437
- Partials 380 489 +109
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| // Ensure bundle Secrets in the configured systemNamespace are cached without enabling a cluster-wide Secret informer. | ||
| // Bundle Secrets are created in cfg.systemNamespace by SecretPacker. | ||
| if secretCache, ok := cacheOptions.ByObject[&corev1.Secret{}]; ok { | ||
| if secretCache.Namespaces == nil { | ||
| secretCache.Namespaces = make(map[string]crcache.Config) | ||
| } | ||
| if _, exists := secretCache.Namespaces[cfg.systemNamespace]; !exists { | ||
| secretCache.Namespaces[cfg.systemNamespace] = crcache.Config{} | ||
| } | ||
| cacheOptions.ByObject[&corev1.Secret{}] = secretCache | ||
| } |
There was a problem hiding this comment.
We already cache everything in the system namespace, don't we? See lines 259-261.
| cfg.systemNamespace: {LabelSelector: k8slabels.Everything()}, | ||
| }, | ||
| DefaultLabelSelector: k8slabels.Nothing(), | ||
| // Memory optimization: strip managed fields and large annotations from cached objects |
There was a problem hiding this comment.
Aside: I don't think we strip managed fields anymore do we? That would break our SSA clients (I think?)
There was a problem hiding this comment.
Comment done by Claude:
A few observations on this change:
The map lookup is always false — this code is unreachable
cacheOptions.ByObject has type map[client.Object]cache.ByObject, where client.Object is an interface. Go compares interface map keys by (dynamic type, dynamic value). Since the dynamic type here is *corev1.Secret (a pointer), Go compares pointer addresses. The &corev1.Secret{} allocated on line 286 is a different pointer than the one used as key in SetupPullSecretCache (pullsecretcache.go:37), so the lookup never matches and ok is always false.
The entire block is dead code.
Even if it worked, it would be redundant
DefaultNamespaces(lines 258-260) already includescfg.systemNamespacewithLabelSelector: labels.Everything(), so everything in that namespace (including Secrets) is already cached.SetupPullSecretCachealready configures Secret caching scoped tosaKey.Namespace, which iscfg.systemNamespace(the operator's own SA namespace).
There is no cluster-wide Secret informer to prevent — the existing configuration already scopes it.
Configures the controller manager cache to watch Secrets only in the
olmv1-systemnamespace, preventing a cluster-wide Secret informer while maintaining good performance for bundle Secret reads.Motivation
Inspired by discussion in:
openshift/operator-framework-operator-controller#687 (comment)