Skip to content

Commit ca4b518

Browse files
committed
rootless: support --exec-opt native.cgroupdriver=systemd
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 <[email protected]>
1 parent 31a86c4 commit ca4b518

4 files changed

Lines changed: 74 additions & 18 deletions

File tree

daemon/daemon_unix.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -599,15 +599,13 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn
599599
}
600600

601601
func (daemon *Daemon) getCgroupDriver() string {
602+
if UsingSystemd(daemon.configStore) {
603+
return cgroupSystemdDriver
604+
}
602605
if daemon.Rootless() {
603606
return cgroupNoneDriver
604607
}
605-
cgroupDriver := cgroupFsDriver
606-
607-
if UsingSystemd(daemon.configStore) {
608-
cgroupDriver = cgroupSystemdDriver
609-
}
610-
return cgroupDriver
608+
return cgroupFsDriver
611609
}
612610

613611
// getCD gets the raw value of the native.cgroupdriver option, if set.

daemon/oci_linux.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"io"
7+
"io/ioutil"
78
"os"
89
"os/exec"
910
"path/filepath"
@@ -84,8 +85,26 @@ func WithLibnetwork(daemon *Daemon, c *container.Container) coci.SpecOpts {
8485
}
8586

8687
// 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)
88+
func WithRootless(daemon *Daemon) coci.SpecOpts {
89+
return func(_ context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
90+
var v2Controllers []string
91+
if daemon.getCgroupDriver() == cgroupSystemdDriver {
92+
if !cgroups.IsCgroup2UnifiedMode() {
93+
return errors.New("rootless systemd driver doesn't support cgroup v1")
94+
}
95+
rootlesskitParentEUID := os.Getenv("ROOTLESSKIT_PARENT_EUID")
96+
if rootlesskitParentEUID == "" {
97+
return errors.New("$ROOTLESSKIT_PARENT_EUID is not set (requires RootlessKit v0.8.0)")
98+
}
99+
controllersPath := fmt.Sprintf("/sys/fs/cgroup/user.slice/user-%s.slice/cgroup.controllers", rootlesskitParentEUID)
100+
controllersFile, err := ioutil.ReadFile(controllersPath)
101+
if err != nil {
102+
return err
103+
}
104+
v2Controllers = strings.Fields(string(controllersFile))
105+
}
106+
return specconv.ToRootless(s, v2Controllers)
107+
}
89108
}
90109

91110
// WithOOMScore sets the oom score
@@ -760,6 +779,9 @@ func WithCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
760779
useSystemd := UsingSystemd(daemon.configStore)
761780
if useSystemd {
762781
parent = "system.slice"
782+
if daemon.configStore.Rootless {
783+
parent = "user.slice"
784+
}
763785
}
764786

765787
if c.HostConfig.CgroupParent != "" {
@@ -985,7 +1007,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
9851007
opts = append(opts, coci.WithReadonlyPaths(c.HostConfig.ReadonlyPaths))
9861008
}
9871009
if daemon.configStore.Rootless {
988-
opts = append(opts, WithRootless)
1010+
opts = append(opts, WithRootless(daemon))
9891011
}
9901012
return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
9911013
ID: c.ID,

hack/dockerfile/install/rootlesskit.installer

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22

3-
# v0.7.1
4-
: ${ROOTLESSKIT_COMMIT:=76c4e26750da3986fa0e741464fbf0fcd55bea71}
3+
# v0.8.0
4+
: ${ROOTLESSKIT_COMMIT:=ce88a431e6a7cf891ebb68b10bfc6a5724b9ae72}
55

66
install_rootlesskit() {
77
case "$1" in

rootless/specconv/specconv_linux.go

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import (
88
)
99

1010
// 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
1212
// * 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())
1517
}
1618

1719
func getCurrentOOMScoreAdj() int {
@@ -26,10 +28,44 @@ func getCurrentOOMScoreAdj() int {
2628
return i
2729
}
2830

29-
func toRootless(spec *specs.Spec, currentOOMScoreAdj int) error {
30-
// Remove cgroup settings.
31-
spec.Linux.Resources = nil
32-
spec.Linux.CgroupsPath = ""
31+
func toRootless(spec *specs.Spec, v2Controllers []string, currentOOMScoreAdj int) error {
32+
if len(v2Controllers) == 0 {
33+
// Remove cgroup settings.
34+
spec.Linux.Resources = nil
35+
spec.Linux.CgroupsPath = ""
36+
} else {
37+
if spec.Linux.Resources != nil {
38+
m := make(map[string]struct{})
39+
for _, s := range v2Controllers {
40+
m[s] = struct{}{}
41+
}
42+
// Remove devices: https://github.com/containers/crun/issues/255
43+
spec.Linux.Resources.Devices = nil
44+
if _, ok := m["memory"]; !ok {
45+
spec.Linux.Resources.Memory = nil
46+
}
47+
if _, ok := m["cpu"]; !ok {
48+
spec.Linux.Resources.CPU = nil
49+
}
50+
if _, ok := m["cpuset"]; !ok {
51+
if spec.Linux.Resources.CPU != nil {
52+
spec.Linux.Resources.CPU.Cpus = ""
53+
spec.Linux.Resources.CPU.Mems = ""
54+
}
55+
}
56+
if _, ok := m["pids"]; !ok {
57+
spec.Linux.Resources.Pids = nil
58+
}
59+
if _, ok := m["io"]; !ok {
60+
spec.Linux.Resources.BlockIO = nil
61+
}
62+
if _, ok := m["rdma"]; !ok {
63+
spec.Linux.Resources.Rdma = nil
64+
}
65+
spec.Linux.Resources.HugepageLimits = nil
66+
spec.Linux.Resources.Network = nil
67+
}
68+
}
3369

3470
if spec.Process.OOMScoreAdj != nil && *spec.Process.OOMScoreAdj < currentOOMScoreAdj {
3571
*spec.Process.OOMScoreAdj = currentOOMScoreAdj

0 commit comments

Comments
 (0)