diff --git a/daemon/container.go b/daemon/container.go index 5c7d3a4e52..b1e3060868 100644 --- a/daemon/container.go +++ b/daemon/container.go @@ -383,6 +383,7 @@ func populateCommand(c *Container, env []string) error { CpusetCpus: c.hostConfig.CpusetCpus, CpusetMems: c.hostConfig.CpusetMems, CpuQuota: c.hostConfig.CpuQuota, + BlkioWeight: c.hostConfig.BlkioWeight, Rlimits: rlimits, OomKillDisable: c.hostConfig.OomKillDisable, } diff --git a/daemon/daemon.go b/daemon/daemon.go index 130fcc46f2..03d6c59608 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -1184,6 +1184,9 @@ func (daemon *Daemon) verifyHostConfig(hostConfig *runconfig.HostConfig) ([]stri warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") hostConfig.CpuQuota = 0 } + if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { + return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") + } return warnings, nil } diff --git a/daemon/execdriver/driver.go b/daemon/execdriver/driver.go index 7827baa266..8a00350368 100644 --- a/daemon/execdriver/driver.go +++ b/daemon/execdriver/driver.go @@ -106,6 +106,7 @@ type Resources struct { CpusetCpus string `json:"cpuset_cpus"` CpusetMems string `json:"cpuset_mems"` CpuQuota int64 `json:"cpu_quota"` + BlkioWeight int64 `json:"blkio_weight"` Rlimits []*ulimit.Rlimit `json:"rlimits"` OomKillDisable bool `json:"oom_kill_disable"` } diff --git a/daemon/execdriver/driver_linux.go b/daemon/execdriver/driver_linux.go index cdaa93af34..f3bbca3e5c 100644 --- a/daemon/execdriver/driver_linux.go +++ b/daemon/execdriver/driver_linux.go @@ -54,6 +54,7 @@ func SetupCgroups(container *configs.Config, c *Command) error { container.Cgroups.CpusetCpus = c.Resources.CpusetCpus container.Cgroups.CpusetMems = c.Resources.CpusetMems container.Cgroups.CpuQuota = c.Resources.CpuQuota + container.Cgroups.BlkioWeight = c.Resources.BlkioWeight container.Cgroups.OomKillDisable = c.Resources.OomKillDisable } diff --git a/daemon/execdriver/lxc/lxc_template.go b/daemon/execdriver/lxc/lxc_template.go index 3d7b2b4999..55c05498c4 100644 --- a/daemon/execdriver/lxc/lxc_template.go +++ b/daemon/execdriver/lxc/lxc_template.go @@ -118,6 +118,9 @@ lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}} {{if .Resources.CpuQuota}} lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CpuQuota}} {{end}} +{{if .Resources.BlkioWeight}} +lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}} +{{end}} {{if .Resources.OomKillDisable}} lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}} {{end}} diff --git a/docs/man/docker-create.1.md b/docs/man/docker-create.1.md index d7bdd55789..98d2359ec2 100644 --- a/docs/man/docker-create.1.md +++ b/docs/man/docker-create.1.md @@ -8,6 +8,7 @@ docker-create - Create a new container **docker create** [**-a**|**--attach**[=*[]*]] [**--add-host**[=*[]*]] +[**--blkio-weight**[=*[BLKIO-WEIGHT]*]] [**-c**|**--cpu-shares**[=*0*]] [**--cap-add**[=*[]*]] [**--cap-drop**[=*[]*]] @@ -59,6 +60,9 @@ IMAGE [COMMAND] [ARG...] **--add-host**=[] Add a custom host-to-IP mapping (host:ip) +**--blkio-weight**=0 + Block IO weight (relative weight) accepts a weight value between 10 and 1000. + **-c**, **--cpu-shares**=0 CPU shares (relative weight) diff --git a/docs/man/docker-run.1.md b/docs/man/docker-run.1.md index ed331089af..c4f70fa389 100644 --- a/docs/man/docker-run.1.md +++ b/docs/man/docker-run.1.md @@ -8,6 +8,7 @@ docker-run - Run a command in a new container **docker run** [**-a**|**--attach**[=*[]*]] [**--add-host**[=*[]*]] +[**--blkio-weight**[=*[BLKIO-WEIGHT]*]] [**-c**|**--cpu-shares**[=*0*]] [**--cap-add**[=*[]*]] [**--cap-drop**[=*[]*]] @@ -86,6 +87,9 @@ each of stdin, stdout, and stderr. Add a line to /etc/hosts. The format is hostname:ip. The **--add-host** option can be set multiple times. +**--blkio-weight**=0 + Block IO weight (relative weight) accepts a weight value between 10 and 1000. + **-c**, **--cpu-shares**=0 CPU shares (relative weight) diff --git a/docs/sources/reference/api/docker_remote_api_v1.19.md b/docs/sources/reference/api/docker_remote_api_v1.19.md index 1a321fe736..2f40cb6fa6 100644 --- a/docs/sources/reference/api/docker_remote_api_v1.19.md +++ b/docs/sources/reference/api/docker_remote_api_v1.19.md @@ -149,6 +149,7 @@ Create a container "CpuShares": 512, "CpusetCpus": "0,1", "CpusetMems": "0,1", + "BlkioWeight": 300, "OomKillDisable": false, "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, "PublishAllPorts": false, @@ -195,6 +196,7 @@ Json Parameters: - **Cpuset** - The same as CpusetCpus, but deprecated, please don't use. - **CpusetCpus** - String value containing the cgroups CpusetCpus to use. - **CpusetMems** - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. +- **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. - **AttachStdin** - Boolean value, attaches to stdin. - **AttachStdout** - Boolean value, attaches to stdout. @@ -341,6 +343,7 @@ Return low-level information on the container `id` "ExecIDs": null, "HostConfig": { "Binds": null, + "BlkioWeight": 0, "CapAdd": null, "CapDrop": null, "ContainerIDFile": "", diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 5a92739529..60c258f889 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -941,6 +941,7 @@ Creates a new container. -a, --attach=[] Attach to STDIN, STDOUT or STDERR --add-host=[] Add a custom host-to-IP mapping (host:ip) + --blkio-weight=0 Block IO weight (relative weight) -c, --cpu-shares=0 CPU shares (relative weight) --cap-add=[] Add Linux capabilities --cap-drop=[] Drop Linux capabilities @@ -1898,6 +1899,7 @@ To remove an image using its digest: -a, --attach=[] Attach to STDIN, STDOUT or STDERR --add-host=[] Add a custom host-to-IP mapping (host:ip) + --blkio-weight=0 Block IO weight (relative weight) -c, --cpu-shares=0 CPU shares (relative weight) --cap-add=[] Add Linux capabilities --cap-drop=[] Drop Linux capabilities diff --git a/docs/sources/reference/run.md b/docs/sources/reference/run.md index 6d9c314dd7..bcbbe4a9a2 100644 --- a/docs/sources/reference/run.md +++ b/docs/sources/reference/run.md @@ -483,6 +483,7 @@ container: --cpuset-cpus="": CPUs in which to allow execution (0-3, 0,1) --cpuset-mems="": Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. --cpu-quota=0: Limit the CPU CFS (Completely Fair Scheduler) quota + --blkio-weight=0: Block IO weight (relative weight) accepts a weight value between 10 and 1000. --oom-kill-disable=true|false: Whether to disable OOM Killer for the container or not. ### Memory constraints @@ -654,6 +655,30 @@ Linux Scheduler used by the kernel. Set this value to 50000 to limit the contain to 50% of a CPU resource. For multiple CPUs, adjust the `--cpu-quota` as necessary. For more information, see the [CFS documentation on bandwidth limiting](https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt). +### Block IO bandwidth (Blkio) constraint + +By default, all containers get the same proportion of block IO bandwidth +(blkio). This proportion is 500. To modify this proportion, change the +container's blkio weight relative to the weighting of all other running +containers using the `--blkio-weight` flag. + +The `--blkio-weight` flag can set the weighting to a value between 10 to 1000. +For example, the commands below create two containers with different blkio +weight: + + $ docker run -ti --name c1 --blkio-weight 300 ubuntu:14.04 /bin/bash + $ docker run -ti --name c2 --blkio-weight 600 ubuntu:14.04 /bin/bash + +If you do block IO in the two containers at the same time, by, for example: + + $ time dd if=/mnt/zerofile of=test.out bs=1M count=1024 oflag=direct + +You'll find that the proportion of time is the same as the proportion of blkio +weights of the two containers. + +> **Note:** The blkio weight setting is only available for direct IO. Buffered IO +> is not currently supported. + ## Runtime privilege, Linux capabilities, and LXC configuration --cap-add: Add Linux capabilities diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index cc4c9988ab..1eee6711ea 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -1158,6 +1158,20 @@ func (s *DockerSuite) TestRunWithCpusetMems(c *check.C) { } } +func (s *DockerSuite) TestRunWithBlkioWeight(c *check.C) { + cmd := exec.Command(dockerBinary, "run", "--blkio-weight", "300", "busybox", "true") + if code, err := runCommand(cmd); err != nil || code != 0 { + c.Fatalf("container should run successfully with blkio-weight of 300: %s", err) + } +} + +func (s *DockerSuite) TestRunWithBlkioInvalidWeight(c *check.C) { + cmd := exec.Command(dockerBinary, "run", "--blkio-weight", "5", "busybox", "true") + if _, err := runCommand(cmd); err == nil { + c.Fatalf("run with invalid blkio-weight should failed") + } +} + func (s *DockerSuite) TestRunDeviceNumbers(c *check.C) { cmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "ls -l /dev/null") out, _, err := runCommandWithOutput(cmd) diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index d634b1ffb9..5c44de2290 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -168,7 +168,8 @@ type HostConfig struct { CpusetCpus string // CpusetCpus 0-2, 0,1 CpusetMems string // CpusetMems 0-2, 0,1 CpuQuota int64 - OomKillDisable bool // Whether to disable OOM Killer or not + BlkioWeight int64 // Block IO weight (relative weight vs. other containers) + OomKillDisable bool // Whether to disable OOM Killer or not Privileged bool PortBindings nat.PortMap Links []string diff --git a/runconfig/parse.go b/runconfig/parse.go index 63eeecc5f6..9d94ce9bf3 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -65,6 +65,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flCpusetCpus = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)") flCpusetMems = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)") flCpuQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS quota") + flBlkioWeight = cmd.Int64([]string{"-blkio-weight"}, 0, "Block IO (relative weight), between 10 and 1000") flNetMode = cmd.String([]string{"-net"}, "bridge", "Set the Network mode for the container") flMacAddress = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)") flIpcMode = cmd.String([]string{"-ipc"}, "", "IPC namespace to use") @@ -308,6 +309,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe CpusetCpus: *flCpusetCpus, CpusetMems: *flCpusetMems, CpuQuota: *flCpuQuota, + BlkioWeight: *flBlkioWeight, OomKillDisable: *flOomKillDisable, Privileged: *flPrivileged, PortBindings: portBindings,