-
Notifications
You must be signed in to change notification settings - Fork 18.7k
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
|
||
|
@@ -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 | ||
} | ||
|
@@ -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 { | ||
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)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any situation where we want Just wondering if we should make Also; looks like we may want to sanitise There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A very quick attempt; 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 { There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "systemd mode" == "cgroupv2" or something else? (my patch above handles it in There was a problem hiding this comment. Choose a reason for hiding this commentThe 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...) | ||
} |
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this just return or not implement this at all? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that is up to |
||
} |
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 | ||
} |
There was a problem hiding this comment.
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?There was a problem hiding this comment.
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 calldaemon.getCgroupDriver()
andos.Getenv("ROOTLESSKIT_PARENT_EUID")
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?