@@ -34,7 +34,10 @@ import (
3434 "k8s.io/apimachinery/pkg/types"
3535 "k8s.io/client-go/informers"
3636 "k8s.io/client-go/kubernetes"
37+ "k8s.io/client-go/kubernetes/scheme"
38+ typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
3739 "k8s.io/client-go/tools/cache"
40+ "k8s.io/client-go/tools/record"
3841 "k8s.io/utils/ptr"
3942
4043 "github.com/nvidia/nvsentinel/data-models/pkg/model"
@@ -44,20 +47,19 @@ import (
4447)
4548
4649const (
47- NodeIndex = "node"
48- NamespaceNodeIndex = "namespace-node"
49- NodeEventReasonIndex = "node-event-reason"
50+ NodeIndex = "node"
51+ NamespaceNodeIndex = "namespace-node"
5052)
5153
5254type Informers struct {
5355 podInformer cache.SharedIndexInformer
54- eventInformer cache.SharedIndexInformer
5556 nodeInformer cache.SharedIndexInformer
57+ eventBroadcaster record.EventBroadcaster
58+ eventRecorder record.EventRecorder
5659 clientset kubernetes.Interface
5760 notReadyTimeoutMinutes * int
5861 drainGPUPods bool
5962 dryRunMode []string
60- namespace string
6163}
6264
6365func NewInformers (clientset kubernetes.Interface , resyncPeriod time.Duration ,
@@ -87,41 +89,30 @@ func NewInformers(clientset kubernetes.Interface, resyncPeriod time.Duration,
8789 return nil , fmt .Errorf ("failed to add indexer: %w" , err )
8890 }
8991
90- eventInformerFactory := informers .NewSharedInformerFactoryWithOptions (
91- clientset ,
92- resyncPeriod ,
93- informers .WithNamespace (metav1 .NamespaceDefault ),
94- )
95-
96- eventInformer := eventInformerFactory .Core ().V1 ().Events ().Informer ()
97-
98- err = eventInformer .GetIndexer ().AddIndexers (
99- cache.Indexers {
100- NodeEventReasonIndex : NodeEventReasonIndexFunc ,
101- })
102- if err != nil {
103- return nil , fmt .Errorf ("failed to add event indexer: %w" , err )
104- }
105-
10692 nodeInformer := informerFactory .Core ().V1 ().Nodes ().Informer ()
10793 if err := nodeInformer .SetTransform (nodeTransform ); err != nil {
10894 return nil , fmt .Errorf ("failed to set node informer transform: %w" , err )
10995 }
11096
97+ eventBroadcaster := record .NewBroadcaster ()
98+
11199 dryRunMode := []string {}
112100 if dryRun {
113101 dryRunMode = []string {metav1 .DryRunAll }
114102 }
115103
116104 return & Informers {
117- clientset : clientset ,
118- podInformer : podInformer ,
119- eventInformer : eventInformer ,
120- nodeInformer : nodeInformer ,
105+ clientset : clientset ,
106+ podInformer : podInformer ,
107+ nodeInformer : nodeInformer ,
108+ eventBroadcaster : eventBroadcaster ,
109+ eventRecorder : eventBroadcaster .NewRecorder (
110+ scheme .Scheme ,
111+ v1.EventSource {Component : "nvsentinel-node-drainer" },
112+ ),
121113 notReadyTimeoutMinutes : notReadyTimeoutMinutes ,
122114 drainGPUPods : drainGPUPods ,
123115 dryRunMode : dryRunMode ,
124- namespace : metav1 .NamespaceDefault ,
125116 }, nil
126117}
127118
@@ -273,7 +264,7 @@ func isDaemonSetOwned(ownerReferences []metav1.OwnerReference) bool {
273264}
274265
275266func (i * Informers ) HasSynced () bool {
276- return i .podInformer .HasSynced () && i .eventInformer . HasSynced () && i . nodeInformer .HasSynced ()
267+ return i .podInformer .HasSynced () && i .nodeInformer .HasSynced ()
277268}
278269
279270func NodeIndexFunc (obj any ) ([]string , error ) {
@@ -304,25 +295,17 @@ func NamespaceNodeIndexFunc(obj any) ([]string, error) {
304295 return []string {compositeKey }, nil
305296}
306297
307- func NodeEventReasonIndexFunc (obj any ) ([]string , error ) {
308- event , ok := obj .(* v1.Event )
309- if ! ok {
310- return []string {}, nil
311- }
312-
313- if event .InvolvedObject .Kind != "Node" {
314- return []string {}, nil
315- }
316-
317- compositeKey := fmt .Sprintf ("%s/%s" , event .InvolvedObject .Name , event .Reason )
318-
319- return []string {compositeKey }, nil
320- }
321-
322298func (i * Informers ) Run (ctx context.Context ) error {
299+ i .eventBroadcaster .StartRecordingToSink (& typedcorev1.EventSinkImpl {
300+ Interface : i .clientset .CoreV1 ().Events (metav1 .NamespaceDefault ),
301+ })
302+
323303 go i .podInformer .Run (ctx .Done ())
324- go i .eventInformer .Run (ctx .Done ())
325304 go i .nodeInformer .Run (ctx .Done ())
305+ go func () {
306+ <- ctx .Done ()
307+ i .eventBroadcaster .Shutdown ()
308+ }()
326309
327310 if ok := cache .WaitForCacheSync (ctx .Done (),
328311 i .HasSynced ); ! ok {
@@ -714,71 +697,13 @@ func (i *Informers) sendEvictionRequestForPod(ctx context.Context, namespace str
714697 return nil
715698}
716699
717- func (i * Informers ) UpdateNodeEvent (ctx context.Context , nodeName string , reason string , message string ) error {
718- compositeKey := fmt .Sprintf ("%s/%s" , nodeName , reason )
719-
720- cachedEvents , err := i .eventInformer .GetIndexer ().ByIndex (NodeEventReasonIndex , compositeKey )
721- if err != nil {
722- slog .ErrorContext (ctx , "Failed to query event cache" , "error" , err )
723- return fmt .Errorf ("error querying event cache: %w" , err )
724- }
725-
726- now := metav1 .NewTime (time .Now ())
727- eventsClient := i .clientset .CoreV1 ().Events (i .namespace )
728-
729- for _ , obj := range cachedEvents {
730- existingEvent , ok := obj .(* v1.Event )
731- if ! ok {
732- continue
733- }
734-
735- if existingEvent .Message == message {
736- eventCopy := existingEvent .DeepCopy ()
737- eventCopy .Count ++
738- eventCopy .LastTimestamp = now
739-
740- _ , err = eventsClient .Update (ctx , eventCopy , metav1.UpdateOptions {})
741- if err != nil {
742- slog .ErrorContext (ctx , "Failed to update event occurrence count" , "error" , err )
743- return fmt .Errorf ("error in updating event occurrence count: %w" , err )
744- }
745-
746- return nil
747- }
748- }
749-
750- // Get node from informer cache to retrieve its UID for proper event association
700+ func (i * Informers ) UpdateNodeEvent (_ context.Context , nodeName string , reason string , message string ) error {
751701 node , err := i .GetNode (nodeName )
752702 if err != nil {
753703 return fmt .Errorf ("error getting node from cache %s: %w" , nodeName , err )
754704 }
755705
756- newEvent := & v1.Event {
757- ObjectMeta : metav1.ObjectMeta {
758- GenerateName : nodeName + "-" ,
759- Namespace : i .namespace ,
760- },
761- InvolvedObject : v1.ObjectReference {
762- Kind : "Node" ,
763- Name : nodeName ,
764- UID : node .UID ,
765- APIVersion : "v1" ,
766- },
767- Reason : reason ,
768- Message : message ,
769- Type : "NodeDraining" ,
770- Source : v1.EventSource {Component : "nvsentinel-node-drainer" },
771- FirstTimestamp : now ,
772- LastTimestamp : now ,
773- Count : 1 ,
774- }
775-
776- _ , err = eventsClient .Create (ctx , newEvent , metav1.CreateOptions {})
777- if err != nil {
778- slog .ErrorContext (ctx , "Failed to create event" , "error" , err , "node" , nodeName , "reason" , reason )
779- return fmt .Errorf ("error in creating event: %w" , err )
780- }
781-
706+ i .eventRecorder .Event (node , v1 .EventTypeNormal , reason , message )
782707 return nil
783708}
784709
0 commit comments