mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
During Nomad client initialization with cgroups v2, we assert that the required cgroup controllers are available in the root `cgroup.subtree_control` file by idempotently writing to the file. But if Nomad is running with delegated cgroups, this will fail file permissions checks even if the subtree control file already has the controllers we need. Update the initialization to first check if the controllers are missing before attempting to write to them. This allows cgroup delegation so long as the cluster administrator has pre-created a Nomad owned cgroups tree and set the `Delegate` option in a systemd override. If not, initialization fails in the existing way. Although this is one small step along the way to supporting a rootless Nomad client, running Nomad as non-root is still unsupported. I've intentionally not documented setting up cgroup delegation in this PR, as this PR is insufficient by itself to have a secure and properly-working rootless Nomad client. Ref: https://github.com/hashicorp/nomad/issues/18211 Ref: https://github.com/hashicorp/nomad/issues/13669
75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
//go:build linux
|
|
|
|
package cgroupslib
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/shoenig/test/must"
|
|
)
|
|
|
|
const (
|
|
cg1 = `
|
|
33 29 0:27 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k
|
|
34 25 0:28 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755
|
|
35 34 0:29 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:10 - cgroup2 cgroup2 rw,nsdelegate
|
|
36 34 0:30 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,xattr,name=systemd
|
|
`
|
|
|
|
cg2 = `
|
|
34 28 0:29 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k,inode64
|
|
35 24 0:30 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw,nsdelegate,memory_recursiveprot
|
|
36 24 0:31 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:10 - pstore pstore rw
|
|
37 24 0:32 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:11 - efivarfs efivarfs rw
|
|
`
|
|
)
|
|
|
|
func Test_scan(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
input string
|
|
exp Mode
|
|
}{
|
|
{
|
|
name: "v1",
|
|
input: cg1,
|
|
exp: CG1,
|
|
},
|
|
{
|
|
name: "v2",
|
|
input: cg2,
|
|
exp: CG2,
|
|
},
|
|
{
|
|
name: "empty",
|
|
input: "",
|
|
exp: OFF,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
in := strings.NewReader(tc.input)
|
|
result := scan(in)
|
|
must.Eq(t, tc.exp, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetMode(t *testing.T) {
|
|
mode := GetMode()
|
|
if os.Geteuid() == 0 {
|
|
ok := mode == CG1 || mode == CG2
|
|
must.True(t, ok)
|
|
} else {
|
|
// note: we can't test with a delegated cgroup without overwriting the
|
|
// package level root
|
|
must.Eq(t, OFF, mode)
|
|
}
|
|
}
|