Skip to content

cgroup2: implement docker info #40662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4047,6 +4047,13 @@ definitions:
enum: ["cgroupfs", "systemd", "none"]
default: "cgroupfs"
example: "cgroupfs"
CgroupVersion:
description: |
The version of the cgroup.
type: "string"
enum: ["1", "2"]
default: "1"
example: "1"
NEventsListener:
description: "Number of event listeners subscribed."
type: "integer"
Expand Down
1 change: 1 addition & 0 deletions api/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ type Info struct {
SystemTime string
LoggingDriver string
CgroupDriver string
CgroupVersion string `json:",omitempty"`
NEventsListener int
KernelVersion string
OperatingSystem string
Expand Down
7 changes: 6 additions & 1 deletion cmd/dockerd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/docker/docker/pkg/pidfile"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/plugin"
"github.com/docker/docker/rootless"
Expand Down Expand Up @@ -456,7 +457,11 @@ func warnOnDeprecatedConfigOptions(config *config.Config) {
}

func initRouter(opts routerOptions) {
decoder := runconfig.ContainerDecoder{}
decoder := runconfig.ContainerDecoder{
GetSysInfo: func() *sysinfo.SysInfo {
return opts.daemon.RawSysInfo(true)
},
}

routers := []router.Router{
// we need to add the checkpoint router before the container router or the DELETE gets masked
Expand Down
6 changes: 3 additions & 3 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"github.com/docker/docker/errdefs"
bkconfig "github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/moby/buildkit/util/resolver"
rsystem "github.com/opencontainers/runc/libcontainer/system"
"github.com/sirupsen/logrus"

// register graph drivers
Expand All @@ -56,7 +57,6 @@ import (
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/locker"
"github.com/docker/docker/pkg/plugingetter"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/truncindex"
"github.com/docker/docker/plugin"
Expand Down Expand Up @@ -1026,10 +1026,10 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
return nil, err
}

sysInfo := sysinfo.New(false)
sysInfo := d.RawSysInfo(false)
// Check if Devices cgroup is mounted, it is hard requirement for container security,
// on Linux.
if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled {
if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled && !rsystem.RunningInUserNS() {
return nil, errors.New("Devices cgroup isn't mounted")
}

Expand Down
17 changes: 15 additions & 2 deletions daemon/daemon_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
if hostConfig == nil {
return nil, nil
}
sysInfo := sysinfo.New(true)
sysInfo := daemon.RawSysInfo(true)

w, err := verifyPlatformContainerResources(&hostConfig.Resources, sysInfo, update)

Expand Down Expand Up @@ -1745,7 +1745,7 @@ func (daemon *Daemon) initCgroupsPath(path string) error {
}

path = filepath.Join(mnt, root, path)
sysInfo := sysinfo.New(true)
sysInfo := daemon.RawSysInfo(true)
if err := maybeCreateCPURealTimeFile(sysInfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
return err
}
Expand Down Expand Up @@ -1779,3 +1779,16 @@ func (daemon *Daemon) setupSeccompProfile() error {
func (daemon *Daemon) useShimV2() bool {
return cgroups.IsCgroup2UnifiedMode()
}

// RawSysInfo returns *sysinfo.SysInfo .
func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the need for this.
If we are adding options to the wrapped function call, why not add the operations in RawSysInfo as an option that callers can add when neccessary?

Copy link
Member Author

@AkihiroSuda AkihiroSuda Apr 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because sysinfo.New() should be decoupled from the daemon, and should not call daemon.getCgroupDriver() and os.Getenv("ROOTLESSKIT_PARENT_EUID")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we expose the sysinfo option fields?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you be more specific?

var opts []sysinfo.Opt
if daemon.getCgroupDriver() == cgroupSystemdDriver {
rootlesskitParentEUID := os.Getenv("ROOTLESSKIT_PARENT_EUID")
if rootlesskitParentEUID != "" {
groupPath := fmt.Sprintf("/user.slice/user-%s.slice", rootlesskitParentEUID)
opts = append(opts, sysinfo.WithCgroup2GroupPath(groupPath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any situation where we want sysinfo.New() to not use this path if ROOTLESSKIT_PARENT_EUID is set?

Just wondering if we should make sysinfo.New() just do the right thing. I see it already uses a findCgroupMountpoints() function

Also; looks like we may want to sanitise rootlesskitParentEUID before using

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very quick attempt;
suggestions.patch.txt

diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go
index 46a62b5d2f..8b59189d57 100644
--- a/cmd/dockerd/daemon.go
+++ b/cmd/dockerd/daemon.go
@@ -45,7 +45,6 @@ import (
 	"github.com/docker/docker/pkg/pidfile"
 	"github.com/docker/docker/pkg/plugingetter"
 	"github.com/docker/docker/pkg/signal"
-	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/plugin"
 	"github.com/docker/docker/rootless"
@@ -459,11 +458,7 @@ func warnOnDeprecatedConfigOptions(config *config.Config) {
 }
 
 func initRouter(opts routerOptions) {
-	decoder := runconfig.ContainerDecoder{
-		GetSysInfo: func() *sysinfo.SysInfo {
-			return opts.daemon.RawSysInfo(true)
-		},
-	}
+	decoder := runconfig.ContainerDecoder{}
 
 	routers := []router.Router{
 		// we need to add the checkpoint router before the container router or the DELETE gets masked
diff --git a/daemon/daemon.go b/daemon/daemon.go
index 35d83d6148..7df8d7f957 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -20,10 +20,6 @@ import (
 	"sync"
 	"time"
 
-	"github.com/docker/docker/pkg/fileutils"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/backoff"
-
 	"github.com/containerd/containerd"
 	"github.com/containerd/containerd/defaults"
 	"github.com/containerd/containerd/pkg/dialer"
@@ -38,27 +34,23 @@ import (
 	"github.com/docker/docker/daemon/discovery"
 	"github.com/docker/docker/daemon/events"
 	"github.com/docker/docker/daemon/exec"
+	_ "github.com/docker/docker/daemon/graphdriver/register" // register graph drivers
 	"github.com/docker/docker/daemon/images"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/network"
-	"github.com/docker/docker/errdefs"
-	"github.com/moby/buildkit/util/resolver"
-	"github.com/moby/buildkit/util/tracing"
-	rsystem "github.com/opencontainers/runc/libcontainer/system"
-	"github.com/sirupsen/logrus"
-
-	// register graph drivers
-	_ "github.com/docker/docker/daemon/graphdriver/register"
 	"github.com/docker/docker/daemon/stats"
 	dmetadata "github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/dockerversion"
+	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/libcontainerd"
 	libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
+	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/locker"
 	"github.com/docker/docker/pkg/plugingetter"
+	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/truncindex"
 	"github.com/docker/docker/plugin"
@@ -70,8 +62,14 @@ import (
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork/cluster"
 	nwconfig "github.com/docker/libnetwork/config"
+	"github.com/moby/buildkit/util/resolver"
+	"github.com/moby/buildkit/util/tracing"
+	rsystem "github.com/opencontainers/runc/libcontainer/system"
 	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 	"golang.org/x/sync/semaphore"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/backoff"
 )
 
 // ContainersNamespace is the name of the namespace used for users containers
@@ -1044,7 +1042,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
 		return nil, err
 	}
 
-	sysInfo := d.RawSysInfo(false)
+	sysInfo := sysinfo.New(false)
 	// Check if Devices cgroup is mounted, it is hard requirement for container security,
 	// on Linux.
 	if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled && !rsystem.RunningInUserNS() {
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index 04a9beda4d..5763298dbc 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -643,7 +643,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
 	if hostConfig == nil {
 		return nil, nil
 	}
-	sysInfo := daemon.RawSysInfo(true)
+	sysInfo := sysinfo.New(true)
 
 	w, err := verifyPlatformContainerResources(&hostConfig.Resources, sysInfo, update)
 
@@ -1631,11 +1631,11 @@ func (daemon *Daemon) initCgroupsPath(path string) error {
 	}
 
 	path = filepath.Join(mnt, root, path)
-	sysinfo := daemon.RawSysInfo(true)
-	if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
+	sysInfo := sysinfo.New(true)
+	if err := maybeCreateCPURealTimeFile(sysInfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
 		return err
 	}
-	return maybeCreateCPURealTimeFile(sysinfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path)
+	return maybeCreateCPURealTimeFile(sysInfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path)
 }
 
 func maybeCreateCPURealTimeFile(sysinfoPresent bool, configValue int64, file string, path string) error {
@@ -1665,16 +1665,3 @@ func (daemon *Daemon) setupSeccompProfile() error {
 func (daemon *Daemon) useShimV2() bool {
 	return cgroups.IsCgroup2UnifiedMode()
 }
-
-// RawSysInfo returns *sysinfo.SysInfo .
-func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
-	var opts []sysinfo.Opt
-	if daemon.getCgroupDriver() == cgroupSystemdDriver {
-		rootlesskitParentEUID := os.Getenv("ROOTLESSKIT_PARENT_EUID")
-		if rootlesskitParentEUID != "" {
-			groupPath := fmt.Sprintf("/user.slice/user-%s.slice", rootlesskitParentEUID)
-			opts = append(opts, sysinfo.WithCgroup2GroupPath(groupPath))
-		}
-	}
-	return sysinfo.New(quiet, opts...)
-}
diff --git a/daemon/daemon_unsupported.go b/daemon/daemon_unsupported.go
index 4c2476edcf..e6bcbdaab1 100644
--- a/daemon/daemon_unsupported.go
+++ b/daemon/daemon_unsupported.go
@@ -4,15 +4,9 @@ package daemon // import "github.com/docker/docker/daemon"
 
 import (
 	"github.com/docker/docker/daemon/config"
-	"github.com/docker/docker/pkg/sysinfo"
 )
 
 const platformSupported = false
 
 func setupResolvConf(config *config.Config) {
 }
-
-// RawSysInfo returns *sysinfo.SysInfo .
-func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
-	return sysinfo.New(quiet)
-}
diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go
index 7fffbfb609..021b7b8f0a 100644
--- a/daemon/daemon_windows.go
+++ b/daemon/daemon_windows.go
@@ -657,8 +657,3 @@ func setupResolvConf(config *config.Config) {
 func (daemon *Daemon) useShimV2() bool {
 	return true
 }
-
-// RawSysInfo returns *sysinfo.SysInfo .
-func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
-	return sysinfo.New(quiet)
-}
diff --git a/daemon/info.go b/daemon/info.go
index 91eb826f8a..cb1d39b04b 100644
--- a/daemon/info.go
+++ b/daemon/info.go
@@ -28,7 +28,7 @@ import (
 func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 	defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()
 
-	sysInfo := daemon.RawSysInfo(true)
+	sysInfo := sysinfo.New(true)
 	cRunning, cPaused, cStopped := stateCtr.get()
 
 	v := &types.Info{
diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go
index c619559e12..de15166329 100644
--- a/pkg/sysinfo/sysinfo_linux.go
+++ b/pkg/sysinfo/sysinfo_linux.go
@@ -106,7 +106,11 @@ func newV2(quiet bool, opts *opts) *SysInfo {
 	}
 	g := opts.cg2GroupPath
 	if g == "" {
-		g = "/"
+		if euid := os.Getenv("ROOTLESSKIT_PARENT_EUID"); euid != "" {
+			g = fmt.Sprintf("/user.slice/user-%s.slice", euid)
+		} else {
+			g = "/"
+		}
 	}
 	m, err := cgroupsV2.LoadManager("/sys/fs/cgroup", g)
 	if err != nil {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

g = fmt.Sprintf("/user.slice/user-%s.slice", euid) is expected only when running in systemd mode

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"systemd mode" == "cgroupv2" or something else? (my patch above handles it in newV2(), or is that incorrect?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"systemd mode" == "--exec-opt native.cgroupdriver=systemd" (&& v2, in this context)

}
}
return sysinfo.New(quiet, opts...)
}
11 changes: 10 additions & 1 deletion daemon/daemon_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
// +build !linux,!freebsd,!windows

package daemon // import "github.com/docker/docker/daemon"
import "github.com/docker/docker/daemon/config"

import (
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/pkg/sysinfo"
)

const platformSupported = false

func setupResolvConf(config *config.Config) {
}

// RawSysInfo returns *sysinfo.SysInfo .
func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
return sysinfo.New(quiet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this just return nil or panic(unsupported) ?

or not implement this at all? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is up to pkg/sysinfo implementation.

}
5 changes: 5 additions & 0 deletions daemon/daemon_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,3 +657,8 @@ func setupResolvConf(config *config.Config) {
func (daemon *Daemon) useShimV2() bool {
return true
}

// RawSysInfo returns *sysinfo.SysInfo .
func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
return sysinfo.New(quiet)
}
3 changes: 1 addition & 2 deletions daemon/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
func (daemon *Daemon) SystemInfo() *types.Info {
defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()

sysInfo := sysinfo.New(true)
sysInfo := daemon.RawSysInfo(true)
cRunning, cPaused, cStopped := stateCtr.get()

v := &types.Info{
Expand All @@ -47,7 +47,6 @@ func (daemon *Daemon) SystemInfo() *types.Info {
NGoroutines: runtime.NumGoroutine(),
SystemTime: time.Now().Format(time.RFC3339Nano),
LoggingDriver: daemon.defaultLogConfig.Type,
CgroupDriver: daemon.getCgroupDriver(),
NEventsListener: daemon.EventsService.SubscribersCount(),
KernelVersion: kernelVersion(),
OperatingSystem: operatingSystem(),
Expand Down
69 changes: 43 additions & 26 deletions daemon/info_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ import (

// fillPlatformInfo fills the platform related info.
func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
v.CgroupDriver = daemon.getCgroupDriver()
v.CgroupVersion = "1"
if sysInfo.CgroupUnified {
v.CgroupVersion = "2"
}

v.MemoryLimit = sysInfo.MemoryLimit
v.SwapLimit = sysInfo.SwapLimit
v.KernelMemory = sysInfo.KernelMemory
Expand Down Expand Up @@ -81,32 +87,43 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
v.InitCommit.ID = "N/A"
}

if !v.MemoryLimit {
v.Warnings = append(v.Warnings, "WARNING: No memory limit support")
}
if !v.SwapLimit {
v.Warnings = append(v.Warnings, "WARNING: No swap limit support")
}
if !v.KernelMemory {
v.Warnings = append(v.Warnings, "WARNING: No kernel memory limit support")
}
if !v.KernelMemoryTCP {
v.Warnings = append(v.Warnings, "WARNING: No kernel memory TCP limit support")
}
if !v.OomKillDisable {
v.Warnings = append(v.Warnings, "WARNING: No oom kill disable support")
}
if !v.CPUCfsQuota {
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs quota support")
}
if !v.CPUCfsPeriod {
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs period support")
}
if !v.CPUShares {
v.Warnings = append(v.Warnings, "WARNING: No cpu shares support")
}
if !v.CPUSet {
v.Warnings = append(v.Warnings, "WARNING: No cpuset support")
if v.CgroupDriver == cgroupNoneDriver {
if v.CgroupVersion == "2" {
v.Warnings = append(v.Warnings, "WARNING: Running in rootless-mode without cgroup. To enable cgroup in rootless-mode, you need to set exec-opt \"native.cgroupdriver=systemd\".")
} else {
v.Warnings = append(v.Warnings, "WARNING: Running in rootless-mode without cgroup. To enable cgroup in rootless-mode, you need to boot the system in cgroup v2 mode and set exec-opt \"native.cgroupdriver=systemd\".")
}
} else {
if !v.MemoryLimit {
v.Warnings = append(v.Warnings, "WARNING: No memory limit support")
}
if !v.SwapLimit {
v.Warnings = append(v.Warnings, "WARNING: No swap limit support")
}
if !v.KernelMemory {
v.Warnings = append(v.Warnings, "WARNING: No kernel memory limit support")
}
if !v.KernelMemoryTCP {
v.Warnings = append(v.Warnings, "WARNING: No kernel memory TCP limit support")
}
if !v.OomKillDisable {
v.Warnings = append(v.Warnings, "WARNING: No oom kill disable support")
}
if !v.CPUCfsQuota {
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs quota support")
}
if !v.CPUCfsPeriod {
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs period support")
}
if !v.CPUShares {
v.Warnings = append(v.Warnings, "WARNING: No cpu shares support")
}
if !v.CPUSet {
v.Warnings = append(v.Warnings, "WARNING: No cpuset support")
}
if v.CgroupVersion == "2" {
v.Warnings = append(v.Warnings, "WARNING: Support for cgroup v2 is experimental")
}
}
if !v.IPv4Forwarding {
v.Warnings = append(v.Warnings, "WARNING: IPv4 forwarding is disabled")
Expand Down
1 change: 1 addition & 0 deletions docs/api/version-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ keywords: "API, Docker, rcli, REST, documentation"

[Docker Engine API v1.41](https://docs.docker.com/engine/api/v1.41/) documentation

* `GET /info` now returns an `CgroupVersion` field, containing the cgroup version.
* `POST /services/create` and `POST /services/{id}/update` now supports `BindOptions.NonRecursive`.
* The `ClusterStore` and `ClusterAdvertise` fields in `GET /info` are deprecated
and are now omitted if they contain an empty value. This change is not versioned,
Expand Down
151 changes: 151 additions & 0 deletions pkg/sysinfo/cgroup2_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package sysinfo // import "github.com/docker/docker/pkg/sysinfo"

import (
"io/ioutil"
"path"
"strings"

cgroupsV2 "github.com/containerd/cgroups/v2"
rsystem "github.com/opencontainers/runc/libcontainer/system"
"github.com/sirupsen/logrus"
)

type infoCollectorV2 func(info *SysInfo, controllers map[string]struct{}, dirPath string) (warnings []string)

func newV2(quiet bool, opts *opts) *SysInfo {
var warnings []string
sysInfo := &SysInfo{
CgroupUnified: true,
}
g := opts.cg2GroupPath
if g == "" {
g = "/"
}
m, err := cgroupsV2.LoadManager("/sys/fs/cgroup", g)
if err != nil {
logrus.Warn(err)
} else {
controllersM := make(map[string]struct{})
controllers, err := m.Controllers()
if err != nil {
logrus.Warn(err)
}
for _, c := range controllers {
controllersM[c] = struct{}{}
}
opsV2 := []infoCollectorV2{
applyMemoryCgroupInfoV2,
applyCPUCgroupInfoV2,
applyIOCgroupInfoV2,
applyCPUSetCgroupInfoV2,
applyPIDSCgroupInfoV2,
applyDevicesCgroupInfoV2,
}
dirPath := path.Join("/sys/fs/cgroup", path.Clean(g))
for _, o := range opsV2 {
w := o(sysInfo, controllersM, dirPath)
warnings = append(warnings, w...)
}
}

ops := []infoCollector{
applyNetworkingInfo,
applyAppArmorInfo,
applySeccompInfo,
applyCgroupNsInfo,
}
for _, o := range ops {
w := o(sysInfo, nil)
warnings = append(warnings, w...)
}
if !quiet {
for _, w := range warnings {
logrus.Warn(w)
}
}
return sysInfo
}

func applyMemoryCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ string) []string {
var warnings []string
if _, ok := controllers["memory"]; !ok {
warnings = append(warnings, "Unable to find memory controller")
return warnings
}

info.MemoryLimit = true
info.SwapLimit = true
info.MemoryReservation = true
info.OomKillDisable = false
info.MemorySwappiness = false
info.KernelMemory = false
info.KernelMemoryTCP = false
return warnings
}

func applyCPUCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ string) []string {
var warnings []string
if _, ok := controllers["cpu"]; !ok {
warnings = append(warnings, "Unable to find cpu controller")
return warnings
}
info.CPUShares = true
info.CPUCfsPeriod = true
info.CPUCfsQuota = true
info.CPURealtimePeriod = false
info.CPURealtimeRuntime = false
return warnings
}

func applyIOCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ string) []string {
var warnings []string
if _, ok := controllers["io"]; !ok {
warnings = append(warnings, "Unable to find io controller")
return warnings
}

info.BlkioWeight = true
info.BlkioWeightDevice = true
info.BlkioReadBpsDevice = true
info.BlkioWriteBpsDevice = true
info.BlkioReadIOpsDevice = true
info.BlkioWriteIOpsDevice = true
return warnings
}

func applyCPUSetCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, dirPath string) []string {
var warnings []string
if _, ok := controllers["cpuset"]; !ok {
warnings = append(warnings, "Unable to find cpuset controller")
return warnings
}
info.Cpuset = true

cpus, err := ioutil.ReadFile(path.Join(dirPath, "cpuset.cpus.effective"))
if err != nil {
return warnings
}
info.Cpus = strings.TrimSpace(string(cpus))

mems, err := ioutil.ReadFile(path.Join(dirPath, "cpuset.mems.effective"))
if err != nil {
return warnings
}
info.Mems = strings.TrimSpace(string(mems))
return warnings
}

func applyPIDSCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ string) []string {
var warnings []string
if _, ok := controllers["pids"]; !ok {
warnings = append(warnings, "Unable to find pids controller")
return warnings
}
info.PidsLimit = true
return warnings
}

func applyDevicesCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ string) []string {
info.CgroupDevicesEnabled = !rsystem.RunningInUserNS()
return nil
}
Loading