...

Source file src/k8s.io/kubernetes/pkg/kubelet/cm/node_container_manager_linux_test.go

Documentation: k8s.io/kubernetes/pkg/kubelet/cm

     1  //go:build linux
     2  // +build linux
     3  
     4  /*
     5  Copyright 2017 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package cm
    21  
    22  import (
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  	"k8s.io/api/core/v1"
    27  	"k8s.io/apimachinery/pkg/api/resource"
    28  	evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api"
    29  )
    30  
    31  func TestNodeAllocatableReservationForScheduling(t *testing.T) {
    32  	memoryEvictionThreshold := resource.MustParse("100Mi")
    33  	cpuMemCases := []struct {
    34  		kubeReserved   v1.ResourceList
    35  		systemReserved v1.ResourceList
    36  		expected       v1.ResourceList
    37  		capacity       v1.ResourceList
    38  		hardThreshold  evictionapi.ThresholdValue
    39  	}{
    40  		{
    41  			kubeReserved:   getResourceList("100m", "100Mi"),
    42  			systemReserved: getResourceList("50m", "50Mi"),
    43  			capacity:       getResourceList("10", "10Gi"),
    44  			expected:       getResourceList("150m", "150Mi"),
    45  		},
    46  		{
    47  			kubeReserved:   getResourceList("100m", "100Mi"),
    48  			systemReserved: getResourceList("50m", "50Mi"),
    49  			hardThreshold: evictionapi.ThresholdValue{
    50  				Quantity: &memoryEvictionThreshold,
    51  			},
    52  			capacity: getResourceList("10", "10Gi"),
    53  			expected: getResourceList("150m", "250Mi"),
    54  		},
    55  		{
    56  			kubeReserved:   getResourceList("100m", "100Mi"),
    57  			systemReserved: getResourceList("50m", "50Mi"),
    58  			capacity:       getResourceList("10", "10Gi"),
    59  			hardThreshold: evictionapi.ThresholdValue{
    60  				Percentage: 0.05,
    61  			},
    62  			expected: getResourceList("150m", "694157320"),
    63  		},
    64  
    65  		{
    66  			kubeReserved:   v1.ResourceList{},
    67  			systemReserved: v1.ResourceList{},
    68  			capacity:       getResourceList("10", "10Gi"),
    69  			expected:       getResourceList("", ""),
    70  		},
    71  		{
    72  			kubeReserved:   getResourceList("", "100Mi"),
    73  			systemReserved: getResourceList("50m", "50Mi"),
    74  			capacity:       getResourceList("10", "10Gi"),
    75  			expected:       getResourceList("50m", "150Mi"),
    76  		},
    77  
    78  		{
    79  			kubeReserved:   getResourceList("50m", "100Mi"),
    80  			systemReserved: getResourceList("", "50Mi"),
    81  			capacity:       getResourceList("10", "10Gi"),
    82  			expected:       getResourceList("50m", "150Mi"),
    83  		},
    84  		{
    85  			kubeReserved:   getResourceList("", "100Mi"),
    86  			systemReserved: getResourceList("", "50Mi"),
    87  			capacity:       getResourceList("10", ""),
    88  			expected:       getResourceList("", "150Mi"),
    89  		},
    90  	}
    91  	for idx, tc := range cpuMemCases {
    92  		nc := NodeConfig{
    93  			NodeAllocatableConfig: NodeAllocatableConfig{
    94  				KubeReserved:   tc.kubeReserved,
    95  				SystemReserved: tc.systemReserved,
    96  				HardEvictionThresholds: []evictionapi.Threshold{
    97  					{
    98  						Signal:   evictionapi.SignalMemoryAvailable,
    99  						Operator: evictionapi.OpLessThan,
   100  						Value:    tc.hardThreshold,
   101  					},
   102  				},
   103  			},
   104  		}
   105  		cm := &containerManagerImpl{
   106  			NodeConfig: nc,
   107  			capacity:   tc.capacity,
   108  		}
   109  		for k, v := range cm.GetNodeAllocatableReservation() {
   110  			expected, exists := tc.expected[k]
   111  			assert.True(t, exists, "test case %d expected resource %q", idx+1, k)
   112  			assert.Equal(t, expected.MilliValue(), v.MilliValue(), "test case %d failed for resource %q", idx+1, k)
   113  		}
   114  	}
   115  
   116  	ephemeralStorageEvictionThreshold := resource.MustParse("100Mi")
   117  	ephemeralStorageTestCases := []struct {
   118  		kubeReserved  v1.ResourceList
   119  		expected      v1.ResourceList
   120  		capacity      v1.ResourceList
   121  		hardThreshold evictionapi.ThresholdValue
   122  	}{
   123  		{
   124  			kubeReserved: getEphemeralStorageResourceList("100Mi"),
   125  			capacity:     getEphemeralStorageResourceList("10Gi"),
   126  			expected:     getEphemeralStorageResourceList("100Mi"),
   127  		},
   128  		{
   129  			kubeReserved: getEphemeralStorageResourceList("100Mi"),
   130  			hardThreshold: evictionapi.ThresholdValue{
   131  				Quantity: &ephemeralStorageEvictionThreshold,
   132  			},
   133  			capacity: getEphemeralStorageResourceList("10Gi"),
   134  			expected: getEphemeralStorageResourceList("200Mi"),
   135  		},
   136  		{
   137  			kubeReserved: getEphemeralStorageResourceList("150Mi"),
   138  			capacity:     getEphemeralStorageResourceList("10Gi"),
   139  			hardThreshold: evictionapi.ThresholdValue{
   140  				Percentage: 0.05,
   141  			},
   142  			expected: getEphemeralStorageResourceList("694157320"),
   143  		},
   144  
   145  		{
   146  			kubeReserved: v1.ResourceList{},
   147  			capacity:     getEphemeralStorageResourceList("10Gi"),
   148  			expected:     getEphemeralStorageResourceList(""),
   149  		},
   150  	}
   151  	for idx, tc := range ephemeralStorageTestCases {
   152  		nc := NodeConfig{
   153  			NodeAllocatableConfig: NodeAllocatableConfig{
   154  				KubeReserved: tc.kubeReserved,
   155  				HardEvictionThresholds: []evictionapi.Threshold{
   156  					{
   157  						Signal:   evictionapi.SignalNodeFsAvailable,
   158  						Operator: evictionapi.OpLessThan,
   159  						Value:    tc.hardThreshold,
   160  					},
   161  				},
   162  			},
   163  		}
   164  		cm := &containerManagerImpl{
   165  			NodeConfig: nc,
   166  			capacity:   tc.capacity,
   167  		}
   168  		for k, v := range cm.GetNodeAllocatableReservation() {
   169  			expected, exists := tc.expected[k]
   170  			assert.True(t, exists, "test case %d expected resource %q", idx+1, k)
   171  			assert.Equal(t, expected.MilliValue(), v.MilliValue(), "test case %d failed for resource %q", idx+1, k)
   172  		}
   173  	}
   174  }
   175  
   176  func TestNodeAllocatableForEnforcement(t *testing.T) {
   177  	memoryEvictionThreshold := resource.MustParse("100Mi")
   178  	testCases := []struct {
   179  		kubeReserved   v1.ResourceList
   180  		systemReserved v1.ResourceList
   181  		capacity       v1.ResourceList
   182  		expected       v1.ResourceList
   183  		hardThreshold  evictionapi.ThresholdValue
   184  	}{
   185  		{
   186  			kubeReserved:   getResourceList("100m", "100Mi"),
   187  			systemReserved: getResourceList("50m", "50Mi"),
   188  			capacity:       getResourceList("10", "10Gi"),
   189  			expected:       getResourceList("9850m", "10090Mi"),
   190  		},
   191  		{
   192  			kubeReserved:   getResourceList("100m", "100Mi"),
   193  			systemReserved: getResourceList("50m", "50Mi"),
   194  			hardThreshold: evictionapi.ThresholdValue{
   195  				Quantity: &memoryEvictionThreshold,
   196  			},
   197  			capacity: getResourceList("10", "10Gi"),
   198  			expected: getResourceList("9850m", "10090Mi"),
   199  		},
   200  		{
   201  			kubeReserved:   getResourceList("100m", "100Mi"),
   202  			systemReserved: getResourceList("50m", "50Mi"),
   203  			hardThreshold: evictionapi.ThresholdValue{
   204  				Percentage: 0.05,
   205  			},
   206  			capacity: getResourceList("10", "10Gi"),
   207  			expected: getResourceList("9850m", "10090Mi"),
   208  		},
   209  
   210  		{
   211  			kubeReserved:   v1.ResourceList{},
   212  			systemReserved: v1.ResourceList{},
   213  			capacity:       getResourceList("10", "10Gi"),
   214  			expected:       getResourceList("10", "10Gi"),
   215  		},
   216  		{
   217  			kubeReserved:   getResourceList("", "100Mi"),
   218  			systemReserved: getResourceList("50m", "50Mi"),
   219  			capacity:       getResourceList("10", "10Gi"),
   220  			expected:       getResourceList("9950m", "10090Mi"),
   221  		},
   222  
   223  		{
   224  			kubeReserved:   getResourceList("50m", "100Mi"),
   225  			systemReserved: getResourceList("", "50Mi"),
   226  			capacity:       getResourceList("10", "10Gi"),
   227  			expected:       getResourceList("9950m", "10090Mi"),
   228  		},
   229  		{
   230  			kubeReserved:   getResourceList("", "100Mi"),
   231  			systemReserved: getResourceList("", "50Mi"),
   232  			capacity:       getResourceList("10", ""),
   233  			expected:       getResourceList("10", ""),
   234  		},
   235  	}
   236  	for idx, tc := range testCases {
   237  		nc := NodeConfig{
   238  			NodeAllocatableConfig: NodeAllocatableConfig{
   239  				KubeReserved:   tc.kubeReserved,
   240  				SystemReserved: tc.systemReserved,
   241  				HardEvictionThresholds: []evictionapi.Threshold{
   242  					{
   243  						Signal:   evictionapi.SignalMemoryAvailable,
   244  						Operator: evictionapi.OpLessThan,
   245  						Value:    tc.hardThreshold,
   246  					},
   247  				},
   248  			},
   249  		}
   250  		cm := &containerManagerImpl{
   251  			NodeConfig: nc,
   252  			capacity:   tc.capacity,
   253  		}
   254  		for k, v := range cm.GetNodeAllocatableAbsolute() {
   255  			expected, exists := tc.expected[k]
   256  			assert.True(t, exists)
   257  			assert.Equal(t, expected.MilliValue(), v.MilliValue(), "test case %d failed for resource %q", idx+1, k)
   258  		}
   259  	}
   260  }
   261  
   262  func TestNodeAllocatableInputValidation(t *testing.T) {
   263  	memoryEvictionThreshold := resource.MustParse("100Mi")
   264  	highMemoryEvictionThreshold := resource.MustParse("2Gi")
   265  	cpuMemTestCases := []struct {
   266  		kubeReserved         v1.ResourceList
   267  		systemReserved       v1.ResourceList
   268  		capacity             v1.ResourceList
   269  		hardThreshold        evictionapi.ThresholdValue
   270  		invalidConfiguration bool
   271  	}{
   272  		{
   273  			kubeReserved:   getResourceList("100m", "100Mi"),
   274  			systemReserved: getResourceList("50m", "50Mi"),
   275  			capacity:       getResourceList("10", "10Gi"),
   276  		},
   277  		{
   278  			kubeReserved:   getResourceList("100m", "100Mi"),
   279  			systemReserved: getResourceList("50m", "50Mi"),
   280  			hardThreshold: evictionapi.ThresholdValue{
   281  				Quantity: &memoryEvictionThreshold,
   282  			},
   283  			capacity: getResourceList("10", "10Gi"),
   284  		},
   285  		{
   286  			kubeReserved:   getResourceList("100m", "100Mi"),
   287  			systemReserved: getResourceList("50m", "50Mi"),
   288  			hardThreshold: evictionapi.ThresholdValue{
   289  				Percentage: 0.05,
   290  			},
   291  			capacity: getResourceList("10", "10Gi"),
   292  		},
   293  		{
   294  			kubeReserved:   v1.ResourceList{},
   295  			systemReserved: v1.ResourceList{},
   296  			capacity:       getResourceList("10", "10Gi"),
   297  		},
   298  		{
   299  			kubeReserved:   getResourceList("", "100Mi"),
   300  			systemReserved: getResourceList("50m", "50Mi"),
   301  			capacity:       getResourceList("10", "10Gi"),
   302  		},
   303  		{
   304  			kubeReserved:   getResourceList("50m", "100Mi"),
   305  			systemReserved: getResourceList("", "50Mi"),
   306  			capacity:       getResourceList("10", "10Gi"),
   307  		},
   308  		{
   309  			kubeReserved:   getResourceList("", "100Mi"),
   310  			systemReserved: getResourceList("", "50Mi"),
   311  			capacity:       getResourceList("10", ""),
   312  		},
   313  		{
   314  			kubeReserved:   getResourceList("5", "10Gi"),
   315  			systemReserved: getResourceList("5", "10Gi"),
   316  			hardThreshold: evictionapi.ThresholdValue{
   317  				Quantity: &highMemoryEvictionThreshold,
   318  			},
   319  			capacity:             getResourceList("10", "11Gi"),
   320  			invalidConfiguration: true,
   321  		},
   322  	}
   323  	for _, tc := range cpuMemTestCases {
   324  		nc := NodeConfig{
   325  			NodeAllocatableConfig: NodeAllocatableConfig{
   326  				KubeReserved:   tc.kubeReserved,
   327  				SystemReserved: tc.systemReserved,
   328  				HardEvictionThresholds: []evictionapi.Threshold{
   329  					{
   330  						Signal:   evictionapi.SignalMemoryAvailable,
   331  						Operator: evictionapi.OpLessThan,
   332  						Value:    tc.hardThreshold,
   333  					},
   334  				},
   335  			},
   336  		}
   337  		cm := &containerManagerImpl{
   338  			NodeConfig: nc,
   339  			capacity:   tc.capacity,
   340  		}
   341  		err := cm.validateNodeAllocatable()
   342  		if err == nil && tc.invalidConfiguration {
   343  			t.Fatalf("Expected invalid node allocatable configuration")
   344  		} else if err != nil && !tc.invalidConfiguration {
   345  			t.Fatalf("Expected valid node allocatable configuration: %v", err)
   346  		}
   347  	}
   348  
   349  	ephemeralStorageEvictionThreshold := resource.MustParse("100Mi")
   350  	ephemeralStorageTestCases := []struct {
   351  		kubeReserved         v1.ResourceList
   352  		capacity             v1.ResourceList
   353  		hardThreshold        evictionapi.ThresholdValue
   354  		invalidConfiguration bool
   355  	}{
   356  		{
   357  			kubeReserved: getEphemeralStorageResourceList("100Mi"),
   358  			capacity:     getEphemeralStorageResourceList("500Mi"),
   359  		},
   360  		{
   361  			kubeReserved: getEphemeralStorageResourceList("20Gi"),
   362  			hardThreshold: evictionapi.ThresholdValue{
   363  				Quantity: &ephemeralStorageEvictionThreshold,
   364  			},
   365  			capacity:             getEphemeralStorageResourceList("20Gi"),
   366  			invalidConfiguration: true,
   367  		},
   368  	}
   369  	for _, tc := range ephemeralStorageTestCases {
   370  		nc := NodeConfig{
   371  			NodeAllocatableConfig: NodeAllocatableConfig{
   372  				KubeReserved: tc.kubeReserved,
   373  				HardEvictionThresholds: []evictionapi.Threshold{
   374  					{
   375  						Signal:   evictionapi.SignalNodeFsAvailable,
   376  						Operator: evictionapi.OpLessThan,
   377  						Value:    tc.hardThreshold,
   378  					},
   379  				},
   380  			},
   381  		}
   382  		cm := &containerManagerImpl{
   383  			NodeConfig: nc,
   384  			capacity:   tc.capacity,
   385  		}
   386  		err := cm.validateNodeAllocatable()
   387  		if err == nil && tc.invalidConfiguration {
   388  			t.Fatalf("Expected invalid node allocatable configuration")
   389  		} else if err != nil && !tc.invalidConfiguration {
   390  			t.Fatalf("Expected valid node allocatable configuration: %v", err)
   391  		}
   392  	}
   393  }
   394  
   395  // getEphemeralStorageResourceList returns a ResourceList with the
   396  // specified ephemeral storage resource values
   397  func getEphemeralStorageResourceList(storage string) v1.ResourceList {
   398  	res := v1.ResourceList{}
   399  	if storage != "" {
   400  		res[v1.ResourceEphemeralStorage] = resource.MustParse(storage)
   401  	}
   402  	return res
   403  }
   404  

View as plain text