...

Source file src/k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources/resource_allocation_test.go

Documentation: k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources

     1  /*
     2  Copyright 2023 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package noderesources
    18  
    19  import (
    20  	"testing"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/api/resource"
    24  
    25  	"k8s.io/kubernetes/pkg/scheduler/util"
    26  )
    27  
    28  func TestResourceAllocationScorerCalculateRequests(t *testing.T) {
    29  	const oneMi = 1048576
    30  	tests := []struct {
    31  		name     string
    32  		pod      v1.Pod
    33  		expected map[v1.ResourceName]int64
    34  	}{
    35  		{
    36  			name: "overhead only",
    37  			pod: v1.Pod{
    38  				Spec: v1.PodSpec{
    39  					Overhead: v1.ResourceList{
    40  						v1.ResourceCPU:    resource.MustParse("1"),
    41  						v1.ResourceMemory: resource.MustParse("1Mi"),
    42  					},
    43  				},
    44  			},
    45  			expected: map[v1.ResourceName]int64{
    46  				v1.ResourceCPU:    1000,
    47  				v1.ResourceMemory: oneMi,
    48  			},
    49  		},
    50  		{
    51  			name: "1x requestless container",
    52  			pod: v1.Pod{
    53  				Spec: v1.PodSpec{
    54  					Containers: []v1.Container{
    55  						{},
    56  					},
    57  				},
    58  			},
    59  			expected: map[v1.ResourceName]int64{
    60  				v1.ResourceCPU:    util.DefaultMilliCPURequest,
    61  				v1.ResourceMemory: util.DefaultMemoryRequest,
    62  			},
    63  		},
    64  		{
    65  			name: "2x requestless container",
    66  			pod: v1.Pod{
    67  				Spec: v1.PodSpec{
    68  					Containers: []v1.Container{
    69  						{}, {},
    70  					},
    71  				},
    72  			},
    73  			// should accumulate once per container without a request
    74  			expected: map[v1.ResourceName]int64{
    75  				v1.ResourceCPU:    2 * util.DefaultMilliCPURequest,
    76  				v1.ResourceMemory: 2 * util.DefaultMemoryRequest,
    77  			},
    78  		},
    79  		{
    80  			name: "request container + requestless container",
    81  			pod: v1.Pod{
    82  				Spec: v1.PodSpec{
    83  					Containers: []v1.Container{
    84  						{
    85  							Resources: v1.ResourceRequirements{
    86  								Requests: v1.ResourceList{
    87  									v1.ResourceCPU:    resource.MustParse("1"),
    88  									v1.ResourceMemory: resource.MustParse("1Mi"),
    89  								},
    90  							},
    91  						},
    92  						{},
    93  					},
    94  				},
    95  			},
    96  			expected: map[v1.ResourceName]int64{
    97  				v1.ResourceCPU:    1000 + util.DefaultMilliCPURequest,
    98  				v1.ResourceMemory: oneMi + util.DefaultMemoryRequest,
    99  			},
   100  		},
   101  		{
   102  			name: "container + requestless container + overhead",
   103  			pod: v1.Pod{
   104  				Spec: v1.PodSpec{
   105  					Overhead: v1.ResourceList{
   106  						v1.ResourceCPU:    resource.MustParse("1"),
   107  						v1.ResourceMemory: resource.MustParse("1Mi"),
   108  					},
   109  					Containers: []v1.Container{
   110  						{
   111  							Resources: v1.ResourceRequirements{
   112  								Requests: v1.ResourceList{
   113  									v1.ResourceCPU:    resource.MustParse("1"),
   114  									v1.ResourceMemory: resource.MustParse("1Mi"),
   115  								},
   116  							},
   117  						},
   118  						{},
   119  					},
   120  				},
   121  			},
   122  			expected: map[v1.ResourceName]int64{
   123  				v1.ResourceCPU:    2000 + util.DefaultMilliCPURequest,
   124  				v1.ResourceMemory: 2*oneMi + util.DefaultMemoryRequest,
   125  			},
   126  		},
   127  		{
   128  			name: "init container + container + requestless container + overhead",
   129  			pod: v1.Pod{
   130  				Spec: v1.PodSpec{
   131  					Overhead: v1.ResourceList{
   132  						v1.ResourceCPU:    resource.MustParse("1"),
   133  						v1.ResourceMemory: resource.MustParse("1Mi"),
   134  					},
   135  					InitContainers: []v1.Container{
   136  						{
   137  							Resources: v1.ResourceRequirements{
   138  								Requests: v1.ResourceList{
   139  									v1.ResourceCPU: resource.MustParse("3"),
   140  								},
   141  							},
   142  						},
   143  					},
   144  					Containers: []v1.Container{
   145  						{
   146  							Resources: v1.ResourceRequirements{
   147  								Requests: v1.ResourceList{
   148  									v1.ResourceCPU:    resource.MustParse("1"),
   149  									v1.ResourceMemory: resource.MustParse("1Mi"),
   150  								},
   151  							},
   152  						},
   153  						{},
   154  					},
   155  				},
   156  			},
   157  			expected: map[v1.ResourceName]int64{
   158  				v1.ResourceCPU:    4000,
   159  				v1.ResourceMemory: 2*oneMi + util.DefaultMemoryRequest,
   160  			},
   161  		},
   162  		{
   163  			name: "requestless init container + small init container + small container ",
   164  			pod: v1.Pod{
   165  				Spec: v1.PodSpec{
   166  					InitContainers: []v1.Container{
   167  						{},
   168  						{
   169  							Resources: v1.ResourceRequirements{
   170  								Requests: v1.ResourceList{
   171  									v1.ResourceCPU:    resource.MustParse("1m"),
   172  									v1.ResourceMemory: resource.MustParse("1"),
   173  								},
   174  							},
   175  						},
   176  					},
   177  					Containers: []v1.Container{
   178  						{
   179  							Resources: v1.ResourceRequirements{
   180  								Requests: v1.ResourceList{
   181  									v1.ResourceCPU:    resource.MustParse("3m"),
   182  									v1.ResourceMemory: resource.MustParse("3"),
   183  								},
   184  							},
   185  						},
   186  					},
   187  				},
   188  			},
   189  			expected: map[v1.ResourceName]int64{
   190  				v1.ResourceCPU:    util.DefaultMilliCPURequest,
   191  				v1.ResourceMemory: util.DefaultMemoryRequest,
   192  			},
   193  		},
   194  		{
   195  			name: "requestless init container + small init container + small container + requestless container ",
   196  			pod: v1.Pod{
   197  				Spec: v1.PodSpec{
   198  					InitContainers: []v1.Container{
   199  						{},
   200  						{
   201  							Resources: v1.ResourceRequirements{
   202  								Requests: v1.ResourceList{
   203  									v1.ResourceCPU:    resource.MustParse("1m"),
   204  									v1.ResourceMemory: resource.MustParse("1"),
   205  								},
   206  							},
   207  						},
   208  					},
   209  					Containers: []v1.Container{
   210  						{
   211  							Resources: v1.ResourceRequirements{
   212  								Requests: v1.ResourceList{
   213  									v1.ResourceCPU:    resource.MustParse("3m"),
   214  									v1.ResourceMemory: resource.MustParse("3"),
   215  								},
   216  							},
   217  						},
   218  						{},
   219  					},
   220  				},
   221  			},
   222  			expected: map[v1.ResourceName]int64{
   223  				v1.ResourceCPU:    3 + util.DefaultMilliCPURequest,
   224  				v1.ResourceMemory: 3 + util.DefaultMemoryRequest,
   225  			},
   226  		},
   227  	}
   228  
   229  	for _, tc := range tests {
   230  		t.Run(tc.name, func(t *testing.T) {
   231  			var scorer resourceAllocationScorer
   232  			for n, exp := range tc.expected {
   233  				got := scorer.calculatePodResourceRequest(&tc.pod, n)
   234  				if got != exp {
   235  					t.Errorf("expected %s = %d, got %d", n, exp, got)
   236  				}
   237  			}
   238  		})
   239  	}
   240  }
   241  

View as plain text