diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index 9da6c6a1048..2dc46a46ae7 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -86,6 +86,13 @@ const ( // PodNodeNameKeyIndex is the name of the index used by PodInformer to index pods by their node name. PodNodeNameKeyIndex = "spec.nodeName" + + // OrphanPodIndexKey is used to index all Orphan pods to this key + OrphanPodIndexKey = "_ORPHAN_POD" + + // podControllerUIDIndex is the name for the Pod store's index function, + // which is to index by pods's controllerUID. + PodControllerUIDIndex = "podControllerUID" ) var UpdateTaintBackoff = wait.Backoff{ @@ -1076,6 +1083,30 @@ func AddPodNodeNameIndexer(podInformer cache.SharedIndexInformer) error { }) } +// AddPodControllerUIDIndexer adds an indexer for Pod's controllerRef.UID to the given PodInformer. +// This indexer is used to efficiently look up pods by their ControllerRef.UID +func AddPodControllerUIDIndexer(podInformer cache.SharedIndexInformer) error { + if _, exists := podInformer.GetIndexer().GetIndexers()[PodControllerUIDIndex]; exists { + // indexer already exists, do nothing + return nil + } + return podInformer.AddIndexers(cache.Indexers{ + PodControllerUIDIndex: func(obj interface{}) ([]string, error) { + pod, ok := obj.(*v1.Pod) + if !ok { + return nil, nil + } + // Get the ControllerRef of the Pod to check if it's managed by a controller + if ref := metav1.GetControllerOf(pod); ref != nil { + return []string{string(ref.UID)}, nil + } + // If the Pod has no controller (i.e., it's orphaned), index it with the OrphanPodIndexKey + // This helps identify orphan pods for reconciliation and adoption by controllers + return []string{OrphanPodIndexKey}, nil + }, + }) +} + // PodKey returns a key unique to the given pod within a cluster. // It's used so we consistently use the same key scheme in this module. // It does exactly what cache.MetaNamespaceKeyFunc would have done diff --git a/pkg/controller/daemon/daemon_controller.go b/pkg/controller/daemon/daemon_controller.go index ca2c5d6ee6e..4db3a5933d9 100644 --- a/pkg/controller/daemon/daemon_controller.go +++ b/pkg/controller/daemon/daemon_controller.go @@ -113,7 +113,7 @@ type DaemonSetsController struct { historyStoreSynced cache.InformerSynced // podLister get list/get pods from the shared informers's store podLister corelisters.PodLister - // podIndexer allows looking up pods by node name. + // podIndexer allows looking up pods by node name or by ControllerRef UID podIndexer cache.Indexer // podStoreSynced returns true if the pod store has been synced at least once. // Added as a member to the struct to allow injection for testing. @@ -217,6 +217,7 @@ func NewDaemonSetsController( dsc.podLister = podInformer.Lister() dsc.podStoreSynced = podInformer.Informer().HasSynced controller.AddPodNodeNameIndexer(podInformer.Informer()) + controller.AddPodControllerUIDIndexer(podInformer.Informer()) dsc.podIndexer = podInformer.Informer().GetIndexer() nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -688,6 +689,30 @@ func (dsc *DaemonSetsController) updateNode(logger klog.Logger, old, cur interfa dsc.nodeUpdateQueue.Add(curNode.Name) } +// getPodsFromCache returns the Pods that a given DS should manage. +func (dsc *DaemonSetsController) getDaemonPodsFromCache(ds *apps.DaemonSet) ([]*v1.Pod, error) { + // Iterate over two keys: + // The UID of the Daemonset, which identifies Pods that are controlled by the Daemonset. + // The OrphanPodIndexKey, which helps identify orphaned Pods that are not currently managed by any controller, + // but may be adopted later on if they have matching labels with the Daemonset. + podsForDS := []*v1.Pod{} + for _, key := range []string{string(ds.UID), controller.OrphanPodIndexKey} { + podObjs, err := dsc.podIndexer.ByIndex(controller.PodControllerUIDIndex, key) + if err != nil { + return nil, err + } + for _, obj := range podObjs { + pod, ok := obj.(*v1.Pod) + if !ok { + utilruntime.HandleError(fmt.Errorf("unexpected object type in pod indexer: %v", obj)) + continue + } + podsForDS = append(podsForDS, pod) + } + } + return podsForDS, nil +} + // getDaemonPods returns daemon pods owned by the given ds. // This also reconciles ControllerRef by adopting/orphaning. // Note that returned Pods are pointers to objects in the cache. @@ -697,10 +722,8 @@ func (dsc *DaemonSetsController) getDaemonPods(ctx context.Context, ds *apps.Dae if err != nil { return nil, err } - - // List all pods to include those that don't match the selector anymore but - // have a ControllerRef pointing to this controller. - pods, err := dsc.podLister.Pods(ds.Namespace).List(labels.Everything()) + // List all pods indexed to DS UID and Orphan pods + pods, err := dsc.getDaemonPodsFromCache(ds) if err != nil { return nil, err }