drivers/raw_exec: enable setting cgroup override values (#20481)

* drivers/raw_exec: enable setting cgroup override values

This PR enables configuration of cgroup override values on the `raw_exec`
task driver. WARNING: setting cgroup override values eliminates any
gauruntee Nomad can make about resource availability for *any* task on
the client node.

For cgroup v2 systems, set a single unified cgroup path using `cgroup_v2_override`.
The path may be either absolute or relative to the cgroup root.

config {
  cgroup_v2_override = "custom.slice/app.scope"
}

or

config {
  cgroup_v2_override = "/sys/fs/cgroup/custom.slice/app.scope"
}

For cgroup v1 systems, set a per-controller path for each controller using
`cgroup_v1_override`. The path(s) may be either absolute or relative to
the controller root.

config {
  cgroup_v1_override = {
    "pids": "custom/app",
    "cpuset": "custom/app",
  }
}

or

config {
  cgroup_v1_override = {
    "pids": "/sys/fs/cgroup/pids/custom/app",
    "cpuset": "/sys/fs/cgroup/cpuset/custom/app",
  }
}

* drivers/rawexec: ensure only one of v1/v2 cgroup override is set

* drivers/raw_exec: executor should error if setting cgroup does not work

* drivers/raw_exec: create cgroups in raw_exec tests

* drivers/raw_exec: ensure we fail to start if custom cgroup set and non-root

* move custom cgroup func into shared file

---------

Co-authored-by: Michael Schurter <mschurter@hashicorp.com>
This commit is contained in:
Seth Hoenig
2024-05-07 19:46:27 -04:00
committed by GitHub
parent 5041460043
commit 14a022cbc0
16 changed files with 430 additions and 84 deletions

View File

@@ -134,7 +134,9 @@ func (e *UniversalExecutor) configureResourceContainer(command *ExecCommand, pid
// manually configure cgroup for cpu / memory constraints
switch cgroupslib.GetMode() {
case cgroupslib.CG1:
e.configureCG1(cgroup, command)
if err := e.configureCG1(cgroup, command); err != nil {
return nil, err
}
cgCleanup = e.enterCG1(cgroup, command.CpusetCgroup())
default:
e.configureCG2(cgroup, command)
@@ -189,11 +191,26 @@ func (e *UniversalExecutor) enterCG1(statsCgroup, cpusetCgroup string) func() {
}
}
func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) {
func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) error {
// some drivers like qemu entirely own resource management
if command.Resources == nil || command.Resources.LinuxResources == nil {
return
return nil
}
// if custom cgroups are set join those instead of configuring the /nomad
// cgroups we are not going to use
if len(e.command.OverrideCgroupV1) > 0 {
pid := unix.Getpid()
for controller, path := range e.command.OverrideCgroupV1 {
absPath := cgroupslib.CustomPathCG1(controller, path)
ed := cgroupslib.OpenPath(absPath)
err := ed.Write("cgroup.procs", strconv.Itoa(pid))
if err != nil {
e.logger.Error("unable to write to custom cgroup", "error", err)
return fmt.Errorf("unable to write to custom cgroup: %v", err)
}
}
return nil
}
// write memory limits
@@ -222,10 +239,11 @@ func (e *UniversalExecutor) configureCG1(cgroup string, command *ExecCommand) {
ed = cgroupslib.OpenPath(cpusetPath)
_ = ed.Write("cpuset.cpus", cpuSet)
}
return nil
}
func (e *UniversalExecutor) configureCG2(cgroup string, command *ExecCommand) {
// some drivers like qemu entirely own resource management
if command.Resources == nil || command.Resources.LinuxResources == nil {
return