remove support for deprecated kernel memory limit

kernel-memory limits are not supported in cgroups v2, and were obsoleted in
[kernel v5.4], producing a `ENOTSUP` in kernel v5.16. Support for this option
was removed in runc and other runtimes, as various LTS kernels contained a
broken implementation, resulting in unpredictable behavior.

We deprecated this option in [moby@b8ca7de], producing a warning when used,
and actively ignore the option since [moby@0798f5f].

Given that setting this option had no effect in most situations, we should
just remove this option instead of continuing to handle it with the expectation
that a runtime may still support it.

Note that we still support RHEL 8 (kernel 4.18) and RHEL 9 (kernel 5.14). We
no longer build packages for Ubuntu 20.04 (kernel 5.4) and Debian Bullseye 11
(kernel 5.10), which still have an LTS / ESM programme, but for those it would
only impact situations where a runtime is used that still supports it, and
an old API version was used.

[kernel v5.4]: https://github.com/torvalds/linux/commit/0158115f702b0ba208ab0
[moby@b8ca7de]: b8ca7de823
[moby@0798f5f]: 0798f5f5cf

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-09-16 13:08:36 +02:00
parent 766c8313cb
commit c5991341eb
17 changed files with 0 additions and 65 deletions

View File

@@ -390,9 +390,6 @@ type Resources struct {
DeviceCgroupRules []string // List of rule to be added to the device cgroup DeviceCgroupRules []string // List of rule to be added to the device cgroup
DeviceRequests []DeviceRequest // List of device requests for device drivers DeviceRequests []DeviceRequest // List of device requests for device drivers
// KernelMemory specifies the kernel memory limit (in bytes) for the container.
// Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes.
KernelMemory int64 `json:",omitempty"`
KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes) KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes) MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap

View File

