github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/pkg/sysinfo/cgroup2_linux.go (about)

     1  package sysinfo // import "github.com/docker/docker/pkg/sysinfo"
     2  
     3  import (
     4  	"os"
     5  	"path"
     6  	"strings"
     7  
     8  	cgroupsV2 "github.com/containerd/cgroups/v2"
     9  	"github.com/containerd/containerd/pkg/userns"
    10  	"github.com/opencontainers/runc/libcontainer/cgroups"
    11  	"github.com/sirupsen/logrus"
    12  )
    13  
    14  func newV2(options ...Opt) *SysInfo {
    15  	sysInfo := &SysInfo{
    16  		CgroupUnified: true,
    17  		cg2GroupPath:  "/",
    18  	}
    19  	for _, o := range options {
    20  		o(sysInfo)
    21  	}
    22  
    23  	ops := []infoCollector{
    24  		applyNetworkingInfo,
    25  		applyAppArmorInfo,
    26  		applySeccompInfo,
    27  		applyCgroupNsInfo,
    28  	}
    29  
    30  	m, err := cgroupsV2.LoadManager("/sys/fs/cgroup", sysInfo.cg2GroupPath)
    31  	if err != nil {
    32  		logrus.Warn(err)
    33  	} else {
    34  		sysInfo.cg2Controllers = make(map[string]struct{})
    35  		controllers, err := m.Controllers()
    36  		if err != nil {
    37  			logrus.Warn(err)
    38  		}
    39  		for _, c := range controllers {
    40  			sysInfo.cg2Controllers[c] = struct{}{}
    41  		}
    42  		ops = append(ops,
    43  			applyMemoryCgroupInfoV2,
    44  			applyCPUCgroupInfoV2,
    45  			applyIOCgroupInfoV2,
    46  			applyCPUSetCgroupInfoV2,
    47  			applyPIDSCgroupInfoV2,
    48  			applyDevicesCgroupInfoV2,
    49  		)
    50  	}
    51  
    52  	for _, o := range ops {
    53  		o(sysInfo)
    54  	}
    55  	return sysInfo
    56  }
    57  
    58  func getSwapLimitV2() bool {
    59  	groups, err := cgroups.ParseCgroupFile("/proc/self/cgroup")
    60  	if err != nil {
    61  		return false
    62  	}
    63  
    64  	g := groups[""]
    65  	if g == "" {
    66  		return false
    67  	}
    68  
    69  	cGroupPath := path.Join("/sys/fs/cgroup", g, "memory.swap.max")
    70  	if _, err = os.Stat(cGroupPath); os.IsNotExist(err) {
    71  		return false
    72  	}
    73  	return true
    74  }
    75  
    76  func applyMemoryCgroupInfoV2(info *SysInfo) {
    77  	if _, ok := info.cg2Controllers["memory"]; !ok {
    78  		info.Warnings = append(info.Warnings, "Unable to find memory controller")
    79  		return
    80  	}
    81  
    82  	info.MemoryLimit = true
    83  	info.SwapLimit = getSwapLimitV2()
    84  	info.MemoryReservation = true
    85  	info.OomKillDisable = false
    86  	info.MemorySwappiness = false
    87  	info.KernelMemory = false
    88  	info.KernelMemoryTCP = false
    89  }
    90  
    91  func applyCPUCgroupInfoV2(info *SysInfo) {
    92  	if _, ok := info.cg2Controllers["cpu"]; !ok {
    93  		info.Warnings = append(info.Warnings, "Unable to find cpu controller")
    94  		return
    95  	}
    96  	info.CPUShares = true
    97  	info.CPUCfs = true
    98  	info.CPURealtime = false
    99  }
   100  
   101  func applyIOCgroupInfoV2(info *SysInfo) {
   102  	if _, ok := info.cg2Controllers["io"]; !ok {
   103  		info.Warnings = append(info.Warnings, "Unable to find io controller")
   104  		return
   105  	}
   106  
   107  	info.BlkioWeight = true
   108  	info.BlkioWeightDevice = true
   109  	info.BlkioReadBpsDevice = true
   110  	info.BlkioWriteBpsDevice = true
   111  	info.BlkioReadIOpsDevice = true
   112  	info.BlkioWriteIOpsDevice = true
   113  }
   114  
   115  func applyCPUSetCgroupInfoV2(info *SysInfo) {
   116  	if _, ok := info.cg2Controllers["cpuset"]; !ok {
   117  		info.Warnings = append(info.Warnings, "Unable to find cpuset controller")
   118  		return
   119  	}
   120  	info.Cpuset = true
   121  
   122  	cpus, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.cpus.effective"))
   123  	if err != nil {
   124  		return
   125  	}
   126  	info.Cpus = strings.TrimSpace(string(cpus))
   127  
   128  	mems, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.mems.effective"))
   129  	if err != nil {
   130  		return
   131  	}
   132  	info.Mems = strings.TrimSpace(string(mems))
   133  }
   134  
   135  func applyPIDSCgroupInfoV2(info *SysInfo) {
   136  	if _, ok := info.cg2Controllers["pids"]; !ok {
   137  		info.Warnings = append(info.Warnings, "Unable to find pids controller")
   138  		return
   139  	}
   140  	info.PidsLimit = true
   141  }
   142  
   143  func applyDevicesCgroupInfoV2(info *SysInfo) {
   144  	info.CgroupDevicesEnabled = !userns.RunningInUserNS()
   145  }