Skip to content

[release-4.19] OCPBUGS-56263: scope MCD node listers to current node #5058

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions cmd/machine-config-daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,18 @@ func runStartCmd(_ *cobra.Command, _ []string) {
if startOpts.hypershiftDesiredConfigMap != "" {
// This is a hypershift-mode daemon
ctx := ctrlcommon.CreateControllerContext(ctx, cb)
nodeScopedInformer, nodeScopedInformerStartFunc := ctrlcommon.NewScopedNodeInformerFromClientBuilder(cb, startOpts.nodeName)
err := dn.HypershiftConnect(
startOpts.nodeName,
kubeClient,
ctx.KubeInformerFactory.Core().V1().Nodes(),
nodeScopedInformer,
startOpts.hypershiftDesiredConfigMap,
)
if err != nil {
ctrlcommon.WriteTerminationError(err)
}

nodeScopedInformerStartFunc(stopCh)
ctx.KubeInformerFactory.Start(stopCh)
close(ctx.InformersStarted)

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

ctrlctx := ctrlcommon.CreateControllerContext(ctx, cb)

nodeScopedInformer, nodeScopedInformerStartFunc := ctrlcommon.NewScopedNodeInformerFromClientBuilder(cb, startOpts.nodeName)

// create the daemon instance. this also initializes kube client items
// which need to come from the container and not the chroot.
err = dn.ClusterConnect(
startOpts.nodeName,
kubeClient,
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigs(),
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
nodeScopedInformer,
ctrlctx.InformerFactory.Machineconfiguration().V1().ControllerConfigs(),
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
Expand All @@ -202,6 +206,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
ctrlctx.KubeNamespacedInformerFactory.Start(stopCh)
ctrlctx.InformerFactory.Start(stopCh)
ctrlctx.OperatorInformerFactory.Start(stopCh)
nodeScopedInformerStartFunc(ctrlctx.Stop)
close(ctrlctx.InformersStarted)

select {
Expand All @@ -226,7 +231,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
criClient,
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
nodeScopedInformer,
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
constants.DefaultCRIOSocketPath,
Expand Down
32 changes: 32 additions & 0 deletions pkg/controller/common/controller_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
corev1informers "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/utils/clock"
)
Expand Down Expand Up @@ -162,3 +164,33 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
RouteInformerFactory: routeSharedInformer,
}
}

// Creates a NodeInformer that is bound to a single node. This is for use by
// the MCD to ensure that the MCD only receives watch events for the node that
// it is running on as opposed to all cluster nodes. Doing this helps reduce
// the load on the apiserver. Because the filters are applied to *all*
// informers constructed by the informer factory, we want to ensure that this
// factory is only used to construct a NodeInformer.
//
// Therefore, to ensure that this informer factory is only used for
// constructing a NodeInformer with this specific filter, we only return the
// instantiated NodeInformer instance and a start function.
func NewScopedNodeInformer(kubeclient kubernetes.Interface, nodeName string) (corev1informers.NodeInformer, func(<-chan struct{})) {
sif := informers.NewSharedInformerFactoryWithOptions(
kubeclient,
resyncPeriod()(),
informers.WithTweakListOptions(func(opts *metav1.ListOptions) {
opts.FieldSelector = fields.OneTermEqualSelector("metadata.name", nodeName).String()
}),
)

return sif.Core().V1().Nodes(), sif.Start
}

// Creates a scoped node informer that is bound to a single node from a
// clients.Builder instance. It sets the user-agent for the client to
// node-scoped-informer before instantiating the node informer. Returns the
// instantiated NodeInformer and a start function.
func NewScopedNodeInformerFromClientBuilder(cb *clients.Builder, nodeName string) (corev1informers.NodeInformer, func(<-chan struct{})) {
return NewScopedNodeInformer(cb.KubeClientOrDie("node-scoped-informer"), nodeName)
}
19 changes: 12 additions & 7 deletions pkg/daemon/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

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

"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -86,10 +85,16 @@ func newNodeWriter(nodeName string, stopCh <-chan struct{}) (NodeWriter, error)
}

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

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

nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: nw.handleNodeWriterEvent,
UpdateFunc: func(_, newObj interface{}) { nw.handleNodeWriterEvent(newObj) },
})

informer.Start(stopCh)
startFunc(stopCh)

return nw, nil
}
Expand Down