mirror of
https://github.com/containers/podman.git
synced 2025-08-06 19:44:14 +08:00

The update to runc broke creation of devices for containers in the pod cgroup. We don't support the device cgroup for pods at present, so just disable it for now, resolving the issue. Thanks to Giuseppe for finding this one! [NO NEW TESTS NEEDED] This is a fix for broken tests Signed-off-by: Matt Heon <mheon@redhat.com>
150 lines
5.4 KiB
Go
150 lines
5.4 KiB
Go
//go:build !remote
|
|
|
|
package libpod
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/containers/common/pkg/cgroups"
|
|
"github.com/containers/common/pkg/config"
|
|
"github.com/containers/podman/v4/libpod/define"
|
|
"github.com/containers/podman/v4/pkg/rootless"
|
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (r *Runtime) platformMakePod(pod *Pod, resourceLimits *spec.LinuxResources) (string, error) {
|
|
cgroupParent := ""
|
|
// Check Cgroup parent sanity, and set it if it was not set
|
|
if r.config.Cgroups() != "disabled" {
|
|
switch r.config.Engine.CgroupManager {
|
|
case config.CgroupfsCgroupsManager:
|
|
canUseCgroup := !rootless.IsRootless() || isRootlessCgroupSet(pod.config.CgroupParent)
|
|
if canUseCgroup {
|
|
// need to actually create parent here
|
|
if pod.config.CgroupParent == "" {
|
|
pod.config.CgroupParent = CgroupfsDefaultCgroupParent
|
|
} else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
|
|
return "", fmt.Errorf("systemd slice received as cgroup parent when using cgroupfs: %w", define.ErrInvalidArg)
|
|
}
|
|
// If we are set to use pod cgroups, set the cgroup parent that
|
|
// all containers in the pod will share
|
|
if pod.config.UsePodCgroup {
|
|
pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID())
|
|
cgroupParent = pod.state.CgroupPath
|
|
// cgroupfs + rootless = permission denied when creating the cgroup.
|
|
if !rootless.IsRootless() {
|
|
res, err := GetLimits(resourceLimits)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
res.SkipDevices = true
|
|
// Need to both create and update the cgroup
|
|
// rather than create a new path in c/common for pod cgroup creation
|
|
// just create as if it is a ctr and then update figures out that we need to
|
|
// populate the resource limits on the pod level
|
|
cgc, err := cgroups.New(pod.state.CgroupPath, &res)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = cgc.Update(&res)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case config.SystemdCgroupsManager:
|
|
if pod.config.CgroupParent == "" {
|
|
if rootless.IsRootless() {
|
|
pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent
|
|
} else {
|
|
pod.config.CgroupParent = SystemdDefaultCgroupParent
|
|
}
|
|
} else if len(pod.config.CgroupParent) < 6 || !strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") {
|
|
return "", fmt.Errorf("did not receive systemd slice as cgroup parent when using systemd to manage cgroups: %w", define.ErrInvalidArg)
|
|
}
|
|
// If we are set to use pod cgroups, set the cgroup parent that
|
|
// all containers in the pod will share
|
|
if pod.config.UsePodCgroup {
|
|
cgroupPath, err := systemdSliceFromPath(pod.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", pod.ID()), resourceLimits)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to create pod cgroup for pod %s: %w", pod.ID(), err)
|
|
}
|
|
pod.state.CgroupPath = cgroupPath
|
|
cgroupParent = pod.state.CgroupPath
|
|
}
|
|
default:
|
|
return "", fmt.Errorf("unsupported Cgroup manager: %s - cannot validate cgroup parent: %w", r.config.Engine.CgroupManager, define.ErrInvalidArg)
|
|
}
|
|
}
|
|
|
|
if pod.config.UsePodCgroup {
|
|
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
|
|
}
|
|
|
|
return cgroupParent, nil
|
|
}
|
|
|
|
func (p *Pod) removePodCgroup() error {
|
|
// Remove pod cgroup, if present
|
|
if p.state.CgroupPath == "" {
|
|
return nil
|
|
}
|
|
logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
|
|
|
|
cgroup, err := cgroups.GetOwnCgroup()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// if we are trying to delete a cgroup that is our ancestor, we need to move the
|
|
// current process out of it before the cgroup is destroyed.
|
|
if isSubDir(cgroup, string(filepath.Separator)+p.state.CgroupPath) {
|
|
parent := path.Dir(p.state.CgroupPath)
|
|
if err := cgroups.MoveUnderCgroup(parent, "cleanup", nil); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
switch p.runtime.config.Engine.CgroupManager {
|
|
case config.SystemdCgroupsManager:
|
|
if err := deleteSystemdCgroup(p.state.CgroupPath, p.ResourceLim()); err != nil {
|
|
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
case config.CgroupfsCgroupsManager:
|
|
// Delete the cgroupfs cgroup
|
|
// Make sure the conmon cgroup is deleted first
|
|
// Since the pod is almost gone, don't bother failing
|
|
// hard - instead, just log errors.
|
|
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
|
|
conmonCgroup, err := cgroups.Load(conmonCgroupPath)
|
|
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
|
|
return fmt.Errorf("retrieving pod %s conmon cgroup: %w", p.ID(), err)
|
|
}
|
|
if err == nil {
|
|
if err = conmonCgroup.Delete(); err != nil {
|
|
return fmt.Errorf("removing pod %s conmon cgroup: %w", p.ID(), err)
|
|
}
|
|
}
|
|
cgroup, err := cgroups.Load(p.state.CgroupPath)
|
|
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
|
|
return fmt.Errorf("retrieving pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
if err == nil {
|
|
if err := cgroup.Delete(); err != nil {
|
|
return fmt.Errorf("removing pod %s cgroup: %w", p.ID(), err)
|
|
}
|
|
}
|
|
default:
|
|
// This should be caught much earlier, but let's still
|
|
// keep going so we make sure to evict the pod before
|
|
// ending up with an inconsistent state.
|
|
return fmt.Errorf("unrecognized cgroup manager %s when removing pod %s cgroups: %w", p.runtime.config.Engine.CgroupManager, p.ID(), define.ErrInternal)
|
|
}
|
|
return nil
|
|
}
|