mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	kubelet: new kubelet config option for disabling group oom kill
Signed-off-by: utam0k <k0ma@utam0k.jp>
This commit is contained in:
		@@ -606,7 +606,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Warn if MemoryQoS enabled with cgroups v1
 | 
						// Warn if MemoryQoS enabled with cgroups v1
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.MemoryQoS) &&
 | 
						if utilfeature.DefaultFeatureGate.Enabled(features.MemoryQoS) &&
 | 
				
			||||||
		!isCgroup2UnifiedMode() {
 | 
							!kubeletutil.IsCgroup2UnifiedMode() {
 | 
				
			||||||
		klog.InfoS("Warning: MemoryQoS feature only works with cgroups v2 on Linux, but enabled with cgroups v1")
 | 
							klog.InfoS("Warning: MemoryQoS feature only works with cgroups v2 on Linux, but enabled with cgroups v1")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Obtain Kubelet Lock File
 | 
						// Obtain Kubelet Lock File
 | 
				
			||||||
@@ -831,7 +831,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
 | 
				
			|||||||
				s.TopologyManagerPolicyOptions, features.TopologyManagerPolicyOptions)
 | 
									s.TopologyManagerPolicyOptions, features.TopologyManagerPolicyOptions)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if utilfeature.DefaultFeatureGate.Enabled(features.NodeSwap) {
 | 
							if utilfeature.DefaultFeatureGate.Enabled(features.NodeSwap) {
 | 
				
			||||||
			if !isCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == kubelettypes.LimitedSwap {
 | 
								if !kubeletutil.IsCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == kubelettypes.LimitedSwap {
 | 
				
			||||||
				// This feature is not supported for cgroupv1 so we are failing early.
 | 
									// This feature is not supported for cgroupv1 so we are failing early.
 | 
				
			||||||
				return fmt.Errorf("swap feature is enabled and LimitedSwap but it is only supported with cgroupv2")
 | 
									return fmt.Errorf("swap feature is enabled and LimitedSwap but it is only supported with cgroupv2")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,6 @@ package app
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
	"k8s.io/utils/inotify"
 | 
						"k8s.io/utils/inotify"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func watchForLockfileContention(path string, done chan struct{}) error {
 | 
					func watchForLockfileContention(path string, done chan struct{}) error {
 | 
				
			||||||
@@ -46,7 +44,3 @@ func watchForLockfileContention(path string, done chan struct{}) error {
 | 
				
			|||||||
	}()
 | 
						}()
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func isCgroup2UnifiedMode() bool {
 | 
					 | 
				
			||||||
	return libcontainercgroups.IsCgroup2UnifiedMode()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							@@ -61947,6 +61947,13 @@ func schema_k8sio_kubelet_config_v1beta1_KubeletConfiguration(ref common.Referen
 | 
				
			|||||||
							Format:      "",
 | 
												Format:      "",
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
 | 
										"singleProcessOOMKill": {
 | 
				
			||||||
 | 
											SchemaProps: spec.SchemaProps{
 | 
				
			||||||
 | 
												Description: "singleProcessOOMKill, if true, will prevent the `memory.oom.group` flag from being set for container cgroups in cgroups v2. This causes processes in the container to be OOM killed individually instead of as a group. It means that if true, the behavior aligns with the behavior of cgroups v1. The default value is determined automatically when you don't specify. On non-linux such as windows, only null / absent is allowed. On cgroup v1 linux, only null / absent and true are allowed. On cgroup v2 linux, null / absent, true and false are allowed. The default value is false.",
 | 
				
			||||||
 | 
												Type:        []string{"boolean"},
 | 
				
			||||||
 | 
												Format:      "",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
					"cpuManagerPolicyOptions": {
 | 
										"cpuManagerPolicyOptions": {
 | 
				
			||||||
						SchemaProps: spec.SchemaProps{
 | 
											SchemaProps: spec.SchemaProps{
 | 
				
			||||||
							Description: "cpuManagerPolicyOptions is a set of key=value which \tallows to set extra options to fine tune the behaviour of the cpu manager policies. Requires  both the \"CPUManager\" and \"CPUManagerPolicyOptions\" feature gates to be enabled. Default: nil",
 | 
												Description: "cpuManagerPolicyOptions is a set of key=value which \tallows to set extra options to fine tune the behaviour of the cpu manager policies. Requires  both the \"CPUManager\" and \"CPUManagerPolicyOptions\" feature gates to be enabled. Default: nil",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,12 +73,12 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
 | 
				
			|||||||
			obj.NodeStatusReportFrequency = metav1.Duration{Duration: time.Minute}
 | 
								obj.NodeStatusReportFrequency = metav1.Duration{Duration: time.Minute}
 | 
				
			||||||
			obj.NodeLeaseDurationSeconds = 40
 | 
								obj.NodeLeaseDurationSeconds = 40
 | 
				
			||||||
			obj.CPUManagerPolicy = "none"
 | 
								obj.CPUManagerPolicy = "none"
 | 
				
			||||||
			obj.CPUManagerPolicyOptions = make(map[string]string)
 | 
								obj.CPUManagerPolicyOptions = nil
 | 
				
			||||||
			obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency
 | 
								obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency
 | 
				
			||||||
			obj.NodeStatusMaxImages = 50
 | 
								obj.NodeStatusMaxImages = 50
 | 
				
			||||||
			obj.TopologyManagerPolicy = kubeletconfig.NoneTopologyManagerPolicy
 | 
								obj.TopologyManagerPolicy = kubeletconfig.NoneTopologyManagerPolicy
 | 
				
			||||||
			obj.TopologyManagerScope = kubeletconfig.ContainerTopologyManagerScope
 | 
								obj.TopologyManagerScope = kubeletconfig.ContainerTopologyManagerScope
 | 
				
			||||||
			obj.TopologyManagerPolicyOptions = make(map[string]string)
 | 
								obj.TopologyManagerPolicyOptions = nil
 | 
				
			||||||
			obj.QOSReserved = map[string]string{
 | 
								obj.QOSReserved = map[string]string{
 | 
				
			||||||
				"memory": "50%",
 | 
									"memory": "50%",
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -104,13 +104,14 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
 | 
				
			|||||||
			obj.CgroupsPerQOS = true
 | 
								obj.CgroupsPerQOS = true
 | 
				
			||||||
			obj.CgroupDriver = "cgroupfs"
 | 
								obj.CgroupDriver = "cgroupfs"
 | 
				
			||||||
			obj.EnforceNodeAllocatable = kubeletconfigv1beta1.DefaultNodeAllocatableEnforcement
 | 
								obj.EnforceNodeAllocatable = kubeletconfigv1beta1.DefaultNodeAllocatableEnforcement
 | 
				
			||||||
			obj.StaticPodURLHeader = make(map[string][]string)
 | 
								obj.StaticPodURLHeader = nil
 | 
				
			||||||
 | 
								obj.SingleProcessOOMKill = ptr.To(false)
 | 
				
			||||||
			obj.ContainerLogMaxFiles = 5
 | 
								obj.ContainerLogMaxFiles = 5
 | 
				
			||||||
			obj.ContainerLogMaxSize = "10Mi"
 | 
								obj.ContainerLogMaxSize = "10Mi"
 | 
				
			||||||
			obj.ContainerLogMaxWorkers = 1
 | 
								obj.ContainerLogMaxWorkers = 1
 | 
				
			||||||
			obj.ContainerLogMonitorInterval = metav1.Duration{Duration: 10 * time.Second}
 | 
								obj.ContainerLogMonitorInterval = metav1.Duration{Duration: 10 * time.Second}
 | 
				
			||||||
			obj.ConfigMapAndSecretChangeDetectionStrategy = "Watch"
 | 
								obj.ConfigMapAndSecretChangeDetectionStrategy = "Watch"
 | 
				
			||||||
			obj.AllowedUnsafeSysctls = []string{}
 | 
								obj.AllowedUnsafeSysctls = nil
 | 
				
			||||||
			obj.VolumePluginDir = kubeletconfigv1beta1.DefaultVolumePluginDir
 | 
								obj.VolumePluginDir = kubeletconfigv1beta1.DefaultVolumePluginDir
 | 
				
			||||||
			obj.ContainerRuntimeEndpoint = "unix:///run/containerd/containerd.sock"
 | 
								obj.ContainerRuntimeEndpoint = "unix:///run/containerd/containerd.sock"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -233,6 +233,7 @@ var (
 | 
				
			|||||||
		"Logging.Options.Text.OutputRoutingOptions.SplitStream",
 | 
							"Logging.Options.Text.OutputRoutingOptions.SplitStream",
 | 
				
			||||||
		"Logging.VModule[*].FilePattern",
 | 
							"Logging.VModule[*].FilePattern",
 | 
				
			||||||
		"Logging.VModule[*].Verbosity",
 | 
							"Logging.VModule[*].Verbosity",
 | 
				
			||||||
 | 
							"SingleProcessOOMKill",
 | 
				
			||||||
		"Logging.Verbosity",
 | 
							"Logging.Verbosity",
 | 
				
			||||||
		"TLSCipherSuites[*]",
 | 
							"TLSCipherSuites[*]",
 | 
				
			||||||
		"TLSMinVersion",
 | 
							"TLSMinVersion",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -229,6 +229,10 @@ type KubeletConfiguration struct {
 | 
				
			|||||||
	CgroupsPerQOS bool
 | 
						CgroupsPerQOS bool
 | 
				
			||||||
	// driver that the kubelet uses to manipulate cgroups on the host (cgroupfs or systemd)
 | 
						// driver that the kubelet uses to manipulate cgroups on the host (cgroupfs or systemd)
 | 
				
			||||||
	CgroupDriver string
 | 
						CgroupDriver string
 | 
				
			||||||
 | 
						// SingleProcessOOMKill, if true, will prevent the `memory.oom.group` flag from being set for container
 | 
				
			||||||
 | 
						// cgroups in cgroups v2. This causes processes in the container to be OOM killed individually instead of as
 | 
				
			||||||
 | 
						// a group. It means that if true, the behavior aligns with the behavior of cgroups v1.
 | 
				
			||||||
 | 
						SingleProcessOOMKill *bool
 | 
				
			||||||
	// CPUManagerPolicy is the name of the policy to use.
 | 
						// CPUManagerPolicy is the name of the policy to use.
 | 
				
			||||||
	// Requires the CPUManager feature gate to be enabled.
 | 
						// Requires the CPUManager feature gate to be enabled.
 | 
				
			||||||
	CPUManagerPolicy string
 | 
						CPUManagerPolicy string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,6 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
					func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name     string
 | 
							name     string
 | 
				
			||||||
		config   *v1beta1.KubeletConfiguration
 | 
							config   *v1beta1.KubeletConfiguration
 | 
				
			||||||
@@ -130,6 +129,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    DefaultPodLogsDir,
 | 
									PodLogsDir:                    DefaultPodLogsDir,
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -261,6 +261,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                    ptr.To(false),
 | 
									RegisterNode:                    ptr.To(false),
 | 
				
			||||||
				LocalStorageCapacityIsolation:   ptr.To(false),
 | 
									LocalStorageCapacityIsolation:   ptr.To(false),
 | 
				
			||||||
				PodLogsDir:                      "",
 | 
									PodLogsDir:                      "",
 | 
				
			||||||
 | 
									SingleProcessOOMKill:            ptr.To(false),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			&v1beta1.KubeletConfiguration{
 | 
								&v1beta1.KubeletConfiguration{
 | 
				
			||||||
				EnableServer:       ptr.To(false),
 | 
									EnableServer:       ptr.To(false),
 | 
				
			||||||
@@ -363,6 +364,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(false),
 | 
									RegisterNode:                  ptr.To(false),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(false),
 | 
									LocalStorageCapacityIsolation: ptr.To(false),
 | 
				
			||||||
				PodLogsDir:                    DefaultPodLogsDir,
 | 
									PodLogsDir:                    DefaultPodLogsDir,
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          ptr.To(false),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -516,6 +518,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    "/custom/path",
 | 
									PodLogsDir:                    "/custom/path",
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          ptr.To(true),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			&v1beta1.KubeletConfiguration{
 | 
								&v1beta1.KubeletConfiguration{
 | 
				
			||||||
				EnableServer:       ptr.To(true),
 | 
									EnableServer:       ptr.To(true),
 | 
				
			||||||
@@ -666,6 +669,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    "/custom/path",
 | 
									PodLogsDir:                    "/custom/path",
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          ptr.To(true),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -759,6 +763,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    DefaultPodLogsDir,
 | 
									PodLogsDir:                    DefaultPodLogsDir,
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -852,6 +857,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    DefaultPodLogsDir,
 | 
									PodLogsDir:                    DefaultPodLogsDir,
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -945,6 +951,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
				RegisterNode:                  ptr.To(true),
 | 
									RegisterNode:                  ptr.To(true),
 | 
				
			||||||
				LocalStorageCapacityIsolation: ptr.To(true),
 | 
									LocalStorageCapacityIsolation: ptr.To(true),
 | 
				
			||||||
				PodLogsDir:                    DefaultPodLogsDir,
 | 
									PodLogsDir:                    DefaultPodLogsDir,
 | 
				
			||||||
 | 
									SingleProcessOOMKill:          nil,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -409,6 +409,7 @@ func autoConvert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration(in
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	out.CgroupDriver = in.CgroupDriver
 | 
						out.CgroupDriver = in.CgroupDriver
 | 
				
			||||||
	out.CPUManagerPolicy = in.CPUManagerPolicy
 | 
						out.CPUManagerPolicy = in.CPUManagerPolicy
 | 
				
			||||||
 | 
						out.SingleProcessOOMKill = (*bool)(unsafe.Pointer(in.SingleProcessOOMKill))
 | 
				
			||||||
	out.CPUManagerPolicyOptions = *(*map[string]string)(unsafe.Pointer(&in.CPUManagerPolicyOptions))
 | 
						out.CPUManagerPolicyOptions = *(*map[string]string)(unsafe.Pointer(&in.CPUManagerPolicyOptions))
 | 
				
			||||||
	out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod
 | 
						out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod
 | 
				
			||||||
	out.MemoryManagerPolicy = in.MemoryManagerPolicy
 | 
						out.MemoryManagerPolicy = in.MemoryManagerPolicy
 | 
				
			||||||
@@ -606,6 +607,7 @@ func autoConvert_config_KubeletConfiguration_To_v1beta1_KubeletConfiguration(in
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	out.CgroupDriver = in.CgroupDriver
 | 
						out.CgroupDriver = in.CgroupDriver
 | 
				
			||||||
 | 
						out.SingleProcessOOMKill = (*bool)(unsafe.Pointer(in.SingleProcessOOMKill))
 | 
				
			||||||
	out.CPUManagerPolicy = in.CPUManagerPolicy
 | 
						out.CPUManagerPolicy = in.CPUManagerPolicy
 | 
				
			||||||
	out.CPUManagerPolicyOptions = *(*map[string]string)(unsafe.Pointer(&in.CPUManagerPolicyOptions))
 | 
						out.CPUManagerPolicyOptions = *(*map[string]string)(unsafe.Pointer(&in.CPUManagerPolicyOptions))
 | 
				
			||||||
	out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod
 | 
						out.CPUManagerReconcilePeriod = in.CPUManagerReconcilePeriod
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,13 +24,19 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
						libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
						kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
				
			||||||
 | 
						"k8s.io/utils/ptr"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
 | 
					// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
 | 
				
			||||||
func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
 | 
					func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
 | 
				
			||||||
	if kc.FailCgroupV1 && !libcontainercgroups.IsCgroup2UnifiedMode() {
 | 
						isCgroup1 := !libcontainercgroups.IsCgroup2UnifiedMode()
 | 
				
			||||||
 | 
						if kc.FailCgroupV1 && isCgroup1 {
 | 
				
			||||||
		return fmt.Errorf("kubelet is configured to not run on a host using cgroup v1. cgroup v1 support is in maintenance mode")
 | 
							return fmt.Errorf("kubelet is configured to not run on a host using cgroup v1. cgroup v1 support is in maintenance mode")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isCgroup1 && kc.SingleProcessOOMKill != nil && !ptr.Deref(kc.SingleProcessOOMKill, true) {
 | 
				
			||||||
 | 
							return fmt.Errorf("invalid configuration: singleProcessOOMKill must not be explicitly set to false when using cgroup v1")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,10 +20,16 @@ limitations under the License.
 | 
				
			|||||||
package validation
 | 
					package validation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
						kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
 | 
					// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
 | 
				
			||||||
func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
 | 
					func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
 | 
				
			||||||
 | 
						if kc.SingleProcessOOMKill != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("invalid configuration: singleProcessOOMKill is only supported on linux")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ import (
 | 
				
			|||||||
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
						kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubelet/apis/config/validation"
 | 
						"k8s.io/kubernetes/pkg/kubelet/apis/config/validation"
 | 
				
			||||||
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
						kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
				
			||||||
 | 
						kubeletutil "k8s.io/kubernetes/pkg/kubelet/util"
 | 
				
			||||||
	"k8s.io/utils/ptr"
 | 
						"k8s.io/utils/ptr"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -78,6 +79,7 @@ var (
 | 
				
			|||||||
		ContainerRuntimeEndpoint:    "unix:///run/containerd/containerd.sock",
 | 
							ContainerRuntimeEndpoint:    "unix:///run/containerd/containerd.sock",
 | 
				
			||||||
		ContainerLogMaxWorkers:      1,
 | 
							ContainerLogMaxWorkers:      1,
 | 
				
			||||||
		ContainerLogMonitorInterval: metav1.Duration{Duration: 10 * time.Second},
 | 
							ContainerLogMonitorInterval: metav1.Duration{Duration: 10 * time.Second},
 | 
				
			||||||
 | 
							SingleProcessOOMKill:        ptr.To(!kubeletutil.IsCgroup2UnifiedMode()),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,9 +20,10 @@ limitations under the License.
 | 
				
			|||||||
package validation
 | 
					package validation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
						kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 | 
				
			||||||
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
						kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
				
			||||||
@@ -36,6 +37,10 @@ func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) erro
 | 
				
			|||||||
		klog.Warningf(message, "CgroupsPerQOS", "--cgroups-per-qos", kc.CgroupsPerQOS)
 | 
							klog.Warningf(message, "CgroupsPerQOS", "--cgroups-per-qos", kc.CgroupsPerQOS)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if kc.SingleProcessOOMKill != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("invalid configuration: singleProcessOOMKill is not supported on Windows")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enforceNodeAllocatableWithoutNone := sets.New(kc.EnforceNodeAllocatable...).Delete(kubetypes.NodeAllocatableNoneKey)
 | 
						enforceNodeAllocatableWithoutNone := sets.New(kc.EnforceNodeAllocatable...).Delete(kubetypes.NodeAllocatableNoneKey)
 | 
				
			||||||
	if len(enforceNodeAllocatableWithoutNone) > 0 {
 | 
						if len(enforceNodeAllocatableWithoutNone) > 0 {
 | 
				
			||||||
		klog.Warningf(message, "EnforceNodeAllocatable", "--enforce-node-allocatable", kc.EnforceNodeAllocatable)
 | 
							klog.Warningf(message, "EnforceNodeAllocatable", "--enforce-node-allocatable", kc.EnforceNodeAllocatable)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								pkg/kubelet/apis/config/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								pkg/kubelet/apis/config/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							@@ -204,6 +204,11 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
 | 
				
			|||||||
	out.ImageMinimumGCAge = in.ImageMinimumGCAge
 | 
						out.ImageMinimumGCAge = in.ImageMinimumGCAge
 | 
				
			||||||
	out.ImageMaximumGCAge = in.ImageMaximumGCAge
 | 
						out.ImageMaximumGCAge = in.ImageMaximumGCAge
 | 
				
			||||||
	out.VolumeStatsAggPeriod = in.VolumeStatsAggPeriod
 | 
						out.VolumeStatsAggPeriod = in.VolumeStatsAggPeriod
 | 
				
			||||||
 | 
						if in.SingleProcessOOMKill != nil {
 | 
				
			||||||
 | 
							in, out := &in.SingleProcessOOMKill, &out.SingleProcessOOMKill
 | 
				
			||||||
 | 
							*out = new(bool)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if in.CPUManagerPolicyOptions != nil {
 | 
						if in.CPUManagerPolicyOptions != nil {
 | 
				
			||||||
		in, out := &in.CPUManagerPolicyOptions, &out.CPUManagerPolicyOptions
 | 
							in, out := &in.CPUManagerPolicyOptions, &out.CPUManagerPolicyOptions
 | 
				
			||||||
		*out = make(map[string]string, len(*in))
 | 
							*out = make(map[string]string, len(*in))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@ import (
 | 
				
			|||||||
	v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
						v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
				
			||||||
	utilfs "k8s.io/kubernetes/pkg/util/filesystem"
 | 
						utilfs "k8s.io/kubernetes/pkg/util/filesystem"
 | 
				
			||||||
	netutils "k8s.io/utils/net"
 | 
						netutils "k8s.io/utils/net"
 | 
				
			||||||
 | 
						"k8s.io/utils/ptr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inuserns "github.com/moby/sys/userns"
 | 
						inuserns "github.com/moby/sys/userns"
 | 
				
			||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
@@ -661,6 +662,20 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
 | 
				
			|||||||
		klet.podCache,
 | 
							klet.podCache,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var singleProcessOOMKill *bool
 | 
				
			||||||
 | 
						if sysruntime.GOOS == "linux" {
 | 
				
			||||||
 | 
							if !util.IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
								// This is a default behavior for cgroups v1.
 | 
				
			||||||
 | 
								singleProcessOOMKill = ptr.To(true)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if kubeCfg.SingleProcessOOMKill == nil {
 | 
				
			||||||
 | 
									singleProcessOOMKill = ptr.To(false)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									singleProcessOOMKill = kubeCfg.SingleProcessOOMKill
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	runtime, err := kuberuntime.NewKubeGenericRuntimeManager(
 | 
						runtime, err := kuberuntime.NewKubeGenericRuntimeManager(
 | 
				
			||||||
		kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
 | 
							kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
 | 
				
			||||||
		klet.livenessManager,
 | 
							klet.livenessManager,
 | 
				
			||||||
@@ -680,6 +695,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
 | 
				
			|||||||
		int(kubeCfg.RegistryBurst),
 | 
							int(kubeCfg.RegistryBurst),
 | 
				
			||||||
		imageCredentialProviderConfigFile,
 | 
							imageCredentialProviderConfigFile,
 | 
				
			||||||
		imageCredentialProviderBinDir,
 | 
							imageCredentialProviderBinDir,
 | 
				
			||||||
 | 
							singleProcessOOMKill,
 | 
				
			||||||
		kubeCfg.CPUCFSQuota,
 | 
							kubeCfg.CPUCFSQuota,
 | 
				
			||||||
		kubeCfg.CPUCFSQuotaPeriod,
 | 
							kubeCfg.CPUCFSQuotaPeriod,
 | 
				
			||||||
		kubeDeps.RemoteRuntimeService,
 | 
							kubeDeps.RemoteRuntimeService,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3225,6 +3225,7 @@ func TestSyncPodSpans(t *testing.T) {
 | 
				
			|||||||
		int(kubeCfg.RegistryBurst),
 | 
							int(kubeCfg.RegistryBurst),
 | 
				
			||||||
		"",
 | 
							"",
 | 
				
			||||||
		"",
 | 
							"",
 | 
				
			||||||
 | 
							nil,
 | 
				
			||||||
		kubeCfg.CPUCFSQuota,
 | 
							kubeCfg.CPUCFSQuota,
 | 
				
			||||||
		kubeCfg.CPUCFSQuotaPeriod,
 | 
							kubeCfg.CPUCFSQuotaPeriod,
 | 
				
			||||||
		runtimeSvc,
 | 
							runtimeSvc,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,7 @@ import (
 | 
				
			|||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
						runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
 | 
						v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
 | 
				
			||||||
	kubeapiqos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
						kubeapiqos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
				
			||||||
	kubefeatures "k8s.io/kubernetes/pkg/features"
 | 
						kubefeatures "k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
@@ -45,6 +46,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/kubelet/qos"
 | 
						"k8s.io/kubernetes/pkg/kubelet/qos"
 | 
				
			||||||
	kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
						kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
				
			||||||
	cgroups "k8s.io/kubernetes/third_party/forked/cgroups"
 | 
						cgroups "k8s.io/kubernetes/third_party/forked/cgroups"
 | 
				
			||||||
 | 
						"k8s.io/utils/ptr"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var defaultPageSize = int64(os.Getpagesize())
 | 
					var defaultPageSize = int64(os.Getpagesize())
 | 
				
			||||||
@@ -247,7 +249,7 @@ func (m *kubeGenericRuntimeManager) calculateLinuxResources(cpuRequest, cpuLimit
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// runc requires cgroupv2 for unified mode
 | 
						// runc requires cgroupv2 for unified mode
 | 
				
			||||||
	if isCgroup2UnifiedMode() {
 | 
						if isCgroup2UnifiedMode() && !ptr.Deref(m.singleProcessOOMKill, true) {
 | 
				
			||||||
		resources.Unified = map[string]string{
 | 
							resources.Unified = map[string]string{
 | 
				
			||||||
			// Ask the kernel to kill all processes in the container cgroup in case of OOM.
 | 
								// Ask the kernel to kill all processes in the container cgroup in case of OOM.
 | 
				
			||||||
			// See memory.oom.group in https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html for
 | 
								// See memory.oom.group in https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html for
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -255,6 +255,7 @@ func TestCalculateLinuxResources(t *testing.T) {
 | 
				
			|||||||
		memLim               *resource.Quantity
 | 
							memLim               *resource.Quantity
 | 
				
			||||||
		expected             *runtimeapi.LinuxContainerResources
 | 
							expected             *runtimeapi.LinuxContainerResources
 | 
				
			||||||
		cgroupVersion        CgroupVersion
 | 
							cgroupVersion        CgroupVersion
 | 
				
			||||||
 | 
							singleProcessOOMKill bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "Request128MBLimit256MB",
 | 
								name:   "Request128MBLimit256MB",
 | 
				
			||||||
@@ -321,6 +322,20 @@ func TestCalculateLinuxResources(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			cgroupVersion: cgroupV2,
 | 
								cgroupVersion: cgroupV2,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:   "Request128MBLimit256MBSingleProcess",
 | 
				
			||||||
 | 
								cpuReq: generateResourceQuantity("1"),
 | 
				
			||||||
 | 
								cpuLim: generateResourceQuantity("2"),
 | 
				
			||||||
 | 
								memLim: generateResourceQuantity("128Mi"),
 | 
				
			||||||
 | 
								expected: &runtimeapi.LinuxContainerResources{
 | 
				
			||||||
 | 
									CpuPeriod:          100000,
 | 
				
			||||||
 | 
									CpuQuota:           200000,
 | 
				
			||||||
 | 
									CpuShares:          1024,
 | 
				
			||||||
 | 
									MemoryLimitInBytes: 134217728,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								cgroupVersion:        cgroupV2,
 | 
				
			||||||
 | 
								singleProcessOOMKill: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "RequestNoMemory",
 | 
								name:   "RequestNoMemory",
 | 
				
			||||||
			cpuReq: generateResourceQuantity("2"),
 | 
								cpuReq: generateResourceQuantity("2"),
 | 
				
			||||||
@@ -365,6 +380,7 @@ func TestCalculateLinuxResources(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		setCgroupVersionDuringTest(test.cgroupVersion)
 | 
							setCgroupVersionDuringTest(test.cgroupVersion)
 | 
				
			||||||
 | 
							m.singleProcessOOMKill = ptr.To(test.singleProcessOOMKill)
 | 
				
			||||||
		linuxContainerResources := m.calculateLinuxResources(test.cpuReq, test.cpuLim, test.memLim)
 | 
							linuxContainerResources := m.calculateLinuxResources(test.cpuReq, test.cpuLim, test.memLim)
 | 
				
			||||||
		assert.Equal(t, test.expected, linuxContainerResources)
 | 
							assert.Equal(t, test.expected, linuxContainerResources)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -811,6 +827,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
		name                 string
 | 
							name                 string
 | 
				
			||||||
		limits               v1.ResourceList
 | 
							limits               v1.ResourceList
 | 
				
			||||||
		requests             v1.ResourceList
 | 
							requests             v1.ResourceList
 | 
				
			||||||
 | 
							singleProcessOOMKill bool
 | 
				
			||||||
		expected             *runtimeapi.LinuxContainerResources
 | 
							expected             *runtimeapi.LinuxContainerResources
 | 
				
			||||||
		cgroupVersion        CgroupVersion
 | 
							cgroupVersion        CgroupVersion
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
@@ -818,6 +835,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"requests & limits, cpu & memory, guaranteed qos",
 | 
								"requests & limits, cpu & memory, guaranteed qos",
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 524288000, OomScoreAdj: -997},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 524288000, OomScoreAdj: -997},
 | 
				
			||||||
			cgroupV1,
 | 
								cgroupV1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -825,6 +843,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"requests & limits, cpu & memory, burstable qos",
 | 
								"requests & limits, cpu & memory, burstable qos",
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("750Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("750Mi")},
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 786432000, OomScoreAdj: 970},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 786432000, OomScoreAdj: 970},
 | 
				
			||||||
			cgroupV1,
 | 
								cgroupV1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -832,6 +851,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"best-effort qos",
 | 
								"best-effort qos",
 | 
				
			||||||
			nil,
 | 
								nil,
 | 
				
			||||||
			nil,
 | 
								nil,
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 2, OomScoreAdj: 1000},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 2, OomScoreAdj: 1000},
 | 
				
			||||||
			cgroupV1,
 | 
								cgroupV1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -839,6 +859,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"requests & limits, cpu & memory, guaranteed qos",
 | 
								"requests & limits, cpu & memory, guaranteed qos",
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 524288000, OomScoreAdj: -997, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 524288000, OomScoreAdj: -997, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
				
			||||||
			cgroupV2,
 | 
								cgroupV2,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -846,6 +867,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"requests & limits, cpu & memory, burstable qos",
 | 
								"requests & limits, cpu & memory, burstable qos",
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("750Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("500m"), v1.ResourceMemory: resource.MustParse("750Mi")},
 | 
				
			||||||
			v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
								v1.ResourceList{v1.ResourceCPU: resource.MustParse("250m"), v1.ResourceMemory: resource.MustParse("500Mi")},
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 786432000, OomScoreAdj: 970, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 256, MemoryLimitInBytes: 786432000, OomScoreAdj: 970, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
				
			||||||
			cgroupV2,
 | 
								cgroupV2,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -853,6 +875,7 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
			"best-effort qos",
 | 
								"best-effort qos",
 | 
				
			||||||
			nil,
 | 
								nil,
 | 
				
			||||||
			nil,
 | 
								nil,
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
			&runtimeapi.LinuxContainerResources{CpuShares: 2, OomScoreAdj: 1000, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
								&runtimeapi.LinuxContainerResources{CpuShares: 2, OomScoreAdj: 1000, Unified: map[string]string{"memory.oom.group": "1"}},
 | 
				
			||||||
			cgroupV2,
 | 
								cgroupV2,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -863,6 +886,8 @@ func TestGenerateLinuxContainerResources(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			pod.Spec.Containers[0].Resources = v1.ResourceRequirements{Limits: tc.limits, Requests: tc.requests}
 | 
								pod.Spec.Containers[0].Resources = v1.ResourceRequirements{Limits: tc.limits, Requests: tc.requests}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								m.singleProcessOOMKill = ptr.To(tc.singleProcessOOMKill)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			resources := m.generateLinuxContainerResources(pod, &pod.Spec.Containers[0], false)
 | 
								resources := m.generateLinuxContainerResources(pod, &pod.Spec.Containers[0], false)
 | 
				
			||||||
			tc.expected.HugepageLimits = resources.HugepageLimits
 | 
								tc.expected.HugepageLimits = resources.HugepageLimits
 | 
				
			||||||
			assert.Equal(t, tc.expected, resources)
 | 
								assert.Equal(t, tc.expected, resources)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,11 @@ type kubeGenericRuntimeManager struct {
 | 
				
			|||||||
	readinessManager proberesults.Manager
 | 
						readinessManager proberesults.Manager
 | 
				
			||||||
	startupManager   proberesults.Manager
 | 
						startupManager   proberesults.Manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If false, pass "memory.oom.group" to container cgroups when using cgroups v2 to cause processes
 | 
				
			||||||
 | 
						// in those cgroups to be killed as a unit by the OOM killer.
 | 
				
			||||||
 | 
						// It must be nil except for linux
 | 
				
			||||||
 | 
						singleProcessOOMKill *bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If true, enforce container cpu limits with CFS quota support
 | 
						// If true, enforce container cpu limits with CFS quota support
 | 
				
			||||||
	cpuCFSQuota bool
 | 
						cpuCFSQuota bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -198,6 +203,7 @@ func NewKubeGenericRuntimeManager(
 | 
				
			|||||||
	imagePullBurst int,
 | 
						imagePullBurst int,
 | 
				
			||||||
	imageCredentialProviderConfigFile string,
 | 
						imageCredentialProviderConfigFile string,
 | 
				
			||||||
	imageCredentialProviderBinDir string,
 | 
						imageCredentialProviderBinDir string,
 | 
				
			||||||
 | 
						singleProcessOOMKill *bool,
 | 
				
			||||||
	cpuCFSQuota bool,
 | 
						cpuCFSQuota bool,
 | 
				
			||||||
	cpuCFSQuotaPeriod metav1.Duration,
 | 
						cpuCFSQuotaPeriod metav1.Duration,
 | 
				
			||||||
	runtimeService internalapi.RuntimeService,
 | 
						runtimeService internalapi.RuntimeService,
 | 
				
			||||||
@@ -218,6 +224,7 @@ func NewKubeGenericRuntimeManager(
 | 
				
			|||||||
	tracer := tracerProvider.Tracer(instrumentationScope)
 | 
						tracer := tracerProvider.Tracer(instrumentationScope)
 | 
				
			||||||
	kubeRuntimeManager := &kubeGenericRuntimeManager{
 | 
						kubeRuntimeManager := &kubeGenericRuntimeManager{
 | 
				
			||||||
		recorder:               recorder,
 | 
							recorder:               recorder,
 | 
				
			||||||
 | 
							singleProcessOOMKill:   singleProcessOOMKill,
 | 
				
			||||||
		cpuCFSQuota:            cpuCFSQuota,
 | 
							cpuCFSQuota:            cpuCFSQuota,
 | 
				
			||||||
		cpuCFSQuotaPeriod:      cpuCFSQuotaPeriod,
 | 
							cpuCFSQuotaPeriod:      cpuCFSQuotaPeriod,
 | 
				
			||||||
		seccompProfileRoot:     filepath.Join(rootDirectory, "seccomp"),
 | 
							seccompProfileRoot:     filepath.Join(rootDirectory, "seccomp"),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,11 +28,13 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
						"k8s.io/apimachinery/pkg/api/resource"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
						runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
				
			||||||
 | 
						"k8s.io/utils/ptr"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestApplySandboxResources(t *testing.T) {
 | 
					func TestApplySandboxResources(t *testing.T) {
 | 
				
			||||||
	_, _, m, err := createTestRuntimeManager()
 | 
						_, _, m, err := createTestRuntimeManager()
 | 
				
			||||||
	m.cpuCFSQuota = true
 | 
						m.cpuCFSQuota = true
 | 
				
			||||||
 | 
						m.singleProcessOOMKill = ptr.To(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config := &runtimeapi.PodSandboxConfig{
 | 
						config := &runtimeapi.PodSandboxConfig{
 | 
				
			||||||
		Linux: &runtimeapi.LinuxPodSandboxConfig{},
 | 
							Linux: &runtimeapi.LinuxPodSandboxConfig{},
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								pkg/kubelet/util/util_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								pkg/kubelet/util/util_linux.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					//go:build linux
 | 
				
			||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsCgroup2UnifiedMode returns true if the cgroup v2 unified mode is enabled
 | 
				
			||||||
 | 
					func IsCgroup2UnifiedMode() bool {
 | 
				
			||||||
 | 
						return libcontainercgroups.IsCgroup2UnifiedMode()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								pkg/kubelet/util/util_others.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								pkg/kubelet/util/util_others.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					//go:build !linux && !windows
 | 
				
			||||||
 | 
					// +build !linux,!windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsCgroup2UnifiedMode is a no-op for other OSes.
 | 
				
			||||||
 | 
					func IsCgroup2UnifiedMode() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -73,3 +73,8 @@ func NormalizePath(path string) string {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return path
 | 
						return path
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsCgroup2UnifiedMode is a no-op for Windows for now
 | 
				
			||||||
 | 
					func IsCgroup2UnifiedMode() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -354,6 +354,15 @@ type KubeletConfiguration struct {
 | 
				
			|||||||
	// Default: "None"
 | 
						// Default: "None"
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	CPUManagerPolicy string `json:"cpuManagerPolicy,omitempty"`
 | 
						CPUManagerPolicy string `json:"cpuManagerPolicy,omitempty"`
 | 
				
			||||||
 | 
						// singleProcessOOMKill, if true, will prevent the `memory.oom.group` flag from being set for container
 | 
				
			||||||
 | 
						// cgroups in cgroups v2. This causes processes in the container to be OOM killed individually instead of as
 | 
				
			||||||
 | 
						// a group. It means that if true, the behavior aligns with the behavior of cgroups v1.
 | 
				
			||||||
 | 
						// The default value is determined automatically when you don't specify.
 | 
				
			||||||
 | 
						// On non-linux such as windows, only null / absent is allowed.
 | 
				
			||||||
 | 
						// On cgroup v1 linux, only null / absent and true are allowed.
 | 
				
			||||||
 | 
						// On cgroup v2 linux, null / absent, true and false are allowed. The default value is false.
 | 
				
			||||||
 | 
						// +optional
 | 
				
			||||||
 | 
						SingleProcessOOMKill *bool `json:"singleProcessOOMKill,omitempty"`
 | 
				
			||||||
	// cpuManagerPolicyOptions is a set of key=value which 	allows to set extra options
 | 
						// cpuManagerPolicyOptions is a set of key=value which 	allows to set extra options
 | 
				
			||||||
	// to fine tune the behaviour of the cpu manager policies.
 | 
						// to fine tune the behaviour of the cpu manager policies.
 | 
				
			||||||
	// Requires  both the "CPUManager" and "CPUManagerPolicyOptions" feature gates to be enabled.
 | 
						// Requires  both the "CPUManager" and "CPUManagerPolicyOptions" feature gates to be enabled.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -254,6 +254,11 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
 | 
				
			|||||||
		*out = new(bool)
 | 
							*out = new(bool)
 | 
				
			||||||
		**out = **in
 | 
							**out = **in
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if in.SingleProcessOOMKill != nil {
 | 
				
			||||||
 | 
							in, out := &in.SingleProcessOOMKill, &out.SingleProcessOOMKill
 | 
				
			||||||
 | 
							*out = new(bool)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if in.CPUManagerPolicyOptions != nil {
 | 
						if in.CPUManagerPolicyOptions != nil {
 | 
				
			||||||
		in, out := &in.CPUManagerPolicyOptions, &out.CPUManagerPolicyOptions
 | 
							in, out := &in.CPUManagerPolicyOptions, &out.CPUManagerPolicyOptions
 | 
				
			||||||
		*out = make(map[string]string, len(*in))
 | 
							*out = make(map[string]string, len(*in))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package e2enode
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/onsi/gomega"
 | 
						"github.com/onsi/gomega"
 | 
				
			||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
@@ -38,6 +39,8 @@ type testCase struct {
 | 
				
			|||||||
	name                    string
 | 
						name                    string
 | 
				
			||||||
	podSpec                 *v1.Pod
 | 
						podSpec                 *v1.Pod
 | 
				
			||||||
	oomTargetContainerName  string
 | 
						oomTargetContainerName  string
 | 
				
			||||||
 | 
						enableSingleProcessKill *bool
 | 
				
			||||||
 | 
						expectPodRunning        bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// KubeReservedMemory is default fraction value of node capacity memory to
 | 
					// KubeReservedMemory is default fraction value of node capacity memory to
 | 
				
			||||||
@@ -62,7 +65,7 @@ var _ = SIGDescribe("OOMKiller for pod using more memory than node allocatable [
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ = SIGDescribe("OOMKiller [LinuxOnly]", framework.WithNodeConformance(), func() {
 | 
					var _ = SIGDescribe("OOMKiller [LinuxOnly]", framework.WithNodeConformance(), framework.WithSerial(), func() {
 | 
				
			||||||
	f := framework.NewDefaultFramework("oomkiller-test")
 | 
						f := framework.NewDefaultFramework("oomkiller-test")
 | 
				
			||||||
	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
 | 
						f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,6 +92,24 @@ var _ = SIGDescribe("OOMKiller [LinuxOnly]", framework.WithNodeConformance(), fu
 | 
				
			|||||||
			oomTargetContainerName: "oomkill-multi-target-container",
 | 
								oomTargetContainerName: "oomkill-multi-target-container",
 | 
				
			||||||
			podSpec: getOOMTargetPod("oomkill-target-pod", "oomkill-multi-target-container",
 | 
								podSpec: getOOMTargetPod("oomkill-target-pod", "oomkill-multi-target-container",
 | 
				
			||||||
				getOOMTargetContainerMultiProcess),
 | 
									getOOMTargetContainerMultiProcess),
 | 
				
			||||||
 | 
								enableSingleProcessKill: nil,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							testCases = append(testCases, testCase{
 | 
				
			||||||
 | 
								name:                   "multi process container (single process kill enabled)",
 | 
				
			||||||
 | 
								oomTargetContainerName: "oomkill-multi-target-container",
 | 
				
			||||||
 | 
								podSpec: getOOMTargetPod("oomkill-target-pod", "oomkill-multi-target-container",
 | 
				
			||||||
 | 
									getOOMTargetContainerMultiProcess),
 | 
				
			||||||
 | 
								enableSingleProcessKill: ptr.To(true),
 | 
				
			||||||
 | 
								expectPodRunning:        true,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							testCases = append(testCases, testCase{
 | 
				
			||||||
 | 
								name:                   "multi process container (single process kill disabled)",
 | 
				
			||||||
 | 
								oomTargetContainerName: "oomkill-multi-target-container",
 | 
				
			||||||
 | 
								podSpec: getOOMTargetPod("oomkill-target-pod", "oomkill-multi-target-container",
 | 
				
			||||||
 | 
									getOOMTargetContainerMultiProcess),
 | 
				
			||||||
 | 
								enableSingleProcessKill: ptr.To(false),
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
@@ -99,8 +120,8 @@ var _ = SIGDescribe("OOMKiller [LinuxOnly]", framework.WithNodeConformance(), fu
 | 
				
			|||||||
func runOomKillerTest(f *framework.Framework, testCase testCase, kubeReservedMemory float64) {
 | 
					func runOomKillerTest(f *framework.Framework, testCase testCase, kubeReservedMemory float64) {
 | 
				
			||||||
	ginkgo.Context(testCase.name, func() {
 | 
						ginkgo.Context(testCase.name, func() {
 | 
				
			||||||
		// Update KubeReservedMemory in KubeletConfig.
 | 
							// Update KubeReservedMemory in KubeletConfig.
 | 
				
			||||||
		if kubeReservedMemory > 0 {
 | 
					 | 
				
			||||||
		tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) {
 | 
							tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) {
 | 
				
			||||||
 | 
								if kubeReservedMemory > 0 {
 | 
				
			||||||
				if initialConfig.KubeReserved == nil {
 | 
									if initialConfig.KubeReserved == nil {
 | 
				
			||||||
					initialConfig.KubeReserved = map[string]string{}
 | 
										initialConfig.KubeReserved = map[string]string{}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -109,9 +130,11 @@ func runOomKillerTest(f *framework.Framework, testCase testCase, kubeReservedMem
 | 
				
			|||||||
				// K8s components such that node allocatable memory is less than node capacity to
 | 
									// K8s components such that node allocatable memory is less than node capacity to
 | 
				
			||||||
				// observe OOM kills at cgroup level instead of system OOM kills.
 | 
									// observe OOM kills at cgroup level instead of system OOM kills.
 | 
				
			||||||
				initialConfig.KubeReserved["memory"] = fmt.Sprintf("%d", int(kubeReservedMemory*getLocalNode(context.TODO(), f).Status.Capacity.Memory().AsApproximateFloat64()))
 | 
									initialConfig.KubeReserved["memory"] = fmt.Sprintf("%d", int(kubeReservedMemory*getLocalNode(context.TODO(), f).Status.Capacity.Memory().AsApproximateFloat64()))
 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								initialConfig.SingleProcessOOMKill = testCase.enableSingleProcessKill
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.BeforeEach(func() {
 | 
							ginkgo.BeforeEach(func() {
 | 
				
			||||||
			// Precautionary check that kubelet is healthy before running the test.
 | 
								// Precautionary check that kubelet is healthy before running the test.
 | 
				
			||||||
			waitForKubeletToStart(context.TODO(), f)
 | 
								waitForKubeletToStart(context.TODO(), f)
 | 
				
			||||||
@@ -120,6 +143,24 @@ func runOomKillerTest(f *framework.Framework, testCase testCase, kubeReservedMem
 | 
				
			|||||||
			e2epod.NewPodClient(f).Create(context.TODO(), testCase.podSpec)
 | 
								e2epod.NewPodClient(f).Create(context.TODO(), testCase.podSpec)
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if testCase.expectPodRunning {
 | 
				
			||||||
 | 
								ginkgo.It("The containers should not be OOMKilled", func() {
 | 
				
			||||||
 | 
									err := e2epod.WaitForPodsRunning(context.TODO(), f.ClientSet, f.Namespace.Name, 1, framework.PodStartTimeout)
 | 
				
			||||||
 | 
									framework.ExpectNoError(err, "Failed waiting for pod to be running state, %s/%s", f.Namespace.Name, testCase.podSpec.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									gomega.Consistently(context.TODO(), func(ctx context.Context) error {
 | 
				
			||||||
 | 
										pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(ctx, testCase.podSpec.Name, metav1.GetOptions{})
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return fmt.Errorf("expected the pod %s to exist: %w", pod.Name, err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										phase := pod.Status.Phase
 | 
				
			||||||
 | 
										if phase != v1.PodRunning && phase != v1.PodSucceeded {
 | 
				
			||||||
 | 
											return fmt.Errorf("pod %s: unexpected status %s, expected status: %s or %s", pod.Name, pod.Status.Phase, v1.PodRunning, v1.PodSucceeded)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return nil
 | 
				
			||||||
 | 
									}, 10*time.Second, f.Timeouts.Poll).Should(gomega.BeNil())
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			ginkgo.It("The containers terminated by OOM killer should have the reason set to OOMKilled", func() {
 | 
								ginkgo.It("The containers terminated by OOM killer should have the reason set to OOMKilled", func() {
 | 
				
			||||||
				ginkgo.By("Waiting for the pod to be failed")
 | 
									ginkgo.By("Waiting for the pod to be failed")
 | 
				
			||||||
				err := e2epod.WaitForPodTerminatedInNamespace(context.TODO(), f.ClientSet, testCase.podSpec.Name, "", f.Namespace.Name)
 | 
									err := e2epod.WaitForPodTerminatedInNamespace(context.TODO(), f.ClientSet, testCase.podSpec.Name, "", f.Namespace.Name)
 | 
				
			||||||
@@ -132,6 +173,7 @@ func runOomKillerTest(f *framework.Framework, testCase testCase, kubeReservedMem
 | 
				
			|||||||
				ginkgo.By("Verifying the OOM target container has the expected reason")
 | 
									ginkgo.By("Verifying the OOM target container has the expected reason")
 | 
				
			||||||
				verifyReasonForOOMKilledContainer(pod, testCase.oomTargetContainerName)
 | 
									verifyReasonForOOMKilledContainer(pod, testCase.oomTargetContainerName)
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ginkgo.AfterEach(func() {
 | 
							ginkgo.AfterEach(func() {
 | 
				
			||||||
			ginkgo.By(fmt.Sprintf("deleting pod: %s", testCase.podSpec.Name))
 | 
								ginkgo.By(fmt.Sprintf("deleting pod: %s", testCase.podSpec.Name))
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user