graph_populator.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. Copyright 2017 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 node
  14. import (
  15. "fmt"
  16. "k8s.io/klog"
  17. corev1 "k8s.io/api/core/v1"
  18. storagev1 "k8s.io/api/storage/v1"
  19. utilfeature "k8s.io/apiserver/pkg/util/feature"
  20. corev1informers "k8s.io/client-go/informers/core/v1"
  21. storageinformers "k8s.io/client-go/informers/storage/v1"
  22. "k8s.io/client-go/tools/cache"
  23. "k8s.io/kubernetes/pkg/features"
  24. )
  25. type graphPopulator struct {
  26. graph *Graph
  27. }
  28. func AddGraphEventHandlers(
  29. graph *Graph,
  30. nodes corev1informers.NodeInformer,
  31. pods corev1informers.PodInformer,
  32. pvs corev1informers.PersistentVolumeInformer,
  33. attachments storageinformers.VolumeAttachmentInformer,
  34. ) {
  35. g := &graphPopulator{
  36. graph: graph,
  37. }
  38. if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
  39. nodes.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
  40. AddFunc: g.addNode,
  41. UpdateFunc: g.updateNode,
  42. DeleteFunc: g.deleteNode,
  43. })
  44. }
  45. pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
  46. AddFunc: g.addPod,
  47. UpdateFunc: g.updatePod,
  48. DeleteFunc: g.deletePod,
  49. })
  50. pvs.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
  51. AddFunc: g.addPV,
  52. UpdateFunc: g.updatePV,
  53. DeleteFunc: g.deletePV,
  54. })
  55. attachments.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
  56. AddFunc: g.addVolumeAttachment,
  57. UpdateFunc: g.updateVolumeAttachment,
  58. DeleteFunc: g.deleteVolumeAttachment,
  59. })
  60. }
  61. func (g *graphPopulator) addNode(obj interface{}) {
  62. g.updateNode(nil, obj)
  63. }
  64. func (g *graphPopulator) updateNode(oldObj, obj interface{}) {
  65. node := obj.(*corev1.Node)
  66. var oldNode *corev1.Node
  67. if oldObj != nil {
  68. oldNode = oldObj.(*corev1.Node)
  69. }
  70. // we only set up rules for ConfigMap today, because that is the only reference type
  71. var name, namespace string
  72. if source := node.Spec.ConfigSource; source != nil && source.ConfigMap != nil {
  73. name = source.ConfigMap.Name
  74. namespace = source.ConfigMap.Namespace
  75. }
  76. var oldName, oldNamespace string
  77. if oldNode != nil {
  78. if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMap != nil {
  79. oldName = oldSource.ConfigMap.Name
  80. oldNamespace = oldSource.ConfigMap.Namespace
  81. }
  82. }
  83. // if Node.Spec.ConfigSource wasn't updated, nothing for us to do
  84. if name == oldName && namespace == oldNamespace {
  85. return
  86. }
  87. path := "nil"
  88. if node.Spec.ConfigSource != nil {
  89. path = fmt.Sprintf("%s/%s", namespace, name)
  90. }
  91. klog.V(4).Infof("updateNode configSource reference to %s for node %s", path, node.Name)
  92. g.graph.SetNodeConfigMap(node.Name, name, namespace)
  93. }
  94. func (g *graphPopulator) deleteNode(obj interface{}) {
  95. if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
  96. obj = tombstone.Obj
  97. }
  98. node, ok := obj.(*corev1.Node)
  99. if !ok {
  100. klog.Infof("unexpected type %T", obj)
  101. return
  102. }
  103. // NOTE: We don't remove the node, because if the node is re-created not all pod -> node
  104. // links are re-established (we don't get relevant events because the no mutations need
  105. // to happen in the API; the state is already there).
  106. g.graph.SetNodeConfigMap(node.Name, "", "")
  107. }
  108. func (g *graphPopulator) addPod(obj interface{}) {
  109. g.updatePod(nil, obj)
  110. }
  111. func (g *graphPopulator) updatePod(oldObj, obj interface{}) {
  112. pod := obj.(*corev1.Pod)
  113. if len(pod.Spec.NodeName) == 0 {
  114. // No node assigned
  115. klog.V(5).Infof("updatePod %s/%s, no node", pod.Namespace, pod.Name)
  116. return
  117. }
  118. if oldPod, ok := oldObj.(*corev1.Pod); ok && oldPod != nil {
  119. if (pod.Spec.NodeName == oldPod.Spec.NodeName) && (pod.UID == oldPod.UID) {
  120. // Node and uid are unchanged, all object references in the pod spec are immutable
  121. klog.V(5).Infof("updatePod %s/%s, node unchanged", pod.Namespace, pod.Name)
  122. return
  123. }
  124. }
  125. klog.V(4).Infof("updatePod %s/%s for node %s", pod.Namespace, pod.Name, pod.Spec.NodeName)
  126. g.graph.AddPod(pod)
  127. }
  128. func (g *graphPopulator) deletePod(obj interface{}) {
  129. if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
  130. obj = tombstone.Obj
  131. }
  132. pod, ok := obj.(*corev1.Pod)
  133. if !ok {
  134. klog.Infof("unexpected type %T", obj)
  135. return
  136. }
  137. if len(pod.Spec.NodeName) == 0 {
  138. klog.V(5).Infof("deletePod %s/%s, no node", pod.Namespace, pod.Name)
  139. return
  140. }
  141. klog.V(4).Infof("deletePod %s/%s for node %s", pod.Namespace, pod.Name, pod.Spec.NodeName)
  142. g.graph.DeletePod(pod.Name, pod.Namespace)
  143. }
  144. func (g *graphPopulator) addPV(obj interface{}) {
  145. g.updatePV(nil, obj)
  146. }
  147. func (g *graphPopulator) updatePV(oldObj, obj interface{}) {
  148. pv := obj.(*corev1.PersistentVolume)
  149. // TODO: skip add if uid, pvc, and secrets are all identical between old and new
  150. g.graph.AddPV(pv)
  151. }
  152. func (g *graphPopulator) deletePV(obj interface{}) {
  153. if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
  154. obj = tombstone.Obj
  155. }
  156. pv, ok := obj.(*corev1.PersistentVolume)
  157. if !ok {
  158. klog.Infof("unexpected type %T", obj)
  159. return
  160. }
  161. g.graph.DeletePV(pv.Name)
  162. }
  163. func (g *graphPopulator) addVolumeAttachment(obj interface{}) {
  164. g.updateVolumeAttachment(nil, obj)
  165. }
  166. func (g *graphPopulator) updateVolumeAttachment(oldObj, obj interface{}) {
  167. attachment := obj.(*storagev1.VolumeAttachment)
  168. if oldObj != nil {
  169. // skip add if node name is identical
  170. oldAttachment := oldObj.(*storagev1.VolumeAttachment)
  171. if oldAttachment.Spec.NodeName == attachment.Spec.NodeName {
  172. return
  173. }
  174. }
  175. g.graph.AddVolumeAttachment(attachment.Name, attachment.Spec.NodeName)
  176. }
  177. func (g *graphPopulator) deleteVolumeAttachment(obj interface{}) {
  178. if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
  179. obj = tombstone.Obj
  180. }
  181. attachment, ok := obj.(*storagev1.VolumeAttachment)
  182. if !ok {
  183. klog.Infof("unexpected type %T", obj)
  184. return
  185. }
  186. g.graph.DeleteVolumeAttachment(attachment.Name)
  187. }