mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
executor: limit the value of CPU shares (#19935)
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>
This commit is contained in:
3
.changelog/19935.txt
Normal file
3
.changelog/19935.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug
|
||||||
|
client: Ensure the value for CPU shares are within the allowed range
|
||||||
|
```
|
||||||
@@ -43,6 +43,13 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"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 (
|
var (
|
||||||
// ExecutorCgroupV1MeasuredMemStats is the list of memory stats captured by the executor with cgroup-v1
|
// 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"}
|
ExecutorCgroupV1MeasuredMemStats = []string{"RSS", "Cache", "Swap", "Usage", "Max Usage", "Kernel Usage", "Kernel Max Usage"}
|
||||||
@@ -717,7 +724,7 @@ func (l *LibcontainerExecutor) configureCgroupMemory(cfg *runc.Config, command *
|
|||||||
|
|
||||||
func (l *LibcontainerExecutor) configureCG1(cfg *runc.Config, command *ExecCommand, cgroup string) error {
|
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
|
cpusetPath := command.Resources.LinuxResources.CpusetCgroupPath
|
||||||
cpuCores := command.Resources.LinuxResources.CpusetCpus
|
cpuCores := command.Resources.LinuxResources.CpusetCpus
|
||||||
|
|
||||||
@@ -749,7 +756,7 @@ func (l *LibcontainerExecutor) cpusetCG1(cpusetCgroupPath, cores string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *LibcontainerExecutor) configureCG2(cfg *runc.Config, command *ExecCommand, cg 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
|
cpuCores := command.Resources.LinuxResources.CpusetCpus
|
||||||
|
|
||||||
// Set the v2 specific unified path
|
// Set the v2 specific unified path
|
||||||
@@ -801,6 +808,24 @@ func (l *LibcontainerExecutor) newLibcontainerConfig(command *ExecCommand) (*run
|
|||||||
return cfg, nil
|
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.
|
// cmdDevices converts a list of driver.DeviceConfigs into excutor.Devices.
|
||||||
func cmdDevices(driverDevices []*drivers.DeviceConfig) ([]*devices.Device, error) {
|
func cmdDevices(driverDevices []*drivers.DeviceConfig) ([]*devices.Device, error) {
|
||||||
if len(driverDevices) == 0 {
|
if len(driverDevices) == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user