Skip to content

Commit

Permalink
executor: limit the value of CPU shares (hashicorp#19935)
Browse files Browse the repository at this point in the history
The value for the executor cgroup CPU weight must be within the limits
imposed by the Linux kernel.

Nomad used the task `resource.cpu`, an unbounded value, directly as the
cgroup CPU weight, causing it to potentially go outside the imposed
values.

This commit clamps the CPU shares values to be within the limits
allowed.

Co-authored-by: Tim Gross <tgross@hashicorp.com>
  • Loading branch information
2 people authored and nvanthao committed Mar 1, 2024
1 parent a71b400 commit 003b687
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .changelog/19935.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
client: Ensure the value for CPU shares are within the allowed range
```
29 changes: 27 additions & 2 deletions drivers/shared/executor/executor_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ import (
"golang.org/x/sys/unix"
)

const (
// CPU shares limits are defined by the Linux kernel.
// https://github.com/torvalds/linux/blob/0dd3ee31125508cd67f7e7172247f05b7fd1753a/kernel/sched/sched.h#L409-L418
MinCPUShares = 2
MaxCPUShares = 262_144
)

var (
// ExecutorCgroupV1MeasuredMemStats is the list of memory stats captured by the executor with cgroup-v1
ExecutorCgroupV1MeasuredMemStats = []string{"RSS", "Cache", "Swap", "Usage", "Max Usage", "Kernel Usage", "Kernel Max Usage"}
Expand Down Expand Up @@ -717,7 +724,7 @@ func (l *LibcontainerExecutor) configureCgroupMemory(cfg *runc.Config, command *

func (l *LibcontainerExecutor) configureCG1(cfg *runc.Config, command *ExecCommand, cgroup string) error {

cpuShares := command.Resources.LinuxResources.CPUShares
cpuShares := l.clampCpuShares(command.Resources.LinuxResources.CPUShares)
cpusetPath := command.Resources.LinuxResources.CpusetCgroupPath
cpuCores := command.Resources.LinuxResources.CpusetCpus

Expand Down Expand Up @@ -749,7 +756,7 @@ func (l *LibcontainerExecutor) cpusetCG1(cpusetCgroupPath, cores string) error {
}

func (l *LibcontainerExecutor) configureCG2(cfg *runc.Config, command *ExecCommand, cg string) error {
cpuShares := command.Resources.LinuxResources.CPUShares
cpuShares := l.clampCpuShares(command.Resources.LinuxResources.CPUShares)
cpuCores := command.Resources.LinuxResources.CpusetCpus

// Set the v2 specific unified path
Expand Down Expand Up @@ -801,6 +808,24 @@ func (l *LibcontainerExecutor) newLibcontainerConfig(command *ExecCommand) (*run
return cfg, nil
}

func (l *LibcontainerExecutor) clampCpuShares(shares int64) int64 {
if shares < MinCPUShares {
l.logger.Warn(
"task CPU is lower than minimum allowed, using minimum value instead",
"task_cpu", shares, "min", MinCPUShares,
)
return MinCPUShares
}
if shares > MaxCPUShares {
l.logger.Warn(
"task CPU is greater than maximum allowed, using maximum value instead",
"task_cpu", shares, "max", MaxCPUShares,
)
return MaxCPUShares
}
return shares
}

// cmdDevices converts a list of driver.DeviceConfigs into excutor.Devices.
func cmdDevices(driverDevices []*drivers.DeviceConfig) ([]*devices.Device, error) {
if len(driverDevices) == 0 {
Expand Down

0 comments on commit 003b687

Please sign in to comment.