k8s.io/kubernetes@v1.29.3/pkg/kubelet/pod/pod_manager.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 //go:generate mockgen -destination=testing/mock_manager.go -package=testing -build_flags=-mod=mod . Manager 18 package pod 19 20 import ( 21 "sync" 22 23 v1 "k8s.io/api/core/v1" 24 "k8s.io/apimachinery/pkg/types" 25 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" 26 "k8s.io/kubernetes/pkg/kubelet/metrics" 27 kubetypes "k8s.io/kubernetes/pkg/kubelet/types" 28 ) 29 30 // Manager stores and manages access to pods, maintaining the mappings 31 // between static pods and mirror pods. 32 // 33 // The kubelet discovers pod updates from 3 sources: file, http, and 34 // apiserver. Pods from non-apiserver sources are called static pods, and API 35 // server is not aware of the existence of static pods. In order to monitor 36 // the status of such pods, the kubelet creates a mirror pod for each static 37 // pod via the API server. 38 // 39 // A mirror pod has the same pod full name (name and namespace) as its static 40 // counterpart (albeit different metadata such as UID, etc). By leveraging the 41 // fact that the kubelet reports the pod status using the pod full name, the 42 // status of the mirror pod always reflects the actual status of the static 43 // pod. When a static pod gets deleted, the associated orphaned mirror pod 44 // will also be removed. 45 type Manager interface { 46 // GetPodByFullName returns the (non-mirror) pod that matches full name, as well as 47 // whether the pod was found. 48 GetPodByFullName(podFullName string) (*v1.Pod, bool) 49 // GetPodByName provides the (non-mirror) pod that matches namespace and 50 // name, as well as whether the pod was found. 51 GetPodByName(namespace, name string) (*v1.Pod, bool) 52 // GetPodByUID provides the (non-mirror) pod that matches pod UID, as well as 53 // whether the pod is found. 54 GetPodByUID(types.UID) (*v1.Pod, bool) 55 // GetPodByMirrorPod returns the static pod for the given mirror pod and 56 // whether it was known to the pod manager. 57 GetPodByMirrorPod(*v1.Pod) (*v1.Pod, bool) 58 // GetMirrorPodByPod returns the mirror pod for the given static pod and 59 // whether it was known to the pod manager. 60 GetMirrorPodByPod(*v1.Pod) (*v1.Pod, bool) 61 // GetPodAndMirrorPod returns the complement for a pod - if a pod was provided 62 // and a mirror pod can be found, return it. If a mirror pod is provided and 63 // the pod can be found, return it and true for wasMirror. 64 GetPodAndMirrorPod(*v1.Pod) (pod, mirrorPod *v1.Pod, wasMirror bool) 65 66 // GetPods returns the regular pods bound to the kubelet and their spec. 67 GetPods() []*v1.Pod 68 69 // GetPodsAndMirrorPods returns the set of pods, the set of mirror pods, and 70 // the pod fullnames of any orphaned mirror pods. 71 GetPodsAndMirrorPods() (allPods []*v1.Pod, allMirrorPods []*v1.Pod, orphanedMirrorPodFullnames []string) 72 73 // SetPods replaces the internal pods with the new pods. 74 // It is currently only used for testing. 75 SetPods(pods []*v1.Pod) 76 // AddPod adds the given pod to the manager. 77 AddPod(pod *v1.Pod) 78 // UpdatePod updates the given pod in the manager. 79 UpdatePod(pod *v1.Pod) 80 // RemovePod deletes the given pod from the manager. For mirror pods, 81 // this means deleting the mappings related to mirror pods. For non- 82 // mirror pods, this means deleting from indexes for all non-mirror pods. 83 RemovePod(pod *v1.Pod) 84 85 // TranslatePodUID returns the actual UID of a pod. If the UID belongs to 86 // a mirror pod, returns the UID of its static pod. Otherwise, returns the 87 // original UID. 88 // 89 // All public-facing functions should perform this translation for UIDs 90 // because user may provide a mirror pod UID, which is not recognized by 91 // internal Kubelet functions. 92 TranslatePodUID(uid types.UID) kubetypes.ResolvedPodUID 93 // GetUIDTranslations returns the mappings of static pod UIDs to mirror pod 94 // UIDs and mirror pod UIDs to static pod UIDs. 95 GetUIDTranslations() (podToMirror map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID, mirrorToPod map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID) 96 } 97 98 // basicManager is a functional Manager. 99 // 100 // All fields in basicManager are read-only and are updated calling SetPods, 101 // AddPod, UpdatePod, or RemovePod. 102 type basicManager struct { 103 // Protects all internal maps. 104 lock sync.RWMutex 105 106 // Regular pods indexed by UID. 107 podByUID map[kubetypes.ResolvedPodUID]*v1.Pod 108 // Mirror pods indexed by UID. 109 mirrorPodByUID map[kubetypes.MirrorPodUID]*v1.Pod 110 111 // Pods indexed by full name for easy access. 112 podByFullName map[string]*v1.Pod 113 mirrorPodByFullName map[string]*v1.Pod 114 115 // Mirror pod UID to pod UID map. 116 translationByUID map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID 117 } 118 119 // NewBasicPodManager returns a functional Manager. 120 func NewBasicPodManager() Manager { 121 pm := &basicManager{} 122 pm.SetPods(nil) 123 return pm 124 } 125 126 // Set the internal pods based on the new pods. 127 func (pm *basicManager) SetPods(newPods []*v1.Pod) { 128 pm.lock.Lock() 129 defer pm.lock.Unlock() 130 131 pm.podByUID = make(map[kubetypes.ResolvedPodUID]*v1.Pod) 132 pm.podByFullName = make(map[string]*v1.Pod) 133 pm.mirrorPodByUID = make(map[kubetypes.MirrorPodUID]*v1.Pod) 134 pm.mirrorPodByFullName = make(map[string]*v1.Pod) 135 pm.translationByUID = make(map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID) 136 137 pm.updatePodsInternal(newPods...) 138 } 139 140 func (pm *basicManager) AddPod(pod *v1.Pod) { 141 pm.UpdatePod(pod) 142 } 143 144 func (pm *basicManager) UpdatePod(pod *v1.Pod) { 145 pm.lock.Lock() 146 defer pm.lock.Unlock() 147 pm.updatePodsInternal(pod) 148 } 149 150 // updateMetrics updates the metrics surfaced by the pod manager. 151 // oldPod or newPod may be nil to signify creation or deletion. 152 func updateMetrics(oldPod, newPod *v1.Pod) { 153 var numEC int 154 if oldPod != nil { 155 numEC -= len(oldPod.Spec.EphemeralContainers) 156 } 157 if newPod != nil { 158 numEC += len(newPod.Spec.EphemeralContainers) 159 } 160 if numEC != 0 { 161 metrics.ManagedEphemeralContainers.Add(float64(numEC)) 162 } 163 } 164 165 // updatePodsInternal replaces the given pods in the current state of the 166 // manager, updating the various indices. The caller is assumed to hold the 167 // lock. 168 func (pm *basicManager) updatePodsInternal(pods ...*v1.Pod) { 169 for _, pod := range pods { 170 podFullName := kubecontainer.GetPodFullName(pod) 171 // This logic relies on a static pod and its mirror to have the same name. 172 // It is safe to type convert here due to the IsMirrorPod guard. 173 if kubetypes.IsMirrorPod(pod) { 174 mirrorPodUID := kubetypes.MirrorPodUID(pod.UID) 175 pm.mirrorPodByUID[mirrorPodUID] = pod 176 pm.mirrorPodByFullName[podFullName] = pod 177 if p, ok := pm.podByFullName[podFullName]; ok { 178 pm.translationByUID[mirrorPodUID] = kubetypes.ResolvedPodUID(p.UID) 179 } 180 } else { 181 resolvedPodUID := kubetypes.ResolvedPodUID(pod.UID) 182 updateMetrics(pm.podByUID[resolvedPodUID], pod) 183 pm.podByUID[resolvedPodUID] = pod 184 pm.podByFullName[podFullName] = pod 185 if mirror, ok := pm.mirrorPodByFullName[podFullName]; ok { 186 pm.translationByUID[kubetypes.MirrorPodUID(mirror.UID)] = resolvedPodUID 187 } 188 } 189 } 190 } 191 192 func (pm *basicManager) RemovePod(pod *v1.Pod) { 193 updateMetrics(pod, nil) 194 pm.lock.Lock() 195 defer pm.lock.Unlock() 196 podFullName := kubecontainer.GetPodFullName(pod) 197 // It is safe to type convert here due to the IsMirrorPod guard. 198 if kubetypes.IsMirrorPod(pod) { 199 mirrorPodUID := kubetypes.MirrorPodUID(pod.UID) 200 delete(pm.mirrorPodByUID, mirrorPodUID) 201 delete(pm.mirrorPodByFullName, podFullName) 202 delete(pm.translationByUID, mirrorPodUID) 203 } else { 204 delete(pm.podByUID, kubetypes.ResolvedPodUID(pod.UID)) 205 delete(pm.podByFullName, podFullName) 206 } 207 } 208 209 func (pm *basicManager) GetPods() []*v1.Pod { 210 pm.lock.RLock() 211 defer pm.lock.RUnlock() 212 return podsMapToPods(pm.podByUID) 213 } 214 215 func (pm *basicManager) GetPodsAndMirrorPods() (allPods []*v1.Pod, allMirrorPods []*v1.Pod, orphanedMirrorPodFullnames []string) { 216 pm.lock.RLock() 217 defer pm.lock.RUnlock() 218 allPods = podsMapToPods(pm.podByUID) 219 allMirrorPods = mirrorPodsMapToMirrorPods(pm.mirrorPodByUID) 220 221 for podFullName := range pm.mirrorPodByFullName { 222 if _, ok := pm.podByFullName[podFullName]; !ok { 223 orphanedMirrorPodFullnames = append(orphanedMirrorPodFullnames, podFullName) 224 } 225 } 226 return allPods, allMirrorPods, orphanedMirrorPodFullnames 227 } 228 229 func (pm *basicManager) GetPodByUID(uid types.UID) (*v1.Pod, bool) { 230 pm.lock.RLock() 231 defer pm.lock.RUnlock() 232 pod, ok := pm.podByUID[kubetypes.ResolvedPodUID(uid)] // Safe conversion, map only holds non-mirrors. 233 return pod, ok 234 } 235 236 func (pm *basicManager) GetPodByName(namespace, name string) (*v1.Pod, bool) { 237 podFullName := kubecontainer.BuildPodFullName(name, namespace) 238 return pm.GetPodByFullName(podFullName) 239 } 240 241 func (pm *basicManager) GetPodByFullName(podFullName string) (*v1.Pod, bool) { 242 pm.lock.RLock() 243 defer pm.lock.RUnlock() 244 pod, ok := pm.podByFullName[podFullName] 245 return pod, ok 246 } 247 248 func (pm *basicManager) TranslatePodUID(uid types.UID) kubetypes.ResolvedPodUID { 249 // It is safe to type convert to a resolved UID because type conversion is idempotent. 250 if uid == "" { 251 return kubetypes.ResolvedPodUID(uid) 252 } 253 254 pm.lock.RLock() 255 defer pm.lock.RUnlock() 256 if translated, ok := pm.translationByUID[kubetypes.MirrorPodUID(uid)]; ok { 257 return translated 258 } 259 return kubetypes.ResolvedPodUID(uid) 260 } 261 262 func (pm *basicManager) GetUIDTranslations() (podToMirror map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID, 263 mirrorToPod map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID) { 264 pm.lock.RLock() 265 defer pm.lock.RUnlock() 266 267 podToMirror = make(map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID, len(pm.translationByUID)) 268 mirrorToPod = make(map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID, len(pm.translationByUID)) 269 // Insert empty translation mapping for all static pods. 270 for uid, pod := range pm.podByUID { 271 if !kubetypes.IsStaticPod(pod) { 272 continue 273 } 274 podToMirror[uid] = "" 275 } 276 // Fill in translations. Notice that if there is no mirror pod for a 277 // static pod, its uid will be translated into empty string "". This 278 // is WAI, from the caller side we can know that the static pod doesn't 279 // have a corresponding mirror pod instead of using static pod uid directly. 280 for k, v := range pm.translationByUID { 281 mirrorToPod[k] = v 282 podToMirror[v] = k 283 } 284 return podToMirror, mirrorToPod 285 } 286 287 // IsMirrorPodOf returns true if pod and mirrorPod are associated with each other. 288 func IsMirrorPodOf(mirrorPod, pod *v1.Pod) bool { 289 // Check name and namespace first. 290 if pod.Name != mirrorPod.Name || pod.Namespace != mirrorPod.Namespace { 291 return false 292 } 293 hash, ok := getHashFromMirrorPod(mirrorPod) 294 if !ok { 295 return false 296 } 297 return hash == getPodHash(pod) 298 } 299 300 func podsMapToPods(UIDMap map[kubetypes.ResolvedPodUID]*v1.Pod) []*v1.Pod { 301 pods := make([]*v1.Pod, 0, len(UIDMap)) 302 for _, pod := range UIDMap { 303 pods = append(pods, pod) 304 } 305 return pods 306 } 307 308 func mirrorPodsMapToMirrorPods(UIDMap map[kubetypes.MirrorPodUID]*v1.Pod) []*v1.Pod { 309 pods := make([]*v1.Pod, 0, len(UIDMap)) 310 for _, pod := range UIDMap { 311 pods = append(pods, pod) 312 } 313 return pods 314 } 315 316 func (pm *basicManager) GetMirrorPodByPod(pod *v1.Pod) (*v1.Pod, bool) { 317 pm.lock.RLock() 318 defer pm.lock.RUnlock() 319 mirrorPod, ok := pm.mirrorPodByFullName[kubecontainer.GetPodFullName(pod)] 320 return mirrorPod, ok 321 } 322 323 func (pm *basicManager) GetPodByMirrorPod(mirrorPod *v1.Pod) (*v1.Pod, bool) { 324 pm.lock.RLock() 325 defer pm.lock.RUnlock() 326 pod, ok := pm.podByFullName[kubecontainer.GetPodFullName(mirrorPod)] 327 return pod, ok 328 } 329 330 func (pm *basicManager) GetPodAndMirrorPod(aPod *v1.Pod) (pod, mirrorPod *v1.Pod, wasMirror bool) { 331 pm.lock.RLock() 332 defer pm.lock.RUnlock() 333 334 fullName := kubecontainer.GetPodFullName(aPod) 335 if kubetypes.IsMirrorPod(aPod) { 336 return pm.podByFullName[fullName], aPod, true 337 } 338 return aPod, pm.mirrorPodByFullName[fullName], false 339 340 }