Support cgroup as in Rootless Podman.
Requires cgroup v2 host with crun.
Tested with Ubuntu 19.10 (kernel 5.3, systemd 242), crun v0.12.1.
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
| ... | ... |
@@ -599,15 +599,13 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn |
| 599 | 599 |
} |
| 600 | 600 |
|
| 601 | 601 |
func (daemon *Daemon) getCgroupDriver() string {
|
| 602 |
+ if UsingSystemd(daemon.configStore) {
|
|
| 603 |
+ return cgroupSystemdDriver |
|
| 604 |
+ } |
|
| 602 | 605 |
if daemon.Rootless() {
|
| 603 | 606 |
return cgroupNoneDriver |
| 604 | 607 |
} |
| 605 |
- cgroupDriver := cgroupFsDriver |
|
| 606 |
- |
|
| 607 |
- if UsingSystemd(daemon.configStore) {
|
|
| 608 |
- cgroupDriver = cgroupSystemdDriver |
|
| 609 |
- } |
|
| 610 |
- return cgroupDriver |
|
| 608 |
+ return cgroupFsDriver |
|
| 611 | 609 |
} |
| 612 | 610 |
|
| 613 | 611 |
// getCD gets the raw value of the native.cgroupdriver option, if set. |
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"context" |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"io" |
| 7 |
+ "io/ioutil" |
|
| 7 | 8 |
"os" |
| 8 | 9 |
"os/exec" |
| 9 | 10 |
"path/filepath" |
| ... | ... |
@@ -84,8 +85,26 @@ func WithLibnetwork(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 | 86 |
// WithRootless sets the spec to the rootless configuration |
| 87 |
-func WithRootless(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 88 |
- return specconv.ToRootless(s) |
|
| 87 |
+func WithRootless(daemon *Daemon) coci.SpecOpts {
|
|
| 88 |
+ return func(_ context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 89 |
+ var v2Controllers []string |
|
| 90 |
+ if daemon.getCgroupDriver() == cgroupSystemdDriver {
|
|
| 91 |
+ if !cgroups.IsCgroup2UnifiedMode() {
|
|
| 92 |
+ return errors.New("rootless systemd driver doesn't support cgroup v1")
|
|
| 93 |
+ } |
|
| 94 |
+ rootlesskitParentEUID := os.Getenv("ROOTLESSKIT_PARENT_EUID")
|
|
| 95 |
+ if rootlesskitParentEUID == "" {
|
|
| 96 |
+ return errors.New("$ROOTLESSKIT_PARENT_EUID is not set (requires RootlessKit v0.8.0)")
|
|
| 97 |
+ } |
|
| 98 |
+ controllersPath := fmt.Sprintf("/sys/fs/cgroup/user.slice/user-%s.slice/cgroup.controllers", rootlesskitParentEUID)
|
|
| 99 |
+ controllersFile, err := ioutil.ReadFile(controllersPath) |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ return err |
|
| 102 |
+ } |
|
| 103 |
+ v2Controllers = strings.Fields(string(controllersFile)) |
|
| 104 |
+ } |
|
| 105 |
+ return specconv.ToRootless(s, v2Controllers) |
|
| 106 |
+ } |
|
| 89 | 107 |
} |
| 90 | 108 |
|
| 91 | 109 |
// WithOOMScore sets the oom score |
| ... | ... |
@@ -760,6 +779,9 @@ func WithCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
| 760 | 760 |
useSystemd := UsingSystemd(daemon.configStore) |
| 761 | 761 |
if useSystemd {
|
| 762 | 762 |
parent = "system.slice" |
| 763 |
+ if daemon.configStore.Rootless {
|
|
| 764 |
+ parent = "user.slice" |
|
| 765 |
+ } |
|
| 763 | 766 |
} |
| 764 | 767 |
|
| 765 | 768 |
if c.HostConfig.CgroupParent != "" {
|
| ... | ... |
@@ -985,7 +1007,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e |
| 985 | 985 |
opts = append(opts, coci.WithReadonlyPaths(c.HostConfig.ReadonlyPaths)) |
| 986 | 986 |
} |
| 987 | 987 |
if daemon.configStore.Rootless {
|
| 988 |
- opts = append(opts, WithRootless) |
|
| 988 |
+ opts = append(opts, WithRootless(daemon)) |
|
| 989 | 989 |
} |
| 990 | 990 |
return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
|
| 991 | 991 |
ID: c.ID, |
| ... | ... |
@@ -8,10 +8,12 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// ToRootless converts spec to be compatible with "rootless" runc. |
| 11 |
-// * Remove cgroups (will be supported in separate PR when delegation permission is configured) |
|
| 11 |
+// * Remove non-supported cgroups |
|
| 12 | 12 |
// * Fix up OOMScoreAdj |
| 13 |
-func ToRootless(spec *specs.Spec) error {
|
|
| 14 |
- return toRootless(spec, getCurrentOOMScoreAdj()) |
|
| 13 |
+// |
|
| 14 |
+// v2Controllers should be non-nil only if running with v2 and systemd. |
|
| 15 |
+func ToRootless(spec *specs.Spec, v2Controllers []string) error {
|
|
| 16 |
+ return toRootless(spec, v2Controllers, getCurrentOOMScoreAdj()) |
|
| 15 | 17 |
} |
| 16 | 18 |
|
| 17 | 19 |
func getCurrentOOMScoreAdj() int {
|
| ... | ... |
@@ -26,10 +28,44 @@ func getCurrentOOMScoreAdj() int {
|
| 26 | 26 |
return i |
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 |
-func toRootless(spec *specs.Spec, currentOOMScoreAdj int) error {
|
|
| 30 |
- // Remove cgroup settings. |
|
| 31 |
- spec.Linux.Resources = nil |
|
| 32 |
- spec.Linux.CgroupsPath = "" |
|
| 29 |
+func toRootless(spec *specs.Spec, v2Controllers []string, currentOOMScoreAdj int) error {
|
|
| 30 |
+ if len(v2Controllers) == 0 {
|
|
| 31 |
+ // Remove cgroup settings. |
|
| 32 |
+ spec.Linux.Resources = nil |
|
| 33 |
+ spec.Linux.CgroupsPath = "" |
|
| 34 |
+ } else {
|
|
| 35 |
+ if spec.Linux.Resources != nil {
|
|
| 36 |
+ m := make(map[string]struct{})
|
|
| 37 |
+ for _, s := range v2Controllers {
|
|
| 38 |
+ m[s] = struct{}{}
|
|
| 39 |
+ } |
|
| 40 |
+ // Remove devices: https://github.com/containers/crun/issues/255 |
|
| 41 |
+ spec.Linux.Resources.Devices = nil |
|
| 42 |
+ if _, ok := m["memory"]; !ok {
|
|
| 43 |
+ spec.Linux.Resources.Memory = nil |
|
| 44 |
+ } |
|
| 45 |
+ if _, ok := m["cpu"]; !ok {
|
|
| 46 |
+ spec.Linux.Resources.CPU = nil |
|
| 47 |
+ } |
|
| 48 |
+ if _, ok := m["cpuset"]; !ok {
|
|
| 49 |
+ if spec.Linux.Resources.CPU != nil {
|
|
| 50 |
+ spec.Linux.Resources.CPU.Cpus = "" |
|
| 51 |
+ spec.Linux.Resources.CPU.Mems = "" |
|
| 52 |
+ } |
|
| 53 |
+ } |
|
| 54 |
+ if _, ok := m["pids"]; !ok {
|
|
| 55 |
+ spec.Linux.Resources.Pids = nil |
|
| 56 |
+ } |
|
| 57 |
+ if _, ok := m["io"]; !ok {
|
|
| 58 |
+ spec.Linux.Resources.BlockIO = nil |
|
| 59 |
+ } |
|
| 60 |
+ if _, ok := m["rdma"]; !ok {
|
|
| 61 |
+ spec.Linux.Resources.Rdma = nil |
|
| 62 |
+ } |
|
| 63 |
+ spec.Linux.Resources.HugepageLimits = nil |
|
| 64 |
+ spec.Linux.Resources.Network = nil |
|
| 65 |
+ } |
|
| 66 |
+ } |
|
| 33 | 67 |
|
| 34 | 68 |
if spec.Process.OOMScoreAdj != nil && *spec.Process.OOMScoreAdj < currentOOMScoreAdj {
|
| 35 | 69 |
*spec.Process.OOMScoreAdj = currentOOMScoreAdj |