resource_allocation.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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 priorities
  14. import (
  15. "fmt"
  16. v1 "k8s.io/api/core/v1"
  17. utilfeature "k8s.io/apiserver/pkg/util/feature"
  18. "k8s.io/klog"
  19. "k8s.io/kubernetes/pkg/features"
  20. priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util"
  21. schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
  22. schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
  23. )
  24. // ResourceAllocationPriority contains information to calculate resource allocation priority.
  25. type ResourceAllocationPriority struct {
  26. Name string
  27. scorer func(requested, allocable *schedulernodeinfo.Resource, includeVolumes bool, requestedVolumes int, allocatableVolumes int) int64
  28. }
  29. type CustomAllocationPriority struct {
  30. Name string
  31. scorer func(nodeName string) (float64, error)
  32. }
  33. // PriorityMap priorities nodes according to the resource allocations on the node.
  34. // It will use `scorer` function to calculate the score.
  35. func (r *ResourceAllocationPriority) PriorityMap(
  36. pod *v1.Pod,
  37. meta interface{},
  38. nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.HostPriority, error) {
  39. node := nodeInfo.Node()
  40. if node == nil {
  41. return schedulerapi.HostPriority{}, fmt.Errorf("node not found")
  42. }
  43. allocatable := nodeInfo.AllocatableResource()
  44. var requested schedulernodeinfo.Resource
  45. if priorityMeta, ok := meta.(*priorityMetadata); ok {
  46. requested = *priorityMeta.nonZeroRequest
  47. } else {
  48. // We couldn't parse metadata - fallback to computing it.
  49. requested = *getNonZeroRequests(pod)
  50. }
  51. requested.MilliCPU += nodeInfo.NonZeroRequest().MilliCPU
  52. requested.Memory += nodeInfo.NonZeroRequest().Memory
  53. var score int64
  54. // Check if the pod has volumes and this could be added to scorer function for balanced resource allocation.
  55. if len(pod.Spec.Volumes) >= 0 && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && nodeInfo.TransientInfo != nil {
  56. score = r.scorer(&requested, &allocatable, true, nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes, nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount)
  57. } else {
  58. score = r.scorer(&requested, &allocatable, false, 0, 0)
  59. }
  60. if klog.V(10) {
  61. if len(pod.Spec.Volumes) >= 0 && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && nodeInfo.TransientInfo != nil {
  62. klog.Infof(
  63. "%v -> %v: %v, capacity %d millicores %d memory bytes, %d volumes, total request %d millicores %d memory bytes %d volumes, score %d",
  64. pod.Name, node.Name, r.Name,
  65. allocatable.MilliCPU, allocatable.Memory, nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount,
  66. requested.MilliCPU, requested.Memory,
  67. nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes,
  68. score,
  69. )
  70. } else {
  71. klog.Infof(
  72. "%v -> %v: %v, capacity %d millicores %d memory bytes, total request %d millicores %d memory bytes, score %d",
  73. pod.Name, node.Name, r.Name,
  74. allocatable.MilliCPU, allocatable.Memory,
  75. requested.MilliCPU, requested.Memory,
  76. score,
  77. )
  78. }
  79. }
  80. return schedulerapi.HostPriority{
  81. Host: node.Name,
  82. Score: int(score),
  83. }, nil
  84. }
  85. func (r *CustomAllocationPriority) CustomPriorityMap(
  86. pod *v1.Pod,
  87. meta interface{},
  88. nodeInfo *schedulernodeinfo.NodeInfo) (schedulerapi.CustomHostPriority, error) {
  89. node := nodeInfo.Node()
  90. if node == nil {
  91. return schedulerapi.CustomHostPriority{}, fmt.Errorf("node not found")
  92. }
  93. //allocatable := nodeInfo.AllocatableResource()
  94. //var requested schedulernodeinfo.Resource
  95. // if priorityMeta, ok := meta.(*priorityMetadata); ok {
  96. // requested = *priorityMeta.nonZeroRequest
  97. // } else {
  98. // // We couldn't parse metadata - fallback to computing it.
  99. // requested = *getNonZeroRequests(pod)
  100. // }
  101. //requested.MilliCPU += nodeInfo.NonZeroRequest().MilliCPU
  102. //requested.Memory += nodeInfo.NonZeroRequest().Memory
  103. var score float64
  104. // Check if the pod has volumes and this could be added to scorer function for balanced resource allocation.
  105. // if len(pod.Spec.Volumes) >= 0 && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && nodeInfo.TransientInfo != nil {
  106. // score = r.scorer(&requested, &allocatable, true, nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes, nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount)
  107. // } else {
  108. // score = r.scorer(&requested, &allocatable, false, 0, 0)
  109. // }
  110. score, _ = r.scorer(node.Name)
  111. // if klog.V(10) {
  112. // if len(pod.Spec.Volumes) >= 0 && utilfeature.DefaultFeatureGate.Enabled(features.BalanceAttachedNodeVolumes) && nodeInfo.TransientInfo != nil {
  113. // klog.Infof(
  114. // "%v -> %v: %v, capacity %d millicores %d memory bytes, %d volumes, total request %d millicores %d memory bytes %d volumes, score %d",
  115. // pod.Name, node.Name, r.Name,
  116. // allocatable.MilliCPU, allocatable.Memory, nodeInfo.TransientInfo.TransNodeInfo.AllocatableVolumesCount,
  117. // requested.MilliCPU, requested.Memory,
  118. // nodeInfo.TransientInfo.TransNodeInfo.RequestedVolumes,
  119. // score,
  120. // )
  121. // } else {
  122. // klog.Infof(
  123. // "%v -> %v: %v, capacity %d millicores %d memory bytes, total request %d millicores %d memory bytes, score %d",
  124. // pod.Name, node.Name, r.Name,
  125. // allocatable.MilliCPU, allocatable.Memory,
  126. // requested.MilliCPU, requested.Memory,
  127. // score,
  128. // )
  129. // }
  130. // }
  131. // TODO create a custom HostPriority
  132. return schedulerapi.CustomHostPriority{
  133. Host: node.Name,
  134. Score: float64(score),
  135. }, nil
  136. // return schedulerapi.HostPriority{
  137. // Host: node.Name,
  138. // Score: int(score),
  139. // }, nil
  140. }
  141. func getNonZeroRequests(pod *v1.Pod) *schedulernodeinfo.Resource {
  142. result := &schedulernodeinfo.Resource{}
  143. for i := range pod.Spec.Containers {
  144. container := &pod.Spec.Containers[i]
  145. cpu, memory := priorityutil.GetNonzeroRequests(&container.Resources.Requests)
  146. result.MilliCPU += cpu
  147. result.Memory += memory
  148. }
  149. return result
  150. }