@@ -21,7 +21,6 @@ type Info struct {
Plugins PluginsInfo Plugins PluginsInfo
MemoryLimit bool MemoryLimit bool
SwapLimit bool SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2. KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2.
CPUCfsPeriod bool `json:"CpuCfsPeriod"` CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"` CPUCfsQuota bool `json:"CpuCfsQuota"`

View File

@@ -47,10 +47,6 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
// When using API 1.24 and under, the client is responsible for removing the container // When using API 1.24 and under, the client is responsible for removing the container
hostConfig.AutoRemove = false hostConfig.AutoRemove = false
} }
if versions.GreaterThanOrEqualTo(cli.ClientVersion(), "1.42") || versions.LessThan(cli.ClientVersion(), "1.40") {
// KernelMemory was added in API 1.40, and deprecated in API 1.42
hostConfig.KernelMemory = 0
}
if platform != nil && platform.OS == "linux" && versions.LessThan(cli.ClientVersion(), "1.42") { if platform != nil && platform.OS == "linux" && versions.LessThan(cli.ClientVersion(), "1.42") {
// When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize // When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize
hostConfig.ConsoleSize = [2]uint{0, 0} hostConfig.ConsoleSize = [2]uint{0, 0}

View File

@@ -302,9 +302,6 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
if resources.MemoryReservation != 0 { if resources.MemoryReservation != 0 {
cResources.MemoryReservation = resources.MemoryReservation cResources.MemoryReservation = resources.MemoryReservation
} }
if resources.KernelMemory != 0 {
cResources.KernelMemory = resources.KernelMemory
}
if resources.CPURealtimePeriod != 0 { if resources.CPURealtimePeriod != 0 {
cResources.CPURealtimePeriod = resources.CPURealtimePeriod cResources.CPURealtimePeriod = resources.CPURealtimePeriod
} }

View File

@@ -155,7 +155,6 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
resources.CpusetMems != "" || resources.CpusetMems != "" ||
len(resources.Devices) != 0 || len(resources.Devices) != 0 ||
len(resources.DeviceCgroupRules) != 0 || len(resources.DeviceCgroupRules) != 0 ||
resources.KernelMemory != 0 ||
resources.MemoryReservation != 0 || resources.MemoryReservation != 0 ||
resources.MemorySwap != 0 || resources.MemorySwap != 0 ||
resources.MemorySwappiness != nil || resources.MemorySwappiness != nil ||

View File

@@ -103,11 +103,6 @@ func getMemoryResources(config containertypes.Resources) *specs.LinuxMemory {
if config.OomKillDisable != nil { if config.OomKillDisable != nil {
memory.DisableOOMKiller = config.OomKillDisable memory.DisableOOMKiller = config.OomKillDisable
} }
if config.KernelMemory != 0 { //nolint:staticcheck // ignore SA1019: memory.Kernel is deprecated: kernel-memory limits are not supported in cgroups v2, and were obsoleted in [kernel v5.4]. This field should no longer be used, as it may be ignored by runtimes.
memory.Kernel = &config.KernelMemory //nolint:staticcheck // ignore SA1019: memory.Kernel is deprecated: kernel-memory limits are not supported in cgroups v2, and were obsoleted in [kernel v5.4]. This field should no longer be used, as it may be ignored by runtimes.
}
if config.KernelMemoryTCP != 0 { if config.KernelMemoryTCP != 0 {
memory.KernelTCP = &config.KernelMemoryTCP memory.KernelTCP = &config.KernelMemoryTCP
} }
@@ -451,18 +446,6 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn
if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation { if resources.Memory > 0 && resources.MemoryReservation > 0 && resources.Memory < resources.MemoryReservation {
return warnings, errors.New("Minimum memory limit can not be less than memory reservation limit, see usage") return warnings, errors.New("Minimum memory limit can not be less than memory reservation limit, see usage")
} }
if resources.KernelMemory > 0 {
// Kernel memory limit is not supported on cgroup v2.
// Even on cgroup v1, kernel memory limit (`kmem.limit_in_bytes`) has been deprecated since kernel 5.4.
// https://github.com/torvalds/linux/commit/0158115f702b0ba208ab0b5adf44cae99b3ebcc7
if !sysInfo.KernelMemory {
warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.")
resources.KernelMemory = 0
}
if resources.KernelMemory > 0 && resources.KernelMemory < linuxMinMemory {
return warnings, errors.New("Minimum kernel memory limit allowed is 6MB")
}
}
if resources.OomKillDisable != nil && !sysInfo.OomKillDisable { if resources.OomKillDisable != nil && !sysInfo.OomKillDisable {
// only produce warnings if the setting wasn't to *disable* the OOM Kill; no point // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point
// warning the caller if they already wanted the feature to be off // warning the caller if they already wanted the feature to be off

View File

@@ -144,9 +144,6 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, isHyp
if resources.CpusetMems != "" { if resources.CpusetMems != "" {
return warnings, fmt.Errorf("invalid option: Windows does not support CpusetMems") return warnings, fmt.Errorf("invalid option: Windows does not support CpusetMems")
} }
if resources.KernelMemory != 0 {
return warnings, fmt.Errorf("invalid option: Windows does not support KernelMemory")
}
if resources.MemoryReservation != 0 { if resources.MemoryReservation != 0 {
return warnings, fmt.Errorf("invalid option: Windows does not support MemoryReservation") return warnings, fmt.Errorf("invalid option: Windows does not support MemoryReservation")
} }

View File

@@ -34,7 +34,6 @@ func (daemon *Daemon) fillPlatformInfo(ctx context.Context, v *system.Info, sysI
if v.CgroupDriver != cgroupNoneDriver { if v.CgroupDriver != cgroupNoneDriver {
v.MemoryLimit = sysInfo.MemoryLimit v.MemoryLimit = sysInfo.MemoryLimit
v.SwapLimit = sysInfo.SwapLimit v.SwapLimit = sysInfo.SwapLimit
v.KernelMemory = sysInfo.KernelMemory
v.KernelMemoryTCP = sysInfo.KernelMemoryTCP v.KernelMemoryTCP = sysInfo.KernelMemoryTCP
v.OomKillDisable = sysInfo.OomKillDisable v.OomKillDisable = sysInfo.OomKillDisable
v.CPUCfsPeriod = sysInfo.CPUCfs v.CPUCfsPeriod = sysInfo.CPUCfs

View File

@@ -461,11 +461,6 @@ func (c *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
updateConfig.PidsLimit = nil updateConfig.PidsLimit = nil
} }
if versions.GreaterThanOrEqualTo(httputils.VersionFromContext(ctx), "1.42") {
// Ignore KernelMemory removed in API 1.42.
updateConfig.KernelMemory = 0
}
if updateConfig.PidsLimit != nil && *updateConfig.PidsLimit <= 0 { if updateConfig.PidsLimit != nil && *updateConfig.PidsLimit <= 0 {
// Both `0` and `-1` are accepted to set "unlimited" when updating. // Both `0` and `-1` are accepted to set "unlimited" when updating.
// Historically, any negative value was accepted, so treat them as // Historically, any negative value was accepted, so treat them as
@@ -592,8 +587,6 @@ func (c *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
} }
if versions.GreaterThanOrEqualTo(version, "1.42") { if versions.GreaterThanOrEqualTo(version, "1.42") {
// Ignore KernelMemory removed in API 1.42.
hostConfig.KernelMemory = 0
for _, m := range hostConfig.Mounts { for _, m := range hostConfig.Mounts {
if o := m.VolumeOptions; o != nil && m.Type != mount.TypeVolume { if o := m.VolumeOptions; o != nil && m.Type != mount.TypeVolume {
return errdefs.InvalidParameter(fmt.Errorf("VolumeOptions must not be specified on mount type %q", m.Type)) return errdefs.InvalidParameter(fmt.Errorf("VolumeOptions must not be specified on mount type %q", m.Type))

View File

@@ -118,9 +118,6 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
info.RuncCommit.Expected = info.RuncCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49. info.RuncCommit.Expected = info.RuncCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
info.InitCommit.Expected = info.InitCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49. info.InitCommit.Expected = info.InitCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
} }
if versions.GreaterThanOrEqualTo(version, "1.42") {
info.KernelMemory = false
}
if versions.LessThan(version, "1.50") { if versions.LessThan(version, "1.50") {
info.DiscoveredDevices = nil info.DiscoveredDevices = nil

View File

@@ -59,9 +59,6 @@ func toContainerdResources(resources container.Resources) *libcontainerdtypes.Re
if resources.MemoryReservation != 0 { if resources.MemoryReservation != 0 {
memory.Reservation = &resources.MemoryReservation memory.Reservation = &resources.MemoryReservation
} }
if resources.KernelMemory != 0 { //nolint:staticcheck // ignore SA1019: memory.Kernel is deprecated: kernel-memory limits are not supported in cgroups v2, and were obsoleted in [kernel v5.4]. This field should no longer be used, as it may be ignored by runtimes.
memory.Kernel = &resources.KernelMemory //nolint:staticcheck // ignore SA1019: memory.Kernel is deprecated: kernel-memory limits are not supported in cgroups v2, and were obsoleted in [kernel v5.4]. This field should no longer be used, as it may be ignored by runtimes.
}
if resources.MemorySwap > 0 { if resources.MemorySwap > 0 {
memory.Swap = &resources.MemorySwap memory.Swap = &resources.MemorySwap
} }

View File

@@ -84,7 +84,6 @@ func applyMemoryCgroupInfoV2(info *SysInfo) {
info.MemoryReservation = true info.MemoryReservation = true
info.OomKillDisable = false info.OomKillDisable = false
info.MemorySwappiness = false info.MemorySwappiness = false
info.KernelMemory = false
info.KernelMemoryTCP = false info.KernelMemoryTCP = false
} }

View File

@@ -64,12 +64,6 @@ type cgroupMemInfo struct {
// Whether memory swappiness is supported or not // Whether memory swappiness is supported or not
MemorySwappiness bool MemorySwappiness bool
// Whether kernel memory limit is supported or not. This option is used to
// detect support for kernel-memory limits on API < v1.42. Kernel memory
// limit (`kmem.limit_in_bytes`) is not supported on cgroups v2, and has been
// removed in kernel 5.4.
KernelMemory bool
// Whether kernel memory TCP limit is supported or not. Kernel memory TCP // Whether kernel memory TCP limit is supported or not. Kernel memory TCP
// limit (`memory.kmem.tcp.limit_in_bytes`) is not supported on cgroups v2. // limit (`memory.kmem.tcp.limit_in_bytes`) is not supported on cgroups v2.
KernelMemoryTCP bool KernelMemoryTCP bool

View File

@@ -153,10 +153,6 @@ func applyMemoryCgroupInfo(info *SysInfo) {
info.Warnings = append(info.Warnings, "Your kernel does not support memory swappiness") info.Warnings = append(info.Warnings, "Your kernel does not support memory swappiness")
} }
// Option is deprecated, but still accepted on API < v1.42 with cgroups v1,
// so setting the field to allow feature detection.
info.KernelMemory = cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
// Option is deprecated in runc, but still accepted in our API, so setting // Option is deprecated in runc, but still accepted in our API, so setting
// the field to allow feature detection, but don't warn if it's missing, to // the field to allow feature detection, but don't warn if it's missing, to
// make the daemon logs a bit less noisy. // make the daemon logs a bit less noisy.

View File

@@ -390,9 +390,6 @@ type Resources struct {
DeviceCgroupRules []string // List of rule to be added to the device cgroup DeviceCgroupRules []string // List of rule to be added to the device cgroup
DeviceRequests []DeviceRequest // List of device requests for device drivers DeviceRequests []DeviceRequest // List of device requests for device drivers
// KernelMemory specifies the kernel memory limit (in bytes) for the container.
// Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes.
KernelMemory int64 `json:",omitempty"`
KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes) KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes) MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap

View File

@@ -21,7 +21,6 @@ type Info struct {
Plugins PluginsInfo Plugins PluginsInfo
MemoryLimit bool MemoryLimit bool
SwapLimit bool SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2. KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2.
CPUCfsPeriod bool `json:"CpuCfsPeriod"` CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"` CPUCfsQuota bool `json:"CpuCfsQuota"`

View File

@@ -47,10 +47,6 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
// When using API 1.24 and under, the client is responsible for removing the container // When using API 1.24 and under, the client is responsible for removing the container
hostConfig.AutoRemove = false hostConfig.AutoRemove = false
} }
if versions.GreaterThanOrEqualTo(cli.ClientVersion(), "1.42") || versions.LessThan(cli.ClientVersion(), "1.40") {
// KernelMemory was added in API 1.40, and deprecated in API 1.42
hostConfig.KernelMemory = 0
}
if platform != nil && platform.OS == "linux" && versions.LessThan(cli.ClientVersion(), "1.42") { if platform != nil && platform.OS == "linux" && versions.LessThan(cli.ClientVersion(), "1.42") {
// When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize // When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize
hostConfig.ConsoleSize = [2]uint{0, 0} hostConfig.ConsoleSize = [2]uint{0, 0}