scheduler_binder_cache.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 scheduling
  14. import (
  15. "sync"
  16. v1 "k8s.io/api/core/v1"
  17. "k8s.io/kubernetes/pkg/controller/volume/scheduling/metrics"
  18. )
  19. // PodBindingCache stores PV binding decisions per pod per node.
  20. // Pod entries are removed when the Pod is deleted or updated to
  21. // no longer be schedulable.
  22. type PodBindingCache interface {
  23. // UpdateBindings will update the cache with the given bindings for the
  24. // pod and node.
  25. UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo, provisionings []*v1.PersistentVolumeClaim)
  26. // ClearBindings will clear the cached bindings for the given pod and node.
  27. ClearBindings(pod *v1.Pod, node string)
  28. // GetBindings will return the cached bindings for the given pod and node.
  29. // A nil return value means that the entry was not found. An empty slice
  30. // means that no binding operations are needed.
  31. GetBindings(pod *v1.Pod, node string) []*bindingInfo
  32. // A nil return value means that the entry was not found. An empty slice
  33. // means that no provisioning operations are needed.
  34. GetProvisionedPVCs(pod *v1.Pod, node string) []*v1.PersistentVolumeClaim
  35. // GetDecisions will return all cached decisions for the given pod.
  36. GetDecisions(pod *v1.Pod) nodeDecisions
  37. // DeleteBindings will remove all cached bindings and provisionings for the given pod.
  38. // TODO: separate the func if it is needed to delete bindings/provisionings individually
  39. DeleteBindings(pod *v1.Pod)
  40. }
  41. type podBindingCache struct {
  42. // synchronizes bindingDecisions
  43. rwMutex sync.RWMutex
  44. // Key = pod name
  45. // Value = nodeDecisions
  46. bindingDecisions map[string]nodeDecisions
  47. }
  48. // Key = nodeName
  49. // Value = bindings & provisioned PVCs of the node
  50. type nodeDecisions map[string]nodeDecision
  51. // A decision includes bindingInfo and provisioned PVCs of the node
  52. type nodeDecision struct {
  53. bindings []*bindingInfo
  54. provisionings []*v1.PersistentVolumeClaim
  55. }
  56. // NewPodBindingCache creates a pod binding cache.
  57. func NewPodBindingCache() PodBindingCache {
  58. return &podBindingCache{bindingDecisions: map[string]nodeDecisions{}}
  59. }
  60. func (c *podBindingCache) GetDecisions(pod *v1.Pod) nodeDecisions {
  61. c.rwMutex.RLock()
  62. defer c.rwMutex.RUnlock()
  63. podName := getPodName(pod)
  64. decisions, ok := c.bindingDecisions[podName]
  65. if !ok {
  66. return nil
  67. }
  68. return decisions
  69. }
  70. func (c *podBindingCache) DeleteBindings(pod *v1.Pod) {
  71. c.rwMutex.Lock()
  72. defer c.rwMutex.Unlock()
  73. podName := getPodName(pod)
  74. if _, ok := c.bindingDecisions[podName]; ok {
  75. delete(c.bindingDecisions, podName)
  76. metrics.VolumeBindingRequestSchedulerBinderCache.WithLabelValues("delete").Inc()
  77. }
  78. }
  79. func (c *podBindingCache) UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo, pvcs []*v1.PersistentVolumeClaim) {
  80. c.rwMutex.Lock()
  81. defer c.rwMutex.Unlock()
  82. podName := getPodName(pod)
  83. decisions, ok := c.bindingDecisions[podName]
  84. if !ok {
  85. decisions = nodeDecisions{}
  86. c.bindingDecisions[podName] = decisions
  87. }
  88. decision, ok := decisions[node]
  89. if !ok {
  90. decision = nodeDecision{
  91. bindings: bindings,
  92. provisionings: pvcs,
  93. }
  94. metrics.VolumeBindingRequestSchedulerBinderCache.WithLabelValues("add").Inc()
  95. } else {
  96. decision.bindings = bindings
  97. decision.provisionings = pvcs
  98. }
  99. decisions[node] = decision
  100. }
  101. func (c *podBindingCache) GetBindings(pod *v1.Pod, node string) []*bindingInfo {
  102. c.rwMutex.RLock()
  103. defer c.rwMutex.RUnlock()
  104. podName := getPodName(pod)
  105. decisions, ok := c.bindingDecisions[podName]
  106. if !ok {
  107. return nil
  108. }
  109. decision, ok := decisions[node]
  110. if !ok {
  111. return nil
  112. }
  113. return decision.bindings
  114. }
  115. func (c *podBindingCache) GetProvisionedPVCs(pod *v1.Pod, node string) []*v1.PersistentVolumeClaim {
  116. c.rwMutex.RLock()
  117. defer c.rwMutex.RUnlock()
  118. podName := getPodName(pod)
  119. decisions, ok := c.bindingDecisions[podName]
  120. if !ok {
  121. return nil
  122. }
  123. decision, ok := decisions[node]
  124. if !ok {
  125. return nil
  126. }
  127. return decision.provisionings
  128. }
  129. func (c *podBindingCache) ClearBindings(pod *v1.Pod, node string) {
  130. c.rwMutex.Lock()
  131. defer c.rwMutex.Unlock()
  132. podName := getPodName(pod)
  133. decisions, ok := c.bindingDecisions[podName]
  134. if !ok {
  135. return
  136. }
  137. delete(decisions, node)
  138. }