mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 10:18:13 +00:00 
			
		
		
		
	Set MemorySwapLimitInBytes for CRI when NodeSwapEnabled
This commit is contained in:
		| @@ -652,6 +652,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, | ||||
| 		klet.containerLogManager, | ||||
| 		klet.runtimeClassManager, | ||||
| 		seccompDefault, | ||||
| 		kubeCfg.MemorySwap.SwapBehavior, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
|   | ||||
| @@ -89,6 +89,20 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *v1.C | ||||
|  | ||||
| 	lc.Resources.HugepageLimits = GetHugepageLimitsFromResources(container.Resources) | ||||
|  | ||||
| 	if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.NodeSwapEnabled) { | ||||
| 		// NOTE(ehashman): Behaviour is defined in the opencontainers runtime spec: | ||||
| 		// https://github.com/opencontainers/runtime-spec/blob/1c3f411f041711bbeecf35ff7e93461ea6789220/config-linux.md#memory | ||||
| 		switch m.memorySwapBehavior { | ||||
| 		case "UnlimitedSwap": | ||||
| 			// -1 = unlimited swap | ||||
| 			lc.Resources.MemorySwapLimitInBytes = -1 | ||||
| 		default: | ||||
| 			// memorySwapLimit = total permitted memory+swap; if equal to memory limit, => 0 swap | ||||
| 			// Note that if memory limit is 0, memory swap limit is ignored. | ||||
| 			lc.Resources.MemorySwapLimitInBytes = lc.Resources.MemoryLimitInBytes | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return lc | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -367,3 +367,92 @@ func TestGenerateLinuxContainerConfigNamespaces(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGenerateLinuxContainerConfigSwap(t *testing.T) { | ||||
| 	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.NodeSwapEnabled, true)() | ||||
| 	_, _, m, err := createTestRuntimeManager() | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating test RuntimeManager: %v", err) | ||||
| 	} | ||||
| 	m.machineInfo.MemoryCapacity = 1000000 | ||||
| 	containerName := "test" | ||||
|  | ||||
| 	for _, tc := range []struct { | ||||
| 		name        string | ||||
| 		swapSetting string | ||||
| 		pod         *v1.Pod | ||||
| 		expected    int64 | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "config unset, memory limit set", | ||||
| 			// no swap setting | ||||
| 			pod: &v1.Pod{ | ||||
| 				Spec: v1.PodSpec{ | ||||
| 					Containers: []v1.Container{{ | ||||
| 						Name: containerName, | ||||
| 						Resources: v1.ResourceRequirements{ | ||||
| 							Limits: v1.ResourceList{ | ||||
| 								"memory": resource.MustParse("1000"), | ||||
| 							}, | ||||
| 							Requests: v1.ResourceList{ | ||||
| 								"memory": resource.MustParse("1000"), | ||||
| 							}, | ||||
| 						}, | ||||
| 					}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: 1000, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "config unset, no memory limit", | ||||
| 			// no swap setting | ||||
| 			pod: &v1.Pod{ | ||||
| 				Spec: v1.PodSpec{ | ||||
| 					Containers: []v1.Container{ | ||||
| 						{Name: containerName}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: 0, | ||||
| 		}, | ||||
| 		{ | ||||
| 			// Note: behaviour will be the same as previous two cases | ||||
| 			name:        "config set to NoSwap, memory limit set", | ||||
| 			swapSetting: "NoSwap", | ||||
| 			pod: &v1.Pod{ | ||||
| 				Spec: v1.PodSpec{ | ||||
| 					Containers: []v1.Container{{ | ||||
| 						Name: containerName, | ||||
| 						Resources: v1.ResourceRequirements{ | ||||
| 							Limits: v1.ResourceList{ | ||||
| 								"memory": resource.MustParse("1000"), | ||||
| 							}, | ||||
| 							Requests: v1.ResourceList{ | ||||
| 								"memory": resource.MustParse("1000"), | ||||
| 							}, | ||||
| 						}, | ||||
| 					}}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: 1000, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:        "UnlimitedSwap enabled", | ||||
| 			swapSetting: "UnlimitedSwap", | ||||
| 			pod: &v1.Pod{ | ||||
| 				Spec: v1.PodSpec{ | ||||
| 					Containers: []v1.Container{ | ||||
| 						{Name: containerName}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: -1, | ||||
| 		}, | ||||
| 	} { | ||||
| 		t.Run(tc.name, func(t *testing.T) { | ||||
| 			m.memorySwapBehavior = tc.swapSetting | ||||
| 			actual := m.generateLinuxContainerConfig(&tc.pod.Spec.Containers[0], tc.pod, nil, "", nil) | ||||
| 			assert.Equal(t, tc.expected, actual.Resources.MemorySwapLimitInBytes, "memory swap config for %s", tc.name) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -144,6 +144,9 @@ type kubeGenericRuntimeManager struct { | ||||
|  | ||||
| 	// Use RuntimeDefault as the default seccomp profile for all workloads. | ||||
| 	seccompDefault bool | ||||
|  | ||||
| 	// MemorySwapBehavior defines how swap is used | ||||
| 	memorySwapBehavior string | ||||
| } | ||||
|  | ||||
| // KubeGenericRuntime is a interface contains interfaces for container runtime and command. | ||||
| @@ -186,6 +189,7 @@ func NewKubeGenericRuntimeManager( | ||||
| 	logManager logs.ContainerLogManager, | ||||
| 	runtimeClassManager *runtimeclass.Manager, | ||||
| 	seccompDefault bool, | ||||
| 	memorySwapBehavior string, | ||||
| ) (KubeGenericRuntime, error) { | ||||
| 	kubeRuntimeManager := &kubeGenericRuntimeManager{ | ||||
| 		recorder:            recorder, | ||||
| @@ -206,6 +210,7 @@ func NewKubeGenericRuntimeManager( | ||||
| 		runtimeClassManager: runtimeClassManager, | ||||
| 		logReduction:        logreduction.NewLogReduction(identicalErrorDelay), | ||||
| 		seccompDefault:      seccompDefault, | ||||
| 		memorySwapBehavior:  memorySwapBehavior, | ||||
| 	} | ||||
|  | ||||
| 	typedVersion, err := kubeRuntimeManager.getTypedVersion() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Elana Hashman
					Elana Hashman