docker: set default cpu cfs period (#6737)

* docker: set default cpu cfs period

Co-Authored-By: Michael Schurter <mschurter@hashicorp.com>
This commit is contained in:
Nick Ethier
2019-11-19 19:05:15 -05:00
committed by GitHub
parent 635f67b507
commit ac239a3f0b
4 changed files with 116 additions and 63 deletions

View File

@@ -276,7 +276,10 @@ var (
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
"command": hclspec.NewAttr("command", "string", false),
"cpu_hard_limit": hclspec.NewAttr("cpu_hard_limit", "bool", false),
"cpu_cfs_period": hclspec.NewAttr("cpu_cfs_period", "number", false),
"cpu_cfs_period": hclspec.NewDefault(
hclspec.NewAttr("cpu_cfs_period", "number", false),
hclspec.NewLiteral(`100000`),
),
"devices": hclspec.NewBlockList("devices", hclspec.NewObject(map[string]*hclspec.Spec{
"host_path": hclspec.NewAttr("host_path", "string", false),
"container_path": hclspec.NewAttr("container_path", "string", false),

View File

@@ -20,9 +20,10 @@ func TestConfig_ParseHCL(t *testing.T) {
image = "redis:3.2"
}`,
&TaskConfig{
Image: "redis:3.2",
Devices: []DockerDevice{},
Mounts: []DockerMount{},
Image: "redis:3.2",
Devices: []DockerDevice{},
Mounts: []DockerMount{},
CPUCFSPeriod: 100000,
},
},
}
@@ -51,36 +52,40 @@ func TestConfig_ParseJSON(t *testing.T) {
name: "nil values for blocks are safe",
input: `{"Config": {"image": "bash:3", "mounts": null}}`,
expected: TaskConfig{
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
CPUCFSPeriod: 100000,
},
},
{
name: "nil values for 'volumes' field are safe",
input: `{"Config": {"image": "bash:3", "volumes": null}}`,
expected: TaskConfig{
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
CPUCFSPeriod: 100000,
},
},
{
name: "nil values for 'args' field are safe",
input: `{"Config": {"image": "bash:3", "args": null}}`,
expected: TaskConfig{
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
CPUCFSPeriod: 100000,
},
},
{
name: "nil values for string fields are safe",
input: `{"Config": {"image": "bash:3", "command": null}}`,
expected: TaskConfig{
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
Image: "bash:3",
Mounts: []DockerMount{},
Devices: []DockerDevice{},
CPUCFSPeriod: 100000,
},
},
}

View File

@@ -19,6 +19,8 @@ import (
"github.com/hashicorp/nomad/client/taskenv"
"github.com/hashicorp/nomad/client/testutil"
"github.com/hashicorp/nomad/devices/gpu/nvidia"
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
"github.com/hashicorp/nomad/helper/pluginutils/loader"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/helper/uuid"
@@ -103,6 +105,7 @@ func dockerTask(t *testing.T) (*drivers.TaskConfig, *TaskConfig, []int) {
LinuxResources: &drivers.LinuxResources{
CPUShares: 512,
MemoryLimitBytes: 256 * 1024 * 1024,
PercentTicks: float64(512) / float64(4096),
},
},
}
@@ -2498,3 +2501,30 @@ func TestDockerDriver_CreationIdempotent(t *testing.T) {
require.NoError(t, err)
})
}
// TestDockerDriver_CreateContainerConfig_CPUHardLimit asserts that a default
// CPU quota and period are set when cpu_hard_limit = true.
func TestDockerDriver_CreateContainerConfig_CPUHardLimit(t *testing.T) {
t.Parallel()
task, _, _ := dockerTask(t)
dh := dockerDriverHarness(t, nil)
driver := dh.Impl().(*Driver)
schema, _ := driver.TaskConfigSchema()
spec, _ := hclspecutils.Convert(schema)
val, _, _ := hclutils.ParseHclInterface(map[string]interface{}{
"image": "foo/bar",
"cpu_hard_limit": true,
}, spec, nil)
require.NoError(t, task.EncodeDriverConfig(val))
cfg := &TaskConfig{}
require.NoError(t, task.DecodeDriverConfig(cfg))
c, err := driver.createContainerConfig(task, cfg, "org/repo:0.1")
require.NoError(t, err)
require.NotZero(t, c.HostConfig.CPUQuota)
require.NotZero(t, c.HostConfig.CPUPeriod)
}

View File

@@ -42,9 +42,10 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -58,9 +59,10 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -73,10 +75,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
PidsLimit: 2,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
PidsLimit: 2,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -91,10 +94,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
PidsLimit: 2,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
PidsLimit: 2,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -107,10 +111,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -125,10 +130,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -141,10 +147,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -159,10 +166,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -177,11 +185,12 @@ func TestParseHclInterface_Hcl(t *testing.T) {
spec: dockerDecSpec,
vars: vars,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Args: []string{"world", "2"},
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Args: []string{"world", "2"},
PidsLimit: 4,
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -196,10 +205,11 @@ func TestParseHclInterface_Hcl(t *testing.T) {
}`),
spec: dockerDecSpec,
expected: &docker.TaskConfig{
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Image: "redis:3.2",
Args: []string{"foo", "bar"},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -220,8 +230,9 @@ func TestParseHclInterface_Hcl(t *testing.T) {
"foo": 1234,
"bar": 5678,
},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -244,8 +255,9 @@ func TestParseHclInterface_Hcl(t *testing.T) {
"foo": 1234,
"bar": 5678,
},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -280,7 +292,8 @@ func TestParseHclInterface_Hcl(t *testing.T) {
ContainerPath: "/dev/xvdd",
},
},
Mounts: []docker.DockerMount{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -309,8 +322,9 @@ func TestParseHclInterface_Hcl(t *testing.T) {
"tag": "driver-test",
},
},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
Devices: []docker.DockerDevice{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},
@@ -347,7 +361,8 @@ func TestParseHclInterface_Hcl(t *testing.T) {
ContainerPath: "/dev/xvdd",
},
},
Mounts: []docker.DockerMount{},
Mounts: []docker.DockerMount{},
CPUCFSPeriod: 100000,
},
expectedType: &docker.TaskConfig{},
},