scheduler_binder_cache.go 4.5 KB

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