Skip to content

Commit c462d4c

Browse files
authored
Merge pull request kubernetes#126096 from utam0k/support-disabling-oom-group-kill
kubelet: new kubelet config option for disabling group oom kill
2 parents 3b69780 + 4f909c1 commit c462d4c

25 files changed

+253
-45
lines changed

cmd/kubelet/app/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
606606

607607
// Warn if MemoryQoS enabled with cgroups v1
608608
if utilfeature.DefaultFeatureGate.Enabled(features.MemoryQoS) &&
609-
!isCgroup2UnifiedMode() {
609+
!kubeletutil.IsCgroup2UnifiedMode() {
610610
klog.InfoS("Warning: MemoryQoS feature only works with cgroups v2 on Linux, but enabled with cgroups v1")
611611
}
612612
// Obtain Kubelet Lock File
@@ -831,7 +831,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
831831
s.TopologyManagerPolicyOptions, features.TopologyManagerPolicyOptions)
832832
}
833833
if utilfeature.DefaultFeatureGate.Enabled(features.NodeSwap) {
834-
if !isCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == kubelettypes.LimitedSwap {
834+
if !kubeletutil.IsCgroup2UnifiedMode() && s.MemorySwap.SwapBehavior == kubelettypes.LimitedSwap {
835835
// This feature is not supported for cgroupv1 so we are failing early.
836836
return fmt.Errorf("swap feature is enabled and LimitedSwap but it is only supported with cgroupv2")
837837
}

cmd/kubelet/app/server_linux.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ package app
1919
import (
2020
"k8s.io/klog/v2"
2121
"k8s.io/utils/inotify"
22-
23-
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
2422
)
2523

2624
func watchForLockfileContention(path string, done chan struct{}) error {
@@ -46,7 +44,3 @@ func watchForLockfileContention(path string, done chan struct{}) error {
4644
}()
4745
return nil
4846
}
49-
50-
func isCgroup2UnifiedMode() bool {
51-
return libcontainercgroups.IsCgroup2UnifiedMode()
52-
}

pkg/generated/openapi/zz_generated.openapi.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/kubelet/apis/config/fuzzer/fuzzer.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
7373
obj.NodeStatusReportFrequency = metav1.Duration{Duration: time.Minute}
7474
obj.NodeLeaseDurationSeconds = 40
7575
obj.CPUManagerPolicy = "none"
76-
obj.CPUManagerPolicyOptions = make(map[string]string)
76+
obj.CPUManagerPolicyOptions = nil
7777
obj.CPUManagerReconcilePeriod = obj.NodeStatusUpdateFrequency
7878
obj.NodeStatusMaxImages = 50
7979
obj.TopologyManagerPolicy = kubeletconfig.NoneTopologyManagerPolicy
8080
obj.TopologyManagerScope = kubeletconfig.ContainerTopologyManagerScope
81-
obj.TopologyManagerPolicyOptions = make(map[string]string)
81+
obj.TopologyManagerPolicyOptions = nil
8282
obj.QOSReserved = map[string]string{
8383
"memory": "50%",
8484
}
@@ -104,13 +104,14 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
104104
obj.CgroupsPerQOS = true
105105
obj.CgroupDriver = "cgroupfs"
106106
obj.EnforceNodeAllocatable = kubeletconfigv1beta1.DefaultNodeAllocatableEnforcement
107-
obj.StaticPodURLHeader = make(map[string][]string)
107+
obj.StaticPodURLHeader = nil
108+
obj.SingleProcessOOMKill = ptr.To(false)
108109
obj.ContainerLogMaxFiles = 5
109110
obj.ContainerLogMaxSize = "10Mi"
110111
obj.ContainerLogMaxWorkers = 1
111112
obj.ContainerLogMonitorInterval = metav1.Duration{Duration: 10 * time.Second}
112113
obj.ConfigMapAndSecretChangeDetectionStrategy = "Watch"
113-
obj.AllowedUnsafeSysctls = []string{}
114+
obj.AllowedUnsafeSysctls = nil
114115
obj.VolumePluginDir = kubeletconfigv1beta1.DefaultVolumePluginDir
115116
obj.ContainerRuntimeEndpoint = "unix:///run/containerd/containerd.sock"
116117

pkg/kubelet/apis/config/helpers_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ var (
233233
"Logging.Options.Text.OutputRoutingOptions.SplitStream",
234234
"Logging.VModule[*].FilePattern",
235235
"Logging.VModule[*].Verbosity",
236+
"SingleProcessOOMKill",
236237
"Logging.Verbosity",
237238
"TLSCipherSuites[*]",
238239
"TLSMinVersion",

pkg/kubelet/apis/config/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ type KubeletConfiguration struct {
229229
CgroupsPerQOS bool
230230
// driver that the kubelet uses to manipulate cgroups on the host (cgroupfs or systemd)
231231
CgroupDriver string
232+
// SingleProcessOOMKill, if true, will prevent the `memory.oom.group` flag from being set for container
233+
// cgroups in cgroups v2. This causes processes in the container to be OOM killed individually instead of as
234+
// a group. It means that if true, the behavior aligns with the behavior of cgroups v1.
235+
SingleProcessOOMKill *bool
232236
// CPUManagerPolicy is the name of the policy to use.
233237
// Requires the CPUManager feature gate to be enabled.
234238
CPUManagerPolicy string

pkg/kubelet/apis/config/v1beta1/defaults_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import (
3434
)
3535

3636
func TestSetDefaultsKubeletConfiguration(t *testing.T) {
37-
3837
tests := []struct {
3938
name string
4039
config *v1beta1.KubeletConfiguration
@@ -130,6 +129,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
130129
RegisterNode: ptr.To(true),
131130
LocalStorageCapacityIsolation: ptr.To(true),
132131
PodLogsDir: DefaultPodLogsDir,
132+
SingleProcessOOMKill: nil,
133133
},
134134
},
135135
{
@@ -261,6 +261,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
261261
RegisterNode: ptr.To(false),
262262
LocalStorageCapacityIsolation: ptr.To(false),
263263
PodLogsDir: "",
264+
SingleProcessOOMKill: ptr.To(false),
264265
},
265266
&v1beta1.KubeletConfiguration{
266267
EnableServer: ptr.To(false),
@@ -363,6 +364,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
363364
RegisterNode: ptr.To(false),
364365
LocalStorageCapacityIsolation: ptr.To(false),
365366
PodLogsDir: DefaultPodLogsDir,
367+
SingleProcessOOMKill: ptr.To(false),
366368
},
367369
},
368370
{
@@ -516,6 +518,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
516518
RegisterNode: ptr.To(true),
517519
LocalStorageCapacityIsolation: ptr.To(true),
518520
PodLogsDir: "/custom/path",
521+
SingleProcessOOMKill: ptr.To(true),
519522
},
520523
&v1beta1.KubeletConfiguration{
521524
EnableServer: ptr.To(true),
@@ -666,6 +669,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
666669
RegisterNode: ptr.To(true),
667670
LocalStorageCapacityIsolation: ptr.To(true),
668671
PodLogsDir: "/custom/path",
672+
SingleProcessOOMKill: ptr.To(true),
669673
},
670674
},
671675
{
@@ -759,6 +763,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
759763
RegisterNode: ptr.To(true),
760764
LocalStorageCapacityIsolation: ptr.To(true),
761765
PodLogsDir: DefaultPodLogsDir,
766+
SingleProcessOOMKill: nil,
762767
},
763768
},
764769
{
@@ -852,6 +857,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
852857
RegisterNode: ptr.To(true),
853858
LocalStorageCapacityIsolation: ptr.To(true),
854859
PodLogsDir: DefaultPodLogsDir,
860+
SingleProcessOOMKill: nil,
855861
},
856862
},
857863
{
@@ -945,6 +951,7 @@ func TestSetDefaultsKubeletConfiguration(t *testing.T) {
945951
RegisterNode: ptr.To(true),
946952
LocalStorageCapacityIsolation: ptr.To(true),
947953
PodLogsDir: DefaultPodLogsDir,
954+
SingleProcessOOMKill: nil,
948955
},
949956
},
950957
}

pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/kubelet/apis/config/validation/validation_linux.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,19 @@ import (
2424

2525
libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
2626
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
27+
"k8s.io/utils/ptr"
2728
)
2829

2930
// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
3031
func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
31-
if kc.FailCgroupV1 && !libcontainercgroups.IsCgroup2UnifiedMode() {
32+
isCgroup1 := !libcontainercgroups.IsCgroup2UnifiedMode()
33+
if kc.FailCgroupV1 && isCgroup1 {
3234
return fmt.Errorf("kubelet is configured to not run on a host using cgroup v1. cgroup v1 support is in maintenance mode")
3335
}
3436

37+
if isCgroup1 && kc.SingleProcessOOMKill != nil && !ptr.Deref(kc.SingleProcessOOMKill, true) {
38+
return fmt.Errorf("invalid configuration: singleProcessOOMKill must not be explicitly set to false when using cgroup v1")
39+
}
40+
3541
return nil
3642
}

pkg/kubelet/apis/config/validation/validation_others.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ limitations under the License.
2020
package validation
2121

2222
import (
23+
"fmt"
24+
2325
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
2426
)
2527

2628
// validateKubeletOSConfiguration validates os specific kubelet configuration and returns an error if it is invalid.
2729
func validateKubeletOSConfiguration(kc *kubeletconfig.KubeletConfiguration) error {
30+
if kc.SingleProcessOOMKill != nil {
31+
return fmt.Errorf("invalid configuration: singleProcessOOMKill is only supported on linux")
32+
}
33+
2834
return nil
2935
}

0 commit comments

Comments
 (0)