Skip to content

Commit

Permalink
Initial v2 resources.unified systemd support
Browse files Browse the repository at this point in the history
In case systemd is used as cgroups manager, and a user sets some
resources using unified resource map (as per [1]), systemd is not
aware of any parameters, so there will be a discrepancy between
the cgroupfs state and systemd unit state.

Let's try to fix that by converting known unified resources to systemd
properties.

Currently, this is only implemented for pids.max as a POC.

Some other parameters (that might or might not have systemd unit
property equivalents) are:

$ ls -l | grep w-
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.freeze
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.max.depth
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.max.descendants
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.procs
-rw-r--r--. 1 root root 0 Oct 21 09:43 cgroup.subtree_control
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.threads
-rw-r--r--. 1 root root 0 Oct 10 13:57 cgroup.type
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.max
-rw-r--r--. 1 root root 0 Oct 10 13:57 cpu.pressure
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.cpus
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.cpus.partition
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpuset.mems
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.weight
-rw-r--r--. 1 root root 0 Oct 22 10:30 cpu.weight.nice
-rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.1GB.max
-rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.1GB.rsvd.max
-rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.2MB.max
-rw-r--r--. 1 root root 0 Oct 22 10:30 hugetlb.2MB.rsvd.max
-rw-r--r--. 1 root root 0 Oct 22 10:30 io.bfq.weight
-rw-r--r--. 1 root root 0 Oct 22 10:30 io.latency
-rw-r--r--. 1 root root 0 Oct 22 10:30 io.max
-rw-r--r--. 1 root root 0 Oct 10 13:57 io.pressure
-rw-r--r--. 1 root root 0 Oct 22 10:30 io.weight
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.high
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.low
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.max
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.min
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.oom.group
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.pressure
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.swap.high
-rw-r--r--. 1 root root 0 Oct 10 13:57 memory.swap.max

Surely, it is a manual conversion for every such case...

[1] opencontainers/runtime-spec#1040

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin committed Oct 30, 2020
1 parent cf6c074 commit 5032a16
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 5 deletions.
44 changes: 44 additions & 0 deletions libcontainer/cgroups/systemd/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package systemd

import (
"fmt"
"math"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -34,6 +36,39 @@ func NewUnifiedManager(config *configs.Cgroup, path string, rootless bool) cgrou
}
}

// unifiedResToSystemdProps tries to convert from Cgroup.Resources.Unified
// key/value map to systemd unit properties. This is on a best-effort basis,
// i.e. all the unknown parameters are ignored.
func unifiedResToSystemdProps(res map[string]string) (props []systemdDbus.Property, _ error) {
for k, v := range res {
if strings.Contains(k, "/") {
return nil, fmt.Errorf("unified resource %q must be a file name (no slashes)", k)
}
sk := strings.SplitN(k, ".", 2)
if len(sk) != 2 {
return nil, fmt.Errorf("unified resource %q must be in the form CONTROLLER.PARAMETER", k)
}
switch k {
case "pids.max":
num := uint64(math.MaxUint64)
if v != "max" {
var err error
num, err = strconv.ParseUint(v, 10, 64)
if err != nil {
return nil, fmt.Errorf("unified resource %q value conversion error: %w", k, err)
}
}
props = append(props,
newProp("TasksAccounting", true),
newProp("TasksMax", uint64(num)))
default:
logrus.Debugf("skipping unknown unified resource %q=%q", k, v)
}
}

return props, nil
}

func genV2ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]systemdDbus.Property, error) {
var properties []systemdDbus.Property
r := c.Resources
Expand Down Expand Up @@ -82,6 +117,15 @@ func genV2ResourcesProperties(c *configs.Cgroup, conn *systemdDbus.Conn) ([]syst

// ignore r.KernelMemory

// convert Resources.Unified map to systemd properties
if r.Unified != nil {
unifiedProps, err := unifiedResToSystemdProps(r.Unified)
if err != nil {
return nil, err
}
properties = append(properties, unifiedProps...)
}

return properties, nil
}

Expand Down
21 changes: 16 additions & 5 deletions tests/integration/cgroups.bats
Original file line number Diff line number Diff line change
Expand Up @@ -216,16 +216,22 @@ function setup() {
echo "$output" | grep -q '^memory.max:10485760$'
echo "$output" | grep -q '^pids.max:99$'
echo "$output" | grep -q '^cpu.max:10000 100000$'

check_systemd_value "TasksMax" 99
}

@test "runc run (cgroup v2 resources.unified override)" {
requires root cgroups_v2

set_cgroups_path "$BUSYBOX_BUNDLE"
update_config ' .linux.resources.memory |= {"limit": 33554432}
| .linux.resources.memorySwap |= {"limit": 33554432}
| .linux.resources.unified |=
{"memory.min": "131072", "memory.max": "10485760" }' \
"$BUSYBOX_BUNDLE"
update_config ' .linux.resources.memory |= { "limit": 33554432 }
| .linux.resources.memorySwap |= { "limit": 33554432 }
| .linux.resources.pids |= { "limit": 20 }
| .linux.resources.unified |= {
"memory.min": "131072",
"memory.max": "10485760",
"pids.max": "42"
}' "$BUSYBOX_BUNDLE"

runc run -d --console-socket "$CONSOLE_SOCKET" test_cgroups_unified
[ "$status" -eq 0 ]
Expand All @@ -237,4 +243,9 @@ function setup() {
runc exec test_cgroups_unified cat /sys/fs/cgroup/memory.max
[ "$status" -eq 0 ]
[ "$output" = '10485760' ]

runc exec test_cgroups_unified cat /sys/fs/cgroup/pids.max
[ "$status" -eq 0 ]
[ "$output" = '42' ]
check_systemd_value "TasksMax" 42
}

0 comments on commit 5032a16

Please sign in to comment.