least_allocated_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. Copyright 2019 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 noderesources
  14. import (
  15. "context"
  16. "reflect"
  17. "testing"
  18. v1 "k8s.io/api/core/v1"
  19. "k8s.io/apimachinery/pkg/api/resource"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
  22. "k8s.io/kubernetes/pkg/scheduler/internal/cache"
  23. )
  24. func TestNodeResourcesLeastAllocated(t *testing.T) {
  25. labels1 := map[string]string{
  26. "foo": "bar",
  27. "baz": "blah",
  28. }
  29. labels2 := map[string]string{
  30. "bar": "foo",
  31. "baz": "blah",
  32. }
  33. machine1Spec := v1.PodSpec{
  34. NodeName: "machine1",
  35. }
  36. machine2Spec := v1.PodSpec{
  37. NodeName: "machine2",
  38. }
  39. noResources := v1.PodSpec{
  40. Containers: []v1.Container{},
  41. }
  42. cpuOnly := v1.PodSpec{
  43. NodeName: "machine1",
  44. Containers: []v1.Container{
  45. {
  46. Resources: v1.ResourceRequirements{
  47. Requests: v1.ResourceList{
  48. v1.ResourceCPU: resource.MustParse("1000m"),
  49. v1.ResourceMemory: resource.MustParse("0"),
  50. },
  51. },
  52. },
  53. {
  54. Resources: v1.ResourceRequirements{
  55. Requests: v1.ResourceList{
  56. v1.ResourceCPU: resource.MustParse("2000m"),
  57. v1.ResourceMemory: resource.MustParse("0"),
  58. },
  59. },
  60. },
  61. },
  62. }
  63. cpuOnly2 := cpuOnly
  64. cpuOnly2.NodeName = "machine2"
  65. cpuAndMemory := v1.PodSpec{
  66. NodeName: "machine2",
  67. Containers: []v1.Container{
  68. {
  69. Resources: v1.ResourceRequirements{
  70. Requests: v1.ResourceList{
  71. v1.ResourceCPU: resource.MustParse("1000m"),
  72. v1.ResourceMemory: resource.MustParse("2000"),
  73. },
  74. },
  75. },
  76. {
  77. Resources: v1.ResourceRequirements{
  78. Requests: v1.ResourceList{
  79. v1.ResourceCPU: resource.MustParse("2000m"),
  80. v1.ResourceMemory: resource.MustParse("3000"),
  81. },
  82. },
  83. },
  84. },
  85. }
  86. tests := []struct {
  87. pod *v1.Pod
  88. pods []*v1.Pod
  89. nodes []*v1.Node
  90. expectedList framework.NodeScoreList
  91. name string
  92. }{
  93. {
  94. // Node1 scores (remaining resources) on 0-10 scale
  95. // CPU Score: ((4000 - 0) *100) / 4000 = 100
  96. // Memory Score: ((10000 - 0) *100) / 10000 = 100
  97. // Node1 Score: (100 + 100) / 2 = 100
  98. // Node2 scores (remaining resources) on 0-10 scale
  99. // CPU Score: ((4000 - 0) *100) / 4000 = 100
  100. // Memory Score: ((10000 - 0) *10) / 10000 = 100
  101. // Node2 Score: (100 + 100) / 2 = 100
  102. pod: &v1.Pod{Spec: noResources},
  103. nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)},
  104. expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}},
  105. name: "nothing scheduled, nothing requested",
  106. },
  107. {
  108. // Node1 scores on 0-10 scale
  109. // CPU Score: ((4000 - 3000) *100) / 4000 = 25
  110. // Memory Score: ((10000 - 5000) *100) / 10000 = 50
  111. // Node1 Score: (25 + 50) / 2 = 37
  112. // Node2 scores on 0-10 scale
  113. // CPU Score: ((6000 - 3000) *100) / 6000 = 50
  114. // Memory Score: ((10000 - 5000) *100) / 10000 = 50
  115. // Node2 Score: (50 + 50) / 2 = 50
  116. pod: &v1.Pod{Spec: cpuAndMemory},
  117. nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 6000, 10000)},
  118. expectedList: []framework.NodeScore{{Name: "machine1", Score: 37}, {Name: "machine2", Score: 50}},
  119. name: "nothing scheduled, resources requested, differently sized machines",
  120. },
  121. {
  122. // Node1 scores on 0-10 scale
  123. // CPU Score: ((4000 - 0) *100) / 4000 = 100
  124. // Memory Score: ((10000 - 0) *100) / 10000 = 100
  125. // Node1 Score: (100 + 100) / 2 = 100
  126. // Node2 scores on 0-10 scale
  127. // CPU Score: ((4000 - 0) *100) / 4000 = 100
  128. // Memory Score: ((10000 - 0) *100) / 10000 = 100
  129. // Node2 Score: (100 + 100) / 2 = 100
  130. pod: &v1.Pod{Spec: noResources},
  131. nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)},
  132. expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}},
  133. name: "no resources requested, pods scheduled",
  134. pods: []*v1.Pod{
  135. {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}},
  136. {Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  137. {Spec: machine2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  138. {Spec: machine2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  139. },
  140. },
  141. {
  142. // Node1 scores on 0-10 scale
  143. // CPU Score: ((10000 - 6000) *100) / 10000 = 40
  144. // Memory Score: ((20000 - 0) *100) / 20000 = 100
  145. // Node1 Score: (40 + 100) / 2 = 70
  146. // Node2 scores on 0-10 scale
  147. // CPU Score: ((10000 - 6000) *100) / 10000 = 40
  148. // Memory Score: ((20000 - 5000) *100) / 20000 = 75
  149. // Node2 Score: (40 + 75) / 2 = 57
  150. pod: &v1.Pod{Spec: noResources},
  151. nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)},
  152. expectedList: []framework.NodeScore{{Name: "machine1", Score: 70}, {Name: "machine2", Score: 57}},
  153. name: "no resources requested, pods scheduled with resources",
  154. pods: []*v1.Pod{
  155. {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}},
  156. {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  157. {Spec: cpuOnly2, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  158. {Spec: cpuAndMemory, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
  159. },
  160. },
  161. {
  162. // Node1 scores on 0-10 scale
  163. // CPU Score: ((10000 - 6000) *10) / 10000 = 40
  164. // Memory Score: ((20000 - 5000) *10) / 20000 = 75
  165. // Node1 Score: (40 + 75) / 2 = 57
  166. // Node2 scores on 0-10 scale
  167. // CPU Score: ((10000 - 6000) *100) / 10000 = 40
  168. // Memory Score: ((20000 - 10000) *100) / 20000 = 50
  169. // Node2 Score: (40 + 50) / 2 = 45
  170. pod: &v1.Pod{Spec: cpuAndMemory},
  171. nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 20000)},
  172. expectedList: []framework.NodeScore{{Name: "machine1", Score: 57}, {Name: "machine2", Score: 45}},
  173. name: "resources requested, pods scheduled with resources",
  174. pods: []*v1.Pod{
  175. {Spec: cpuOnly},
  176. {Spec: cpuAndMemory},
  177. },
  178. },
  179. {
  180. // Node1 scores on 0-10 scale
  181. // CPU Score: ((10000 - 6000) *100) / 10000 = 40
  182. // Memory Score: ((20000 - 5000) *100) / 20000 = 75
  183. // Node1 Score: (40 + 75) / 2 = 57
  184. // Node2 scores on 0-10 scale
  185. // CPU Score: ((10000 - 6000) *100) / 10000 = 40
  186. // Memory Score: ((50000 - 10000) *100) / 50000 = 80
  187. // Node2 Score: (40 + 80) / 2 = 60
  188. pod: &v1.Pod{Spec: cpuAndMemory},
  189. nodes: []*v1.Node{makeNode("machine1", 10000, 20000), makeNode("machine2", 10000, 50000)},
  190. expectedList: []framework.NodeScore{{Name: "machine1", Score: 57}, {Name: "machine2", Score: 60}},
  191. name: "resources requested, pods scheduled with resources, differently sized machines",
  192. pods: []*v1.Pod{
  193. {Spec: cpuOnly},
  194. {Spec: cpuAndMemory},
  195. },
  196. },
  197. {
  198. // Node1 scores on 0-10 scale
  199. // CPU Score: ((4000 - 6000) *100) / 4000 = 0
  200. // Memory Score: ((10000 - 0) *100) / 10000 = 100
  201. // Node1 Score: (0 + 100) / 2 = 50
  202. // Node2 scores on 0-10 scale
  203. // CPU Score: ((4000 - 6000) *100) / 4000 = 0
  204. // Memory Score: ((10000 - 5000) *100) / 10000 = 50
  205. // Node2 Score: (0 + 50) / 2 = 25
  206. pod: &v1.Pod{Spec: cpuOnly},
  207. nodes: []*v1.Node{makeNode("machine1", 4000, 10000), makeNode("machine2", 4000, 10000)},
  208. expectedList: []framework.NodeScore{{Name: "machine1", Score: 50}, {Name: "machine2", Score: 25}},
  209. name: "requested resources exceed node capacity",
  210. pods: []*v1.Pod{
  211. {Spec: cpuOnly},
  212. {Spec: cpuAndMemory},
  213. },
  214. },
  215. {
  216. pod: &v1.Pod{Spec: noResources},
  217. nodes: []*v1.Node{makeNode("machine1", 0, 0), makeNode("machine2", 0, 0)},
  218. expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}},
  219. name: "zero node resources, pods scheduled with resources",
  220. pods: []*v1.Pod{
  221. {Spec: cpuOnly},
  222. {Spec: cpuAndMemory},
  223. },
  224. },
  225. }
  226. for _, test := range tests {
  227. t.Run(test.name, func(t *testing.T) {
  228. snapshot := cache.NewSnapshot(test.pods, test.nodes)
  229. fh, _ := framework.NewFramework(nil, nil, nil, framework.WithSnapshotSharedLister(snapshot))
  230. p, _ := NewLeastAllocated(nil, fh)
  231. for i := range test.nodes {
  232. hostResult, err := p.(framework.ScorePlugin).Score(context.Background(), nil, test.pod, test.nodes[i].Name)
  233. if err != nil {
  234. t.Errorf("unexpected error: %v", err)
  235. }
  236. if !reflect.DeepEqual(test.expectedList[i].Score, hostResult) {
  237. t.Errorf("expected %#v, got %#v", test.expectedList[i].Score, hostResult)
  238. }
  239. }
  240. })
  241. }
  242. }