mirror of
https://github.com/moby/moby.git
synced 2026-01-11 10:41:43 +00:00
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]:0798f5f5cfSigned-off-by: Sebastiaan van Stijn <github@gone.nl>
159 lines
3.5 KiB
Go
159 lines
3.5 KiB
Go
package sysinfo
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/containerd/cgroups/v3"
|
|
cgroupsV2 "github.com/containerd/cgroups/v3/cgroup2"
|
|
"github.com/containerd/log"
|
|
"github.com/moby/sys/userns"
|
|
)
|
|
|
|
func newV2(options ...Opt) *SysInfo {
|
|
sysInfo := &SysInfo{
|
|
CgroupUnified: true,
|
|
cg2GroupPath: "/",
|
|
}
|
|
for _, o := range options {
|
|
o(sysInfo)
|
|
}
|
|
|
|
ops := []infoCollector{
|
|
applyNetworkingInfo,
|
|
applyAppArmorInfo,
|
|
applySeccompInfo,
|
|
applyCgroupNsInfo,
|
|
}
|
|
|
|
m, err := cgroupsV2.Load(sysInfo.cg2GroupPath)
|
|
if err != nil {
|
|
log.G(context.TODO()).Warn(err)
|
|
} else {
|
|
sysInfo.cg2Controllers = make(map[string]struct{})
|
|
controllers, err := m.Controllers()
|
|
if err != nil {
|
|
log.G(context.TODO()).Warn(err)
|
|
}
|
|
for _, c := range controllers {
|
|
sysInfo.cg2Controllers[c] = struct{}{}
|
|
}
|
|
ops = append(ops,
|
|
applyMemoryCgroupInfoV2,
|
|
applyCPUCgroupInfoV2,
|
|
applyIOCgroupInfoV2,
|
|
applyCPUSetCgroupInfoV2,
|
|
applyPIDSCgroupInfoV2,
|
|
applyDevicesCgroupInfoV2,
|
|
)
|
|
}
|
|
|
|
for _, o := range ops {
|
|
o(sysInfo)
|
|
}
|
|
return sysInfo
|
|
}
|
|
|
|
func getSwapLimitV2() bool {
|
|
_, g, err := cgroups.ParseCgroupFileUnified("/proc/self/cgroup")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
if g == "" {
|
|
return false
|
|
}
|
|
|
|
cGroupPath := path.Join("/sys/fs/cgroup", g, "memory.swap.max")
|
|
if _, err = os.Stat(cGroupPath); os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func applyMemoryCgroupInfoV2(info *SysInfo) {
|
|
if _, ok := info.cg2Controllers["memory"]; !ok {
|
|
info.Warnings = append(info.Warnings, "Unable to find memory controller")
|
|
return
|
|
}
|
|
|
|
info.MemoryLimit = true
|
|
info.SwapLimit = getSwapLimitV2()
|
|
info.MemoryReservation = true
|
|
info.OomKillDisable = false
|
|
info.MemorySwappiness = false
|
|
info.KernelMemoryTCP = false
|
|
}
|
|
|
|
func applyCPUCgroupInfoV2(info *SysInfo) {
|
|
if _, ok := info.cg2Controllers["cpu"]; !ok {
|
|
info.Warnings = append(info.Warnings, "Unable to find cpu controller")
|
|
return
|
|
}
|
|
info.CPUShares = true
|
|
info.CPUCfs = true
|
|
info.CPURealtime = false
|
|
}
|
|
|
|
func applyIOCgroupInfoV2(info *SysInfo) {
|
|
if _, ok := info.cg2Controllers["io"]; !ok {
|
|
info.Warnings = append(info.Warnings, "Unable to find io controller")
|
|
return
|
|
}
|
|
|
|
info.BlkioWeight = true
|
|
info.BlkioWeightDevice = true
|
|
info.BlkioReadBpsDevice = true
|
|
info.BlkioWriteBpsDevice = true
|
|
info.BlkioReadIOpsDevice = true
|
|
info.BlkioWriteIOpsDevice = true
|
|
}
|
|
|
|
func applyCPUSetCgroupInfoV2(info *SysInfo) {
|
|
if _, ok := info.cg2Controllers["cpuset"]; !ok {
|
|
info.Warnings = append(info.Warnings, "Unable to find cpuset controller")
|
|
return
|
|
}
|
|
info.Cpuset = true
|
|
|
|
cpus, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.cpus.effective"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
info.Cpus = strings.TrimSpace(string(cpus))
|
|
|
|
cpuSets, err := parseUintList(info.Cpus, 0)
|
|
if err != nil {
|
|
info.Warnings = append(info.Warnings, "Unable to parse cpuset cpus: "+err.Error())
|
|
return
|
|
}
|
|
info.CPUSets = cpuSets
|
|
|
|
mems, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.mems.effective"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
info.Mems = strings.TrimSpace(string(mems))
|
|
|
|
memSets, err := parseUintList(info.Cpus, 0)
|
|
if err != nil {
|
|
info.Warnings = append(info.Warnings, "Unable to parse cpuset mems: "+err.Error())
|
|
return
|
|
}
|
|
info.MemSets = memSets
|
|
}
|
|
|
|
func applyPIDSCgroupInfoV2(info *SysInfo) {
|
|
if _, ok := info.cg2Controllers["pids"]; !ok {
|
|
info.Warnings = append(info.Warnings, "Unable to find pids controller")
|
|
return
|
|
}
|
|
info.PidsLimit = true
|
|
}
|
|
|
|
func applyDevicesCgroupInfoV2(info *SysInfo) {
|
|
info.CgroupDevicesEnabled = !userns.RunningInUserNS()
|
|
}
|