diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index dbaa43da63..5a2883324c 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -439,6 +439,12 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon if versions.LessThan(httputils.VersionFromContext(ctx), "1.40") { 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 { // Both `0` and `-1` are accepted to set "unlimited" when updating. // Historically, any negative value was accepted, so treat them as @@ -505,6 +511,11 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo } } + if hostConfig != nil && versions.GreaterThanOrEqualTo(version, "1.42") { + // Ignore KernelMemory removed in API 1.42. + hostConfig.KernelMemory = 0 + } + var platform *specs.Platform if versions.GreaterThanOrEqualTo(version, "1.41") { if v := r.Form.Get("platform"); v != "" { diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go index d25d92204c..44f80dba5f 100644 --- a/api/server/router/system/system_routes.go +++ b/api/server/router/system/system_routes.go @@ -51,7 +51,8 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht info.Warnings = append(info.Warnings, info.Swarm.Warnings...) } - if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") { + version := httputils.VersionFromContext(ctx) + if versions.LessThan(version, "1.25") { // TODO: handle this conversion in engine-api type oldInfo struct { *types.Info @@ -72,7 +73,7 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht old.SecurityOptions = nameOnlySecurityOptions return httputils.WriteJSON(w, http.StatusOK, old) } - if versions.LessThan(httputils.VersionFromContext(ctx), "1.39") { + if versions.LessThan(version, "1.39") { if info.KernelVersion == "" { info.KernelVersion = "" } @@ -80,6 +81,9 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht info.OperatingSystem = "" } } + if versions.GreaterThanOrEqualTo(version, "1.42") { + info.KernelMemory = false + } return httputils.WriteJSON(w, http.StatusOK, info) } diff --git a/api/swagger.yaml b/api/swagger.yaml index a0588f0bd3..edd356e0f9 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -577,19 +577,13 @@ definitions: type: "array" items: $ref: "#/definitions/DeviceRequest" - KernelMemory: - description: | - Kernel memory limit in bytes. - -


- - > **Deprecated**: This field is deprecated as the kernel 5.4 deprecated - > `kmem.limit_in_bytes`. - type: "integer" - format: "int64" - example: 209715200 KernelMemoryTCP: - description: "Hard limit for kernel TCP buffer memory (in bytes)." + description: | + Hard limit for kernel TCP buffer memory (in bytes). Depending on the + OCI runtime in use, this option may be ignored. It is no longer supported + by the default (runc) runtime. + + This field is omitted when empty. type: "integer" format: "int64" MemoryReservation: @@ -4657,19 +4651,10 @@ definitions: description: "Indicates if the host has memory swap limit support enabled." type: "boolean" example: true - KernelMemory: - description: | - Indicates if the host has kernel memory limit support enabled. - -


- - > **Deprecated**: This field is deprecated as the kernel 5.4 deprecated - > `kmem.limit_in_bytes`. - type: "boolean" - example: true KernelMemoryTCP: description: | - Indicates if the host has kernel memory TCP limit support enabled. + Indicates if the host has kernel memory TCP limit support enabled. This + field is omitted if not supported. Kernel memory TCP limits are not supported when using cgroups v2, which does not support the corresponding `memory.kmem.tcp.limit_in_bytes` cgroup. @@ -5834,7 +5819,6 @@ paths: Memory: 0 MemorySwap: 0 MemoryReservation: 0 - KernelMemory: 0 NanoCpus: 500000 CpuPercent: 80 CpuShares: 512 @@ -6126,7 +6110,6 @@ paths: Memory: 0 MemorySwap: 0 MemoryReservation: 0 - KernelMemory: 0 OomKillDisable: false OomScoreAdj: 500 NetworkMode: "bridge" @@ -6871,7 +6854,6 @@ paths: Memory: 314572800 MemorySwap: 514288000 MemoryReservation: 209715200 - KernelMemory: 52428800 RestartPolicy: MaximumRetryCount: 4 Name: "on-failure" diff --git a/api/types/container/host_config.go b/api/types/container/host_config.go index dcea6c8a5a..9a5aa28f9a 100644 --- a/api/types/container/host_config.go +++ b/api/types/container/host_config.go @@ -376,14 +376,17 @@ type Resources struct { Devices []DeviceMapping // List of devices to map inside the container DeviceCgroupRules []string // List of rule to be added to the device cgroup DeviceRequests []DeviceRequest // List of device requests for device drivers - KernelMemory int64 // Kernel memory limit (in bytes), Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes - KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes) - MemoryReservation int64 // Memory soft limit (in bytes) - MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap - MemorySwappiness *int64 // Tuning container memory swappiness behaviour - OomKillDisable *bool // Whether to disable OOM Killer or not - PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change. - Ulimits []*units.Ulimit // List of ulimits to be set in the container + + // 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) + MemoryReservation int64 // Memory soft limit (in bytes) + MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap + MemorySwappiness *int64 // Tuning container memory swappiness behaviour + OomKillDisable *bool // Whether to disable OOM Killer or not + PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change. + Ulimits []*units.Ulimit // List of ulimits to be set in the container // Applicable to Windows CPUCount int64 `json:"CpuCount"` // CPU count diff --git a/api/types/types.go b/api/types/types.go index 1afc4bf9d3..c5a3fe52e7 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -239,8 +239,8 @@ type Info struct { Plugins PluginsInfo MemoryLimit bool SwapLimit bool - KernelMemory bool // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes - KernelMemoryTCP 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. CPUCfsPeriod bool `json:"CpuCfsPeriod"` CPUCfsQuota bool `json:"CpuCfsQuota"` CPUShares bool diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index e5c6dbbc5a..a92c675c8f 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -445,17 +445,16 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn // 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 - warnings = append(warnings, "Specifying a kernel memory limit is deprecated and will be removed in a future release.") - } - if resources.KernelMemory > 0 && !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, fmt.Errorf("Minimum kernel memory limit allowed is 6MB") - } - if resources.KernelMemory > 0 && !kernel.CheckKernelVersion(4, 0, 0) { - warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") + 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, fmt.Errorf("Minimum kernel memory limit allowed is 6MB") + } + if !kernel.CheckKernelVersion(4, 0, 0) { + warnings = append(warnings, "You specified a kernel memory limit on a kernel older than 4.0. Kernel memory limits are experimental on older kernels, it won't work as expected and can cause your system to be unstable.") + } } if resources.OomKillDisable != nil && !sysInfo.OomKillDisable { // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 4e7f89d2d8..3cf25ee5d1 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -42,6 +42,14 @@ keywords: "API, Docker, rcli, REST, documentation" versioned, and affects all API versions if the daemon has this patch. * The `POST /containers/{id}/wait` endpoint now returns a `400` status code if an invalid `condition` is provided (on API 1.30 and up). +* Removed the `KernelMemory` field from the `POST /containers/create` and + `POST /containers/{id}/update` endpoints, any value it is set to will be ignored + on API version `v1.42` and up. Older API versions still accept this field, but + may take no effect, depending on the kernel version and OCI runtime in use. +* `GET /containers/{id}/json` now omits the `KernelMemory` and `KernelMemoryTCP` + if they are not set. +* `GET /info` now omits the `KernelMemory` and `KernelMemoryTCP` if they are not + supported by the host or host's configuration (if cgroups v2 are in use). ## v1.41 API changes diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go index ac8a417581..3078ecef36 100644 --- a/pkg/sysinfo/sysinfo.go +++ b/pkg/sysinfo/sysinfo.go @@ -71,10 +71,14 @@ type cgroupMemInfo struct { // Whether memory swappiness is supported or not MemorySwappiness bool - // Whether kernel memory limit is supported or not + // 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 + // 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. KernelMemoryTCP bool } diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go index ac858f452f..910ce2d442 100644 --- a/pkg/sysinfo/sysinfo_linux.go +++ b/pkg/sysinfo/sysinfo_linux.go @@ -149,14 +149,15 @@ func applyMemoryCgroupInfo(info *SysInfo) { if !info.MemorySwappiness { 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") - if !info.KernelMemory { - info.Warnings = append(info.Warnings, "Your kernel does not support kernel memory limit") - } + + // 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 + // make the daemon logs a bit less noisy. info.KernelMemoryTCP = cgroupEnabled(mountPoint, "memory.kmem.tcp.limit_in_bytes") - if !info.KernelMemoryTCP { - info.Warnings = append(info.Warnings, "Your kernel does not support kernel memory TCP limit") - } } // applyCPUCgroupInfo adds the cpu cgroup controller information to the info.