Skip to content
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

Store cgroup manager on a per-container basis #7970

Merged
merged 1 commit into from
Oct 8, 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
19 changes: 16 additions & 3 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,9 +888,22 @@ func (c *Container) NamespacePath(linuxNS LinuxNS) (string, error) { //nolint:in
return fmt.Sprintf("/proc/%d/ns/%s", c.state.PID, linuxNS.String()), nil
}

// CgroupManager returns the cgroup manager used by the given container.
func (c *Container) CgroupManager() string {
cgroupManager := c.config.CgroupManager
if cgroupManager == "" {
cgroupManager = c.runtime.config.Engine.CgroupManager
}
return cgroupManager
}

// CGroupPath returns a cgroups "path" for a given container.
func (c *Container) CGroupPath() (string, error) {
cgroupManager := c.CgroupManager()

switch {
case c.config.NoCgroups || c.config.CgroupsMode == "disabled":
return "", errors.Wrapf(define.ErrNoCgroups, "this container is not creating cgroups")
case c.config.CgroupsMode == cgroupSplit:
if c.config.CgroupParent != "" {
return "", errors.Errorf("cannot specify cgroup-parent with cgroup-mode %q", cgroupSplit)
Expand All @@ -906,9 +919,9 @@ func (c *Container) CGroupPath() (string, error) {
return "", errors.Errorf("invalid cgroup for conmon %q", cg)
}
return strings.TrimSuffix(cg, "/supervisor") + "/container", nil
case c.runtime.config.Engine.CgroupManager == config.CgroupfsCgroupsManager:
case cgroupManager == config.CgroupfsCgroupsManager:
return filepath.Join(c.config.CgroupParent, fmt.Sprintf("libpod-%s", c.ID())), nil
case c.runtime.config.Engine.CgroupManager == config.SystemdCgroupsManager:
case cgroupManager == config.SystemdCgroupsManager:
if rootless.IsRootless() {
uid := rootless.GetRootlessUID()
parts := strings.SplitN(c.config.CgroupParent, "/", 2)
Expand All @@ -922,7 +935,7 @@ func (c *Container) CGroupPath() (string, error) {
}
return filepath.Join(c.config.CgroupParent, createUnitName("libpod", c.ID())), nil
default:
return "", errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager %s in use", c.runtime.config.Engine.CgroupManager)
return "", errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager %s in use", cgroupManager)
}
}

Expand Down
5 changes: 4 additions & 1 deletion libpod/container_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,16 @@ type ContainerMiscConfig struct {
StopTimeout uint `json:"stopTimeout,omitempty"`
// Time container was created
CreatedTime time.Time `json:"createdTime"`
// CgroupManager is the cgroup manager used to create this container.
// If empty, the runtime default will be used.
CgroupManager string `json:"cgroupManager,omitempty"`
// NoCgroups indicates that the container will not create CGroups. It is
// incompatible with CgroupParent. Deprecated in favor of CgroupsMode.
NoCgroups bool `json:"noCgroups,omitempty"`
// CgroupsMode indicates how the container will create cgroups
// (disabled, no-conmon, enabled). It supersedes NoCgroups.
CgroupsMode string `json:"cgroupsMode,omitempty"`
// Cgroup parent of the container
// Cgroup parent of the container.
CgroupParent string `json:"cgroupParent"`
// LogPath log location
LogPath string `json:"logPath"`
Expand Down
3 changes: 2 additions & 1 deletion libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
// CGroup parent
// Need to check if it's the default, and not print if so.
defaultCgroupParent := ""
switch c.runtime.config.Engine.CgroupManager {
switch c.CgroupManager() {
case config.CgroupfsCgroupsManager:
defaultCgroupParent = CgroupfsDefaultCgroupParent
case config.SystemdCgroupsManager:
Expand All @@ -738,6 +738,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
if c.config.CgroupParent != defaultCgroupParent {
hostConfig.CgroupParent = c.config.CgroupParent
}
hostConfig.CgroupManager = c.CgroupManager()

// PID namespace mode
pidMode := ""
Expand Down
7 changes: 4 additions & 3 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1965,6 +1965,7 @@ func (c *Container) getOCICgroupPath() (string, error) {
if err != nil {
return "", err
}
cgroupManager := c.CgroupManager()
switch {
case (rootless.IsRootless() && !unified) || c.config.NoCgroups:
return "", nil
Expand All @@ -1977,22 +1978,22 @@ func (c *Container) getOCICgroupPath() (string, error) {
return "", err
}
return filepath.Join(selfCgroup, "container"), nil
case c.runtime.config.Engine.CgroupManager == config.SystemdCgroupsManager:
case cgroupManager == config.SystemdCgroupsManager:
// When the OCI runtime is set to use Systemd as a cgroup manager, it
// expects cgroups to be passed as follows:
// slice:prefix:name
systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID())
logrus.Debugf("Setting CGroups for container %s to %s", c.ID(), systemdCgroups)
return systemdCgroups, nil
case c.runtime.config.Engine.CgroupManager == config.CgroupfsCgroupsManager:
case cgroupManager == config.CgroupfsCgroupsManager:
cgroupPath, err := c.CGroupPath()
if err != nil {
return "", err
}
logrus.Debugf("Setting CGroup path for container %s to %s", c.ID(), cgroupPath)
return cgroupPath, nil
default:
return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", c.runtime.config.Engine.CgroupManager)
return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", cgroupManager)
}
}

Expand Down
3 changes: 3 additions & 0 deletions libpod/define/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ type InspectContainerHostConfig struct {
// include a Mounts field in inspect.
// Format: <src>:<destination>[:<comma-separated options>]
Binds []string `json:"Binds"`
// CgroupManager is the cgroup manager used by the container.
// At present, allowed values are either "cgroupfs" or "systemd".
CgroupManager string `json:"CgroupManager,omitempty"`
// CgroupMode is the configuration of the container's cgroup namespace.
// Populated as follows:
// private - a cgroup namespace has been created
Expand Down
12 changes: 4 additions & 8 deletions libpod/oci_conmon_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ type ConmonOCIRuntime struct {
path string
conmonPath string
conmonEnv []string
cgroupManager string
tmpDir string
exitsDir string
socketsDir string
Expand Down Expand Up @@ -102,7 +101,6 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
runtime.runtimeFlags = runtimeFlags

runtime.conmonEnv = runtimeCfg.Engine.ConmonEnvVars
runtime.cgroupManager = runtimeCfg.Engine.CgroupManager
runtime.tmpDir = runtimeCfg.Engine.TmpDir
runtime.logSizeMax = runtimeCfg.Containers.LogSizeMax
runtime.noPivot = runtimeCfg.Engine.NoPivotRoot
Expand Down Expand Up @@ -149,10 +147,6 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits")
runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket")

if runtime.cgroupManager != config.CgroupfsCgroupsManager && runtime.cgroupManager != config.SystemdCgroupsManager {
return nil, errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager specified: %s", runtime.cgroupManager)
}

// Create the exit files and attach sockets directories
if err := os.MkdirAll(runtime.exitsDir, 0750); err != nil {
// The directory is allowed to exist
Expand Down Expand Up @@ -1325,7 +1319,7 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
args = append(args, rFlags...)
}

if r.cgroupManager == config.SystemdCgroupsManager && !ctr.config.NoCgroups && ctr.config.CgroupsMode != cgroupSplit {
if ctr.CgroupManager() == config.SystemdCgroupsManager && !ctr.config.NoCgroups && ctr.config.CgroupsMode != cgroupSplit {
args = append(args, "-s")
}

Expand Down Expand Up @@ -1442,8 +1436,10 @@ func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec
}

if mustCreateCgroup {
// TODO: This should be a switch - we are not guaranteed that
// there are only 2 valid cgroup managers
cgroupParent := ctr.CgroupParent()
if r.cgroupManager == config.SystemdCgroupsManager {
if ctr.CgroupManager() == config.SystemdCgroupsManager {
unitName := createUnitName("libpod-conmon", ctr.ID())

realCgroupParent := cgroupParent
Expand Down
1 change: 1 addition & 0 deletions libpod/runtime_ctr.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
// Check CGroup parent sanity, and set it if it was not set.
// Only if we're actually configuring CGroups.
if !ctr.config.NoCgroups {
ctr.config.CgroupManager = r.config.Engine.CgroupManager
switch r.config.Engine.CgroupManager {
case config.CgroupfsCgroupsManager:
if ctr.config.CgroupParent == "" {
Expand Down