sigs.k8s.io/controller-runtime@v0.18.2/designs/use-selectors-at-cache.md (about) 1 # Filter cache ListWatch using selectors 2 3 ## Motivation 4 5 Controller-Runtime controllers use a cache to subscribe to events from 6 Kubernetes objects and to read those objects more efficiently by avoiding 7 to call out to the API. This cache is backed by Kubernetes informers. 8 9 The only way to filter this cache is by namespace and resource type. 10 In cases where a controller is only interested in a small subset of objects 11 (for example all pods on a node), this might end up not being efficient enough. 12 13 Requests to a client backed by a filtered cache for objects that do not match 14 the filter will never return anything, so we need to make sure that we properly 15 warn users to only use this when they are sure they know what they are doing. 16 17 This proposal sidesteps the issue of "How to we plug this into the cache-backed 18 client so that users get feedback when they request something that is 19 not matching the caches filter" by only implementing the filter logic in the 20 cache package. This allows advanced users to combine a filtered cache with the 21 already existing `NewCacheFunc` option in the manager and cluster package, 22 while simultaneously hiding it from newer users that might not be aware of the 23 implications and the associated foot-shoot potential. 24 25 The only alternative today to get a filtered cache with controller-runtime is 26 to build it out-of tree. Because such a cache would mostly copy the existing 27 cache and add just some options, this is not great for consumers. 28 29 This proposal is related to the following issue [2] 30 31 ## Proposal 32 33 Add a new selector code at `pkg/cache/internal/selector.go` with common structs 34 and helpers 35 36 ```golang 37 package internal 38 39 ... 40 41 // SelectorsByObject associate a runtime.Object to a field/label selector 42 type SelectorsByObject map[client.Object]Selector 43 44 // SelectorsByGVK associate a GroupVersionResource to a field/label selector 45 type SelectorsByGVK map[schema.GroupVersionKind]Selector 46 47 // Selector specify the label/field selector to fill in ListOptions 48 type Selector struct { 49 Label labels.Selector 50 Field fields.Selector 51 } 52 53 // ApplyToList fill in ListOptions LabelSelector and FieldSelector if needed 54 func (s Selector) ApplyToList(listOpts *metav1.ListOptions) { 55 ... 56 } 57 ``` 58 59 Add a type alias to `pkg/cache/cache.go` to internal 60 61 ```golang 62 type SelectorsByObject internal.SelectorsByObject 63 ``` 64 65 Extend `cache.Options` as follows: 66 67 ```golang 68 type Options struct { 69 Scheme *runtime.Scheme 70 Mapper meta.RESTMapper 71 Resync *time.Duration 72 Namespace string 73 SelectorsByObject SelectorsByObject 74 } 75 ``` 76 77 Add new builder function that will return a cache constructor using the passed 78 cache.Options, users can set SelectorsByObject there to filter out cache, it 79 will convert SelectorByObject to SelectorsByGVK 80 81 ```golang 82 func BuilderWithOptions(options cache.Options) NewCacheFunc { 83 ... 84 } 85 ``` 86 87 is passed to informer's ListWatch and add the filtering option: 88 89 ```golang 90 91 # At pkg/cache/internal/informers_map.go 92 93 ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { 94 ip.selectors[gvk].ApplyToList(&opts) 95 ... 96 ``` 97 98 Here is a PR with the implementatin at the `pkg/cache` part [3] 99 100 ## Example 101 102 User will override `NewCache` function to make clear that they know exactly the 103 implications of using a different cache than the default one 104 105 ```golang 106 ctrl.Options.NewCache = cache.BuilderWithOptions(cache.Options{ 107 SelectorsByObject: cache.SelectorsByObject{ 108 &corev1.Node{}: { 109 Field: fields.SelectorFromSet(fields.Set{"metadata.name": "node01"}), 110 } 111 &v1beta1.NodeNetworkState{}: { 112 Field: fields.SelectorFromSet(fields.Set{"metadata.name": "node01"}), 113 Label: labels.SelectorFromSet(labels.Set{"app": "kubernetes-nmstate})", 114 } 115 } 116 } 117 ) 118 ``` 119 120 [1] https://github.com/nmstate/kubernetes-nmstate/pull/687 121 [2] https://github.com/kubernetes-sigs/controller-runtime/issues/244 122 [3] https://github.com/kubernetes-sigs/controller-runtime/pull/1404