Skip to content

Commit 6682dd1

Browse files
Merge pull request #5058 from openshift-cherrypick-robot/cherry-pick-5015-to-release-4.19
[release-4.19] OCPBUGS-56263: scope MCD node listers to current node
2 parents 7cfebea + a172d19 commit 6682dd1

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

cmd/machine-config-daemon/start.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,18 @@ func runStartCmd(_ *cobra.Command, _ []string) {
153153
if startOpts.hypershiftDesiredConfigMap != "" {
154154
// This is a hypershift-mode daemon
155155
ctx := ctrlcommon.CreateControllerContext(ctx, cb)
156+
nodeScopedInformer, nodeScopedInformerStartFunc := ctrlcommon.NewScopedNodeInformerFromClientBuilder(cb, startOpts.nodeName)
156157
err := dn.HypershiftConnect(
157158
startOpts.nodeName,
158159
kubeClient,
159-
ctx.KubeInformerFactory.Core().V1().Nodes(),
160+
nodeScopedInformer,
160161
startOpts.hypershiftDesiredConfigMap,
161162
)
162163
if err != nil {
163164
ctrlcommon.WriteTerminationError(err)
164165
}
165166

167+
nodeScopedInformerStartFunc(stopCh)
166168
ctx.KubeInformerFactory.Start(stopCh)
167169
close(ctx.InformersStarted)
168170

@@ -177,14 +179,16 @@ func runStartCmd(_ *cobra.Command, _ []string) {
177179

178180
ctrlctx := ctrlcommon.CreateControllerContext(ctx, cb)
179181

182+
nodeScopedInformer, nodeScopedInformerStartFunc := ctrlcommon.NewScopedNodeInformerFromClientBuilder(cb, startOpts.nodeName)
183+
180184
// create the daemon instance. this also initializes kube client items
181185
// which need to come from the container and not the chroot.
182186
err = dn.ClusterConnect(
183187
startOpts.nodeName,
184188
kubeClient,
185189
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
186190
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigs(),
187-
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
191+
nodeScopedInformer,
188192
ctrlctx.InformerFactory.Machineconfiguration().V1().ControllerConfigs(),
189193
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
190194
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
@@ -202,6 +206,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
202206
ctrlctx.KubeNamespacedInformerFactory.Start(stopCh)
203207
ctrlctx.InformerFactory.Start(stopCh)
204208
ctrlctx.OperatorInformerFactory.Start(stopCh)
209+
nodeScopedInformerStartFunc(ctrlctx.Stop)
205210
close(ctrlctx.InformersStarted)
206211

207212
select {
@@ -226,7 +231,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
226231
criClient,
227232
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
228233
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
229-
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
234+
nodeScopedInformer,
230235
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
231236
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
232237
constants.DefaultCRIOSocketPath,

pkg/controller/common/controller_context.go

+32
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"k8s.io/apimachinery/pkg/labels"
2323
"k8s.io/apimachinery/pkg/runtime/schema"
2424
"k8s.io/client-go/informers"
25+
corev1informers "k8s.io/client-go/informers/core/v1"
26+
"k8s.io/client-go/kubernetes"
2527
"k8s.io/klog/v2"
2628
"k8s.io/utils/clock"
2729
)
@@ -162,3 +164,33 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
162164
RouteInformerFactory: routeSharedInformer,
163165
}
164166
}
167+
168+
// Creates a NodeInformer that is bound to a single node. This is for use by
169+
// the MCD to ensure that the MCD only receives watch events for the node that
170+
// it is running on as opposed to all cluster nodes. Doing this helps reduce
171+
// the load on the apiserver. Because the filters are applied to *all*
172+
// informers constructed by the informer factory, we want to ensure that this
173+
// factory is only used to construct a NodeInformer.
174+
//
175+
// Therefore, to ensure that this informer factory is only used for
176+
// constructing a NodeInformer with this specific filter, we only return the
177+
// instantiated NodeInformer instance and a start function.
178+
func NewScopedNodeInformer(kubeclient kubernetes.Interface, nodeName string) (corev1informers.NodeInformer, func(<-chan struct{})) {
179+
sif := informers.NewSharedInformerFactoryWithOptions(
180+
kubeclient,
181+
resyncPeriod()(),
182+
informers.WithTweakListOptions(func(opts *metav1.ListOptions) {
183+
opts.FieldSelector = fields.OneTermEqualSelector("metadata.name", nodeName).String()
184+
}),
185+
)
186+
187+
return sif.Core().V1().Nodes(), sif.Start
188+
}
189+
190+
// Creates a scoped node informer that is bound to a single node from a
191+
// clients.Builder instance. It sets the user-agent for the client to
192+
// node-scoped-informer before instantiating the node informer. Returns the
193+
// instantiated NodeInformer and a start function.
194+
func NewScopedNodeInformerFromClientBuilder(cb *clients.Builder, nodeName string) (corev1informers.NodeInformer, func(<-chan struct{})) {
195+
return NewScopedNodeInformer(cb.KubeClientOrDie("node-scoped-informer"), nodeName)
196+
}

pkg/daemon/writer.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88

99
"k8s.io/client-go/tools/cache"
1010

11-
"k8s.io/client-go/informers"
1211
"k8s.io/client-go/kubernetes"
1312
"k8s.io/client-go/rest"
1413
"k8s.io/client-go/tools/clientcmd"
@@ -86,10 +85,16 @@ func newNodeWriter(nodeName string, stopCh <-chan struct{}) (NodeWriter, error)
8685
}
8786

8887
klog.Infof("NodeWriter initialized with credentials from %s", nodeWriterKubeconfigPath)
89-
informer := informers.NewSharedInformerFactory(kubeClient, ctrlcommon.DefaultResyncPeriod()())
90-
nodeInformer := informer.Core().V1().Nodes()
91-
nodeLister := nodeInformer.Lister()
92-
nodeListerSynced := nodeInformer.Informer().HasSynced
88+
// This informer needs to use the a different service account than the rest
89+
// of the MCD, which is bound to the machine-config-daemon service account.
90+
// Consequently, it must use a different informer factory than the parent
91+
// informer factory. However, we can instantiate both that informer factory
92+
// and the node informer in the same way that we instantiate the MCD
93+
// informer.
94+
informer, startFunc := ctrlcommon.NewScopedNodeInformer(kubeClient, nodeName)
95+
nodeInformer := informer.Informer()
96+
nodeLister := informer.Lister()
97+
nodeListerSynced := nodeInformer.HasSynced
9398

9499
eventBroadcaster := record.NewBroadcaster()
95100
eventBroadcaster.StartLogging(klog.V(2).Infof)
@@ -105,12 +110,12 @@ func newNodeWriter(nodeName string, stopCh <-chan struct{}) (NodeWriter, error)
105110
kubeClient: kubeClient,
106111
}
107112

108-
nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
113+
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
109114
AddFunc: nw.handleNodeWriterEvent,
110115
UpdateFunc: func(_, newObj interface{}) { nw.handleNodeWriterEvent(newObj) },
111116
})
112117

113-
informer.Start(stopCh)
118+
startFunc(stopCh)
114119

115120
return nw, nil
116121
}

0 commit comments

Comments
 (0)