pod_manager.go 13 KB

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