github.com/cilium/cilium@v1.16.2/operator/watchers/pod.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package watchers 5 6 import ( 7 "context" 8 "fmt" 9 "sync" 10 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 "k8s.io/apimachinery/pkg/fields" 13 "k8s.io/client-go/tools/cache" 14 15 operatorOption "github.com/cilium/cilium/operator/option" 16 k8sClient "github.com/cilium/cilium/pkg/k8s/client" 17 "github.com/cilium/cilium/pkg/k8s/informer" 18 slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" 19 slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" 20 k8sUtils "github.com/cilium/cilium/pkg/k8s/utils" 21 ) 22 23 const PodNodeNameIndex = "pod-node" 24 25 var ( 26 // PodStore has a minimal copy of all pods running in the cluster. 27 // Warning: The pods stored in the cache are not intended to be used for Update 28 // operations in k8s as some of its fields are not populated. 29 PodStore cache.Store 30 31 // PodStoreSynced is closed once the PodStore is synced with k8s. 32 PodStoreSynced = make(chan struct{}) 33 34 // UnmanagedPodStore has a minimal copy of the unmanaged pods running 35 // in the cluster. 36 // Warning: The pods stored in the cache are not intended to be used for Update 37 // operations in k8s as some of its fields are not populated. 38 UnmanagedPodStore cache.Store 39 40 // UnmanagedPodStoreSynced is closed once the UnmanagedKubeDNSPodStore is synced 41 // with k8s. 42 UnmanagedPodStoreSynced = make(chan struct{}) 43 ) 44 45 // podNodeNameIndexFunc indexes pods by node name 46 func podNodeNameIndexFunc(obj interface{}) ([]string, error) { 47 pod := obj.(*slim_corev1.Pod) 48 if pod.Spec.NodeName != "" { 49 return []string{pod.Spec.NodeName}, nil 50 } 51 return []string{}, nil 52 } 53 54 func PodsInit(ctx context.Context, wg *sync.WaitGroup, clientset k8sClient.Clientset) { 55 var podInformer cache.Controller 56 PodStore = cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{ 57 PodNodeNameIndex: podNodeNameIndexFunc, 58 }) 59 podInformer = informer.NewInformerWithStore( 60 k8sUtils.ListerWatcherWithFields( 61 k8sUtils.ListerWatcherFromTyped[*slim_corev1.PodList](clientset.Slim().CoreV1().Pods("")), 62 fields.Everything()), 63 &slim_corev1.Pod{}, 64 0, 65 cache.ResourceEventHandlerFuncs{}, 66 transformToPod, 67 PodStore, 68 ) 69 wg.Add(1) 70 go func() { 71 defer wg.Done() 72 podInformer.Run(ctx.Done()) 73 }() 74 75 cache.WaitForCacheSync(ctx.Done(), podInformer.HasSynced) 76 } 77 78 // transformToPod stores a minimal version of the pod as it is only intended 79 // for it to check if a pod is running in the cluster or not. The stored pod 80 // should not be used to update an existing pod in the kubernetes cluster. 81 // If the given obj can't be cast into either Pod nor DeletedFinalStateUnknown, 82 // an error is returned. 83 func transformToPod(obj interface{}) (interface{}, error) { 84 switch concreteObj := obj.(type) { 85 case *slim_corev1.Pod: 86 p := &slim_corev1.Pod{ 87 TypeMeta: concreteObj.TypeMeta, 88 ObjectMeta: slim_metav1.ObjectMeta{ 89 Name: concreteObj.Name, 90 Namespace: concreteObj.Namespace, 91 ResourceVersion: concreteObj.ResourceVersion, 92 }, 93 Spec: slim_corev1.PodSpec{ 94 NodeName: concreteObj.Spec.NodeName, 95 }, 96 Status: slim_corev1.PodStatus{ 97 Phase: concreteObj.Status.Phase, 98 }, 99 } 100 *concreteObj = slim_corev1.Pod{} 101 return p, nil 102 case cache.DeletedFinalStateUnknown: 103 pod, ok := concreteObj.Obj.(*slim_corev1.Pod) 104 if !ok { 105 return nil, fmt.Errorf("unknown object type %T", concreteObj.Obj) 106 } 107 dfsu := cache.DeletedFinalStateUnknown{ 108 Key: concreteObj.Key, 109 Obj: &slim_corev1.Pod{ 110 TypeMeta: pod.TypeMeta, 111 ObjectMeta: slim_metav1.ObjectMeta{ 112 Name: pod.Name, 113 Namespace: pod.Namespace, 114 ResourceVersion: pod.ResourceVersion, 115 }, 116 Spec: slim_corev1.PodSpec{ 117 NodeName: pod.Spec.NodeName, 118 }, 119 Status: slim_corev1.PodStatus{ 120 Phase: pod.Status.Phase, 121 }, 122 }, 123 } 124 // Small GC optimization 125 *pod = slim_corev1.Pod{} 126 return dfsu, nil 127 default: 128 return nil, fmt.Errorf("unknown object type %T", concreteObj) 129 } 130 } 131 132 func UnmanagedPodsInit(ctx context.Context, wg *sync.WaitGroup, clientset k8sClient.Clientset) { 133 var unmanagedPodInformer cache.Controller 134 UnmanagedPodStore, unmanagedPodInformer = informer.NewInformer( 135 k8sUtils.ListerWatcherWithModifier( 136 k8sUtils.ListerWatcherFromTyped[*slim_corev1.PodList](clientset.Slim().CoreV1().Pods("")), 137 func(options *metav1.ListOptions) { 138 options.FieldSelector = "status.phase=Running" 139 options.LabelSelector = operatorOption.Config.PodRestartSelector 140 }), 141 &slim_corev1.Pod{}, 142 0, 143 cache.ResourceEventHandlerFuncs{}, 144 TransformToUnmanagedPod, 145 ) 146 wg.Add(1) 147 go func() { 148 defer wg.Done() 149 unmanagedPodInformer.Run(ctx.Done()) 150 }() 151 152 cache.WaitForCacheSync(ctx.Done(), unmanagedPodInformer.HasSynced) 153 } 154 155 func TransformToUnmanagedPod(obj interface{}) (interface{}, error) { 156 switch concreteObj := obj.(type) { 157 case *slim_corev1.Pod: 158 p := &slim_corev1.Pod{ 159 TypeMeta: concreteObj.TypeMeta, 160 ObjectMeta: slim_metav1.ObjectMeta{ 161 Name: concreteObj.Name, 162 Namespace: concreteObj.Namespace, 163 ResourceVersion: concreteObj.ResourceVersion, 164 }, 165 Spec: slim_corev1.PodSpec{ 166 HostNetwork: concreteObj.Spec.HostNetwork, 167 }, 168 Status: slim_corev1.PodStatus{ 169 StartTime: concreteObj.Status.StartTime, 170 }, 171 } 172 *concreteObj = slim_corev1.Pod{} 173 return p, nil 174 case cache.DeletedFinalStateUnknown: 175 pod, ok := concreteObj.Obj.(*slim_corev1.Pod) 176 if !ok { 177 return nil, fmt.Errorf("unknown object type %T", concreteObj.Obj) 178 } 179 dfsu := cache.DeletedFinalStateUnknown{ 180 Key: concreteObj.Key, 181 Obj: &slim_corev1.Pod{ 182 TypeMeta: pod.TypeMeta, 183 ObjectMeta: slim_metav1.ObjectMeta{ 184 Name: pod.Name, 185 Namespace: pod.Namespace, 186 ResourceVersion: pod.ResourceVersion, 187 }, 188 Spec: slim_corev1.PodSpec{ 189 HostNetwork: pod.Spec.HostNetwork, 190 }, 191 Status: slim_corev1.PodStatus{ 192 StartTime: pod.Status.StartTime, 193 }, 194 }, 195 } 196 // Small GC optimization 197 *pod = slim_corev1.Pod{} 198 return dfsu, nil 199 default: 200 return nil, fmt.Errorf("unknown object type %T", concreteObj) 201 } 202 }