Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cpuset_cpus to docker driver. #8291

Merged
merged 3 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ var (
"cap_add": hclspec.NewAttr("cap_add", "list(string)", false),
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
"command": hclspec.NewAttr("command", "string", false),
"cpuset_cpus": hclspec.NewAttr("cpuset_cpus", "string", false),
"cpu_hard_limit": hclspec.NewAttr("cpu_hard_limit", "bool", false),
"cpu_cfs_period": hclspec.NewDefault(
hclspec.NewAttr("cpu_cfs_period", "number", false),
Expand Down Expand Up @@ -407,6 +408,7 @@ type TaskConfig struct {
Command string `codec:"command"`
CPUCFSPeriod int64 `codec:"cpu_cfs_period"`
CPUHardLimit bool `codec:"cpu_hard_limit"`
CPUSetCPUs string `codec:"cpuset_cpus"`
Devices []DockerDevice `codec:"devices"`
DNSSearchDomains []string `codec:"dns_search_domains"`
DNSOptions []string `codec:"dns_options"`
Expand Down
6 changes: 6 additions & 0 deletions drivers/docker/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,12 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T
Runtime: containerRuntime,
}

// This translates to docker create/run --cpuset-cpus option.
// --cpuset-cpus limit the specific CPUs or cores a container can use.
if driverConfig.CPUSetCPUs != "" {
hostConfig.CPUSetCPUs = driverConfig.CPUSetCPUs
}

// Calculate CPU Quota
// cfs_quota_us is the time per core, so we must
// multiply the time by the number of cores available
Expand Down
47 changes: 47 additions & 0 deletions drivers/docker/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,53 @@ func TestDockerDriver_DNS(t *testing.T) {

}

func TestDockerDriver_CPUSetCPUs(t *testing.T) {
if !tu.IsCI() {
t.Parallel()
}
testutil.DockerCompatible(t)
if runtime.GOOS == "windows" {
t.Skip("Windows does not support CPUSetCPUs.")
}

testCases := []struct {
Name string
CPUSetCPUs string
}{
{
Name: "Single CPU",
CPUSetCPUs: "0",
},
{
Name: "Comma separated list of CPUs",
CPUSetCPUs: "0,1",
},
{
Name: "Range of CPUs",
CPUSetCPUs: "0-1",
},
}

for _, testCase := range testCases {
t.Run(testCase.Name, func(t *testing.T) {
task, cfg, ports := dockerTask(t)
defer freeport.Return(ports)

cfg.CPUSetCPUs = testCase.CPUSetCPUs
require.NoError(t, task.EncodeConcreteDriverConfig(cfg))

client, d, handle, cleanup := dockerSetup(t, task, nil)
defer cleanup()
require.NoError(t, d.WaitUntilStarted(task.ID, 5*time.Second))

container, err := client.InspectContainer(handle.containerID)
require.NoError(t, err)

require.Equal(t, cfg.CPUSetCPUs, container.HostConfig.CPUSetCPUs)
})
}
}

func TestDockerDriver_MemoryHardLimit(t *testing.T) {
if !tu.IsCI() {
t.Parallel()
Expand Down
14 changes: 14 additions & 0 deletions website/pages/docs/drivers/docker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ The `docker` driver supports the following configuration in the job spec. Only
command = "my-command"
}
```
- `cpuset_cpus` - (Optional) CPUs in which to allow execution (0-3, 0,1).
Limit the specific CPUs or cores a container can use. A comma-separated list
or hyphen-separated range of CPUs a container can use, if you have more than
one CPU. The first CPU is numbered 0. A valid value might be 0-3 (to use the
first, second, third, and fourth CPU) or 1,3 (to use the second and fourth CPU).

Note: `cpuset_cpus` pins the workload to the CPUs but doesn't give the workload
exclusive access to those CPUs.

```hcl
config {
cpuset_cpus = "0-3"
}
```

- `dns_search_domains` - (Optional) A list of DNS search domains for the container
to use.
Expand Down