mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28: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.containerLogManager, | ||||||
| 		klet.runtimeClassManager, | 		klet.runtimeClassManager, | ||||||
| 		seccompDefault, | 		seccompDefault, | ||||||
|  | 		kubeCfg.MemorySwap.SwapBehavior, | ||||||
| 	) | 	) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
|   | |||||||
| @@ -89,6 +89,20 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *v1.C | |||||||
|  |  | ||||||
| 	lc.Resources.HugepageLimits = GetHugepageLimitsFromResources(container.Resources) | 	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 | 	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. | 	// Use RuntimeDefault as the default seccomp profile for all workloads. | ||||||
| 	seccompDefault bool | 	seccompDefault bool | ||||||
|  |  | ||||||
|  | 	// MemorySwapBehavior defines how swap is used | ||||||
|  | 	memorySwapBehavior string | ||||||
| } | } | ||||||
|  |  | ||||||
| // KubeGenericRuntime is a interface contains interfaces for container runtime and command. | // KubeGenericRuntime is a interface contains interfaces for container runtime and command. | ||||||
| @@ -186,6 +189,7 @@ func NewKubeGenericRuntimeManager( | |||||||
| 	logManager logs.ContainerLogManager, | 	logManager logs.ContainerLogManager, | ||||||
| 	runtimeClassManager *runtimeclass.Manager, | 	runtimeClassManager *runtimeclass.Manager, | ||||||
| 	seccompDefault bool, | 	seccompDefault bool, | ||||||
|  | 	memorySwapBehavior string, | ||||||
| ) (KubeGenericRuntime, error) { | ) (KubeGenericRuntime, error) { | ||||||
| 	kubeRuntimeManager := &kubeGenericRuntimeManager{ | 	kubeRuntimeManager := &kubeGenericRuntimeManager{ | ||||||
| 		recorder:            recorder, | 		recorder:            recorder, | ||||||
| @@ -206,6 +210,7 @@ func NewKubeGenericRuntimeManager( | |||||||
| 		runtimeClassManager: runtimeClassManager, | 		runtimeClassManager: runtimeClassManager, | ||||||
| 		logReduction:        logreduction.NewLogReduction(identicalErrorDelay), | 		logReduction:        logreduction.NewLogReduction(identicalErrorDelay), | ||||||
| 		seccompDefault:      seccompDefault, | 		seccompDefault:      seccompDefault, | ||||||
|  | 		memorySwapBehavior:  memorySwapBehavior, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	typedVersion, err := kubeRuntimeManager.getTypedVersion() | 	typedVersion, err := kubeRuntimeManager.getTypedVersion() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Elana Hashman
					Elana Hashman