From 843084b08b521a70baf9284ec4e23e941ab38367 Mon Sep 17 00:00:00 2001 From: Ma Shimiao Date: Wed, 8 Jul 2015 19:06:48 +0800 Subject: [PATCH] Add support for blkio read/write iops device Signed-off-by: Ma Shimiao --- contrib/completion/bash/docker | 2 + contrib/completion/zsh/_docker | 2 + daemon/container_operations_unix.go | 36 ++++++++++------ daemon/daemon_unix.go | 41 ++++++++++++++++++- daemon/daemon_windows.go | 8 ++++ daemon/execdriver/driver_unix.go | 28 +++++++------ docs/reference/api/docker_remote_api.md | 2 + docs/reference/api/docker_remote_api_v1.22.md | 12 +++++- docs/reference/commandline/create.md | 2 + docs/reference/commandline/run.md | 2 + docs/reference/run.md | 29 ++++++++++--- integration-cli/docker_cli_run_unix_test.go | 12 ++++++ man/docker-create.1.md | 8 ++++ man/docker-run.1.md | 8 ++++ opts/opts.go | 23 +++++++++++ pkg/sysinfo/sysinfo.go | 6 +++ pkg/sysinfo/sysinfo_linux.go | 19 +++++++-- runconfig/hostconfig.go | 34 +++++++-------- runconfig/parse.go | 40 ++++++++++-------- 19 files changed, 244 insertions(+), 70 deletions(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 4a1b2f39e4..67569506ff 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -1389,7 +1389,9 @@ _docker_run() { --cpu-shares --device --device-read-bps + --device-read-iops --device-write-bps + --device-write-iops --dns --dns-opt --dns-search diff --git a/contrib/completion/zsh/_docker b/contrib/completion/zsh/_docker index 142d87036f..a8c5530142 100644 --- a/contrib/completion/zsh/_docker +++ b/contrib/completion/zsh/_docker @@ -469,7 +469,9 @@ __docker_subcommand() { "($help)--cidfile=[Write the container ID to the file]:CID file:_files" "($help)*--device=[Add a host device to the container]:device:_files" "($help)*--device-read-bps=[Limit the read rate (bytes per second) from a device]:device:IO rate: " + "($help)*--device-read-iops=[Limit the read rate (IO per second) from a device]:device:IO rate: " "($help)*--device-write-bps=[Limit the write rate (bytes per second) to a device]:device:IO rate: " + "($help)*--device-write-iops=[Limit the write rate (IO per second) to a device]:device:IO rate: " "($help)*--dns=[Set custom DNS servers]:DNS server: " "($help)*--dns-opt=[Set custom DNS options]:DNS option: " "($help)*--dns-search=[Set custom DNS search domains]:DNS domains: " diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index c965cbb66b..18de732983 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -174,6 +174,16 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro return err } + readIOpsDevice, err := getBlkioReadIOpsDevices(c.HostConfig) + if err != nil { + return err + } + + writeIOpsDevice, err := getBlkioWriteIOpsDevices(c.HostConfig) + if err != nil { + return err + } + for _, limit := range ulimits { rl, err := limit.GetRlimit() if err != nil { @@ -189,18 +199,20 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro CPUShares: c.HostConfig.CPUShares, BlkioWeight: c.HostConfig.BlkioWeight, }, - MemorySwap: c.HostConfig.MemorySwap, - KernelMemory: c.HostConfig.KernelMemory, - CpusetCpus: c.HostConfig.CpusetCpus, - CpusetMems: c.HostConfig.CpusetMems, - CPUPeriod: c.HostConfig.CPUPeriod, - CPUQuota: c.HostConfig.CPUQuota, - Rlimits: rlimits, - BlkioWeightDevice: weightDevices, - BlkioThrottleReadBpsDevice: readBpsDevice, - BlkioThrottleWriteBpsDevice: writeBpsDevice, - OomKillDisable: c.HostConfig.OomKillDisable, - MemorySwappiness: -1, + MemorySwap: c.HostConfig.MemorySwap, + KernelMemory: c.HostConfig.KernelMemory, + CpusetCpus: c.HostConfig.CpusetCpus, + CpusetMems: c.HostConfig.CpusetMems, + CPUPeriod: c.HostConfig.CPUPeriod, + CPUQuota: c.HostConfig.CPUQuota, + Rlimits: rlimits, + BlkioWeightDevice: weightDevices, + BlkioThrottleReadBpsDevice: readBpsDevice, + BlkioThrottleWriteBpsDevice: writeBpsDevice, + BlkioThrottleReadIOpsDevice: readIOpsDevice, + BlkioThrottleWriteIOpsDevice: writeIOpsDevice, + OomKillDisable: c.HostConfig.OomKillDisable, + MemorySwappiness: -1, } if c.HostConfig.MemorySwappiness != nil { diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index e606dd752e..a09076a4a4 100755 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -85,6 +85,36 @@ func parseSecurityOpt(container *container.Container, config *runconfig.HostConf return err } +func getBlkioReadIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { + var blkioReadIOpsDevice []*blkiodev.ThrottleDevice + var stat syscall.Stat_t + + for _, iopsDevice := range config.BlkioDeviceReadIOps { + if err := syscall.Stat(iopsDevice.Path, &stat); err != nil { + return nil, err + } + readIOpsDevice := blkiodev.NewThrottleDevice(int64(stat.Rdev/256), int64(stat.Rdev%256), iopsDevice.Rate) + blkioReadIOpsDevice = append(blkioReadIOpsDevice, readIOpsDevice) + } + + return blkioReadIOpsDevice, nil +} + +func getBlkioWriteIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { + var blkioWriteIOpsDevice []*blkiodev.ThrottleDevice + var stat syscall.Stat_t + + for _, iopsDevice := range config.BlkioDeviceWriteIOps { + if err := syscall.Stat(iopsDevice.Path, &stat); err != nil { + return nil, err + } + writeIOpsDevice := blkiodev.NewThrottleDevice(int64(stat.Rdev/256), int64(stat.Rdev%256), iopsDevice.Rate) + blkioWriteIOpsDevice = append(blkioWriteIOpsDevice, writeIOpsDevice) + } + + return blkioWriteIOpsDevice, nil +} + func getBlkioReadBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { var blkioReadBpsDevice []*blkiodev.ThrottleDevice var stat syscall.Stat_t @@ -299,6 +329,16 @@ func verifyContainerResources(resources *runconfig.Resources) ([]string, error) logrus.Warnf("Your kernel does not support Block I/O write limit in bytes per second. --device-write-bps discarded.") resources.BlkioDeviceWriteBps = []*pblkiodev.ThrottleDevice{} } + if len(resources.BlkioDeviceReadIOps) > 0 && !sysInfo.BlkioReadIOpsDevice { + warnings = append(warnings, "Your kernel does not support Block read limit in IO per second.") + logrus.Warnf("Your kernel does not support Block I/O read limit in IO per second. -device-read-iops discarded.") + resources.BlkioDeviceReadIOps = []*pblkiodev.ThrottleDevice{} + } + if len(resources.BlkioDeviceWriteIOps) > 0 && !sysInfo.BlkioWriteIOpsDevice { + warnings = append(warnings, "Your kernel does not support Block write limit in IO per second.") + logrus.Warnf("Your kernel does not support Block I/O write limit in IO per second. --device-write-iops discarded.") + resources.BlkioDeviceWriteIOps = []*pblkiodev.ThrottleDevice{} + } return warnings, nil } @@ -328,7 +368,6 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC hostConfig.OomKillDisable = false return warnings, fmt.Errorf("Your kernel does not support oom kill disable.") } - if hostConfig.OomScoreAdj < -1000 || hostConfig.OomScoreAdj > 1000 { return warnings, fmt.Errorf("Invalid value %d, range for oom score adj is [-1000, 1000].", hostConfig.OomScoreAdj) } diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index 4ef30eb927..2735702f7e 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -38,6 +38,14 @@ func parseSecurityOpt(container *container.Container, config *runconfig.HostConf return nil } +func getBlkioReadIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { + return nil, nil +} + +func getBlkioWriteIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { + return nil, nil +} + func getBlkioReadBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { return nil, nil } diff --git a/daemon/execdriver/driver_unix.go b/daemon/execdriver/driver_unix.go index 1a72fd178c..dae5d916c1 100644 --- a/daemon/execdriver/driver_unix.go +++ b/daemon/execdriver/driver_unix.go @@ -37,18 +37,20 @@ type Resources struct { // Fields below here are platform specific - BlkioWeightDevice []*blkiodev.WeightDevice `json:"blkio_weight_device"` - BlkioThrottleReadBpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_read_bps_device"` - BlkioThrottleWriteBpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_write_bps_device"` - MemorySwap int64 `json:"memory_swap"` - KernelMemory int64 `json:"kernel_memory"` - CPUQuota int64 `json:"cpu_quota"` - CpusetCpus string `json:"cpuset_cpus"` - CpusetMems string `json:"cpuset_mems"` - CPUPeriod int64 `json:"cpu_period"` - Rlimits []*ulimit.Rlimit `json:"rlimits"` - OomKillDisable bool `json:"oom_kill_disable"` - MemorySwappiness int64 `json:"memory_swappiness"` + BlkioWeightDevice []*blkiodev.WeightDevice `json:"blkio_weight_device"` + BlkioThrottleReadBpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_read_bps_device"` + BlkioThrottleWriteBpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_write_bps_device"` + BlkioThrottleReadIOpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_read_iops_device"` + BlkioThrottleWriteIOpsDevice []*blkiodev.ThrottleDevice `json:"blkio_throttle_write_iops_device"` + MemorySwap int64 `json:"memory_swap"` + KernelMemory int64 `json:"kernel_memory"` + CPUQuota int64 `json:"cpu_quota"` + CpusetCpus string `json:"cpuset_cpus"` + CpusetMems string `json:"cpuset_mems"` + CPUPeriod int64 `json:"cpu_period"` + Rlimits []*ulimit.Rlimit `json:"rlimits"` + OomKillDisable bool `json:"oom_kill_disable"` + MemorySwappiness int64 `json:"memory_swappiness"` } // ProcessConfig is the platform specific structure that describes a process @@ -181,6 +183,8 @@ func SetupCgroups(container *configs.Config, c *Command) error { container.Cgroups.BlkioWeightDevice = c.Resources.BlkioWeightDevice container.Cgroups.BlkioThrottleReadBpsDevice = c.Resources.BlkioThrottleReadBpsDevice container.Cgroups.BlkioThrottleWriteBpsDevice = c.Resources.BlkioThrottleWriteBpsDevice + container.Cgroups.BlkioThrottleReadIOPSDevice = c.Resources.BlkioThrottleReadIOpsDevice + container.Cgroups.BlkioThrottleWriteIOPSDevice = c.Resources.BlkioThrottleWriteIOpsDevice container.Cgroups.OomKillDisable = c.Resources.OomKillDisable container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness } diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index b90a5a4335..a458cd5efe 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -107,6 +107,8 @@ This section lists each version from latest to oldest. Each listing includes a * Pushes initiated with `POST /images/(name)/push` and pulls initiated with `POST /images/create` will be cancelled if the HTTP connection making the API request is closed before the push or pull completes. +* `POST /containers/create` now allows you to set a read/write rate limit for a + device (in bytes per second or IO per second). ### v1.21 API changes diff --git a/docs/reference/api/docker_remote_api_v1.22.md b/docs/reference/api/docker_remote_api_v1.22.md index 4fef79dd72..c792ccecf9 100644 --- a/docs/reference/api/docker_remote_api_v1.22.md +++ b/docs/reference/api/docker_remote_api_v1.22.md @@ -248,7 +248,9 @@ Create a container "BlkioWeight": 300, "BlkioWeightDevice": [{}], "BlkioDeviceReadBps": [{}], + "BlkioDeviceReadIOps": [{}], "BlkioDeviceWriteBps": [{}], + "BlkioDeviceWriteIOps": [{}], "MemorySwappiness": 60, "OomKillDisable": false, "OomScoreAdj": 500, @@ -306,10 +308,14 @@ Json Parameters: - **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. - **BlkioWeightDevice** - Block IO weight (relative device weight) in the form of: `"BlkioWeightDevice": [{"Path": "device_path", "Weight": weight}]` -- **BlkioDeviceReadBps** - Limit read rate from a device in form of: `"BlkioDeviceReadBps": [{"Path": "device_path", "Rate": rate}]`, for example: +- **BlkioDeviceReadBps** - Limit read rate (bytes per second) from a device in the form of: `"BlkioDeviceReadBps": [{"Path": "device_path", "Rate": rate}]`, for example: `"BlkioDeviceReadBps": [{"Path": "/dev/sda", "Rate": "1024"}]"` -- **BlkioDeviceWriteBps** - Limit write rate to a device in the form of: `"BlkioDeviceWriteBps": [{"Path": "device_path", "Rate": rate}]`, for example: +- **BlkioDeviceWriteBps** - Limit write rate (bytes per second) to a device in the form of: `"BlkioDeviceWriteBps": [{"Path": "device_path", "Rate": rate}]`, for example: `"BlkioDeviceWriteBps": [{"Path": "/dev/sda", "Rate": "1024"}]"` +- **BlkioDeviceReadIOps** - Limit read rate (IO per second) from a device in the form of: `"BlkioDeviceReadIOps": [{"Path": "device_path", "Rate": rate}]`, for example: + `"BlkioDeviceReadIOps": [{"Path": "/dev/sda", "Rate": "1000"}]` +- **BlkioDeviceWiiteIOps** - Limit write rate (IO per second) to a device in the form of: `"BlkioDeviceWriteIOps": [{"Path": "device_path", "Rate": rate}]`, for example: + `"BlkioDeviceWriteIOps": [{"Path": "/dev/sda", "Rate": "1000"}]` - **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. - **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not. - **OomScoreAdj** - An integer value containing the score given to the container in order to tune OOM killer preferences. @@ -465,6 +471,8 @@ Return low-level information on the container `id` "BlkioWeightDevice": [{}], "BlkioDeviceReadBps": [{}], "BlkioDeviceWriteBps": [{}], + "BlkioDeviceReadIOps": [{}], + "BlkioDeviceWriteIOps": [{}], "CapAdd": null, "CapDrop": null, "ContainerIDFile": "", diff --git a/docs/reference/commandline/create.md b/docs/reference/commandline/create.md index fae59a59cf..9f7752fb88 100644 --- a/docs/reference/commandline/create.md +++ b/docs/reference/commandline/create.md @@ -31,7 +31,9 @@ Creates a new container. --cpuset-mems="" Memory nodes (MEMs) in which to allow execution (0-3, 0,1) --device=[] Add a host device to the container --device-read-bps=[] Limit read rate (bytes per second) from a device (e.g., --device-read-bps=/dev/sda:1mb) + --device-read-iops=[] Limit read rate (IO per second) from a device (e.g., --device-read-iops=/dev/sda:1000) --device-write-bps=[] Limit write rate (bytes per second) to a device (e.g., --device-write-bps=/dev/sda:1mb) + --device-write-iops=[] Limit write rate (IO per second) to a device (e.g., --device-write-iops=/dev/sda:1000) --disable-content-trust=true Skip image verification --dns=[] Set custom DNS servers --dns-opt=[] Set custom DNS options diff --git a/docs/reference/commandline/run.md b/docs/reference/commandline/run.md index 57822fbfe6..0aacf894dd 100644 --- a/docs/reference/commandline/run.md +++ b/docs/reference/commandline/run.md @@ -30,7 +30,9 @@ parent = "smn_cli" -d, --detach=false Run container in background and print container ID --device=[] Add a host device to the container --device-read-bps=[] Limit read rate (bytes per second) from a device (e.g., --device-read-bps=/dev/sda:1mb) + --device-read-iops=[] Limit read rate (IO per second) from a device (e.g., --device-read-iops=/dev/sda:1000) --device-write-bps=[] Limit write rate (bytes per second) to a device (e.g., --device-write-bps=/dev/sda:1mb) + --device-write-iops=[] Limit write rate (IO per second) to a device (e.g., --device-write-bps=/dev/sda:1000) --disable-content-trust=true Skip image verification --dns=[] Set custom DNS servers --dns-opt=[] Set custom DNS options diff --git a/docs/reference/run.md b/docs/reference/run.md index 8e83d2b328..41480933c4 100644 --- a/docs/reference/run.md +++ b/docs/reference/run.md @@ -632,6 +632,8 @@ container: | `--blkio-weight-device=""` | Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`) | | `--device-read-bps=""` | Limit read rate from a device (format: `:[]`). Number is a positive integer. Unit can be one of `kb`, `mb`, or `gb`. | | `--device-write-bps=""` | Limit write rate to a device (format: `:[]`). Number is a positive integer. Unit can be one of `kb`, `mb`, or `gb`. | +| `--device-read-iops="" ` | Limit read rate (IO per second) from a device (format: `:`). Number is a positive integer. | +| `--device-write-iops="" ` | Limit write rate (IO per second) to a device (format: `:`). Number is a positive integer. | | `--oom-kill-disable=false` | Whether to disable OOM Killer for the container or not. | | `--memory-swappiness=""` | Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. | | `--shm-size=""` | Size of `/dev/shm`. The format is ``. `number` must be greater than `0`. Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`. | @@ -983,15 +985,15 @@ on `/dev/sda` setting that weight to `200`: --blkio-weight-device "/dev/sda:200" \ ubuntu -The `--device-read-bps` flag limits the read rate from a device. For example, -this command creates a container and limits the read rate to `1mb` per second -from `/dev/sda`: +The `--device-read-bps` flag limits the read rate (bytes per second) from a device. +For example, this command creates a container and limits the read rate to `1mb` +per second from `/dev/sda`: $ docker run -it --device-read-bps /dev/sda:1mb ubuntu -The `--device-write-bps` flag limits the write rate to a device. For example, -this command creates a container and limits the write rate to `1mb` per second -for `/dev/sda`: +The `--device-write-bps` flag limits the write rate (bytes per second)to a device. +For example, this command creates a container and limits the write rate to `1mb` +per second for `/dev/sda`: $ docker run -it --device-write-bps /dev/sda:1mb ubuntu @@ -999,6 +1001,21 @@ Both flags take limits in the `:[unit]` format. Both read and write rates must be a positive integer. You can specify the rate in `kb` (kilobytes), `mb` (megabytes), or `gb` (gigabytes). +The `--device-read-iops` flag limits read rate (IO per second) from a device. +For example, this command creates a container and limits the read rate to +`1000` IO per second from `/dev/sda`: + + $ docker run -ti --device-read-iops /dev/sda:1000 ubuntu + +The `--device-write-iops` flag limits write rate (IO per second) to a device. +For example, this command creates a container and limits the write rate to +`1000` IO per second to `/dev/sda`: + + $ docker run -ti --device-write-iops /dev/sda:1000 ubuntu + +Both flags take limits in the `:` format. Both read and +write rates must be a positive integer. + ## Additional groups --group-add: Add Linux capabilities diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 043810a8f8..f3731553ce 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -267,6 +267,18 @@ func (s *DockerSuite) TestRunWithBlkioInvalidDeviceWriteBps(c *check.C) { c.Assert(err, check.NotNil, check.Commentf(out)) } +func (s *DockerSuite) TestRunWithBlkioInvalidReadiopsDevice(c *check.C) { + testRequires(c, blkioWeight) + out, _, err := dockerCmdWithError("run", "--device-read-iops", "/dev/sdX:500", "busybox", "true") + c.Assert(err, check.NotNil, check.Commentf(out)) +} + +func (s *DockerSuite) TestRunWithBlkioInvalidWriteiopsDevice(c *check.C) { + testRequires(c, blkioWeight) + out, _, err := dockerCmdWithError("run", "--device-write-iops", "/dev/sdX:500", "busybox", "true") + c.Assert(err, check.NotNil, check.Commentf(out)) +} + func (s *DockerSuite) TestRunOOMExitCode(c *check.C) { testRequires(c, oomControl) errChan := make(chan error) diff --git a/man/docker-create.1.md b/man/docker-create.1.md index bca40cbacc..d473a624e9 100644 --- a/man/docker-create.1.md +++ b/man/docker-create.1.md @@ -21,7 +21,9 @@ docker-create - Create a new container [**--cpuset-mems**[=*CPUSET-MEMS*]] [**--device**[=*[]*]] [**--device-read-bps**[=*[]*]] +[**--device-read-iops**[=*[]*]] [**--device-write-bps**[=*[]*]] +[**--device-write-iops**[=*[]*]] [**--dns**[=*[]*]] [**--dns-search**[=*[]*]] [**--dns-opt**[=*[]*]] @@ -130,9 +132,15 @@ two memory nodes. **--device-read-bps**=[] Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb) +**--device-read-iops**=[] + Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000) + **--device-write-bps**=[] Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb) +**--device-write-iops**=[] + Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000) + **--dns**=[] Set custom DNS servers diff --git a/man/docker-run.1.md b/man/docker-run.1.md index 603db39b7f..17c6e3268b 100644 --- a/man/docker-run.1.md +++ b/man/docker-run.1.md @@ -22,7 +22,9 @@ docker-run - Run a command in a new container [**-d**|**--detach**[=*false*]] [**--device**[=*[]*]] [**--device-read-bps**[=*[]*]] +[**--device-read-iops**[=*[]*]] [**--device-write-bps**[=*[]*]] +[**--device-write-iops**[=*[]*]] [**--dns**[=*[]*]] [**--dns-opt**[=*[]*]] [**--dns-search**[=*[]*]] @@ -197,9 +199,15 @@ stopping the process by pressing the keys CTRL-P CTRL-Q. **--device-read-bps**=[] Limit read rate from a device (e.g. --device-read-bps=/dev/sda:1mb) +**--device-read-iops**=[] + Limit read rate from a device (e.g. --device-read-iops=/dev/sda:1000) + **--device-write-bps**=[] Limit write rate to a device (e.g. --device-write-bps=/dev/sda:1mb) +**--device-write-iops**=[] + Limit write rate a a device (e.g. --device-write-iops=/dev/sda:1000) + **--dns-search**=[] Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain) diff --git a/opts/opts.go b/opts/opts.go index 0dd42a6ce0..1a77e20c7a 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -219,6 +219,29 @@ func ValidateThrottleBpsDevice(val string) (*blkiodev.ThrottleDevice, error) { }, nil } +// ValidateThrottleIOpsDevice validates that the specified string has a valid device-rate format. +func ValidateThrottleIOpsDevice(val string) (*blkiodev.ThrottleDevice, error) { + split := strings.SplitN(val, ":", 2) + if len(split) != 2 { + return nil, fmt.Errorf("bad format: %s", val) + } + if !strings.HasPrefix(split[0], "/dev/") { + return nil, fmt.Errorf("bad format for device path: %s", val) + } + rate, err := strconv.ParseUint(split[1], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :. Number must be a positive integer", val) + } + if rate < 0 { + return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :. Number must be a positive integer", val) + } + + return &blkiodev.ThrottleDevice{ + Path: split[0], + Rate: uint64(rate), + }, nil +} + // ValidateEnv validates an environment variable and returns it. // If no value is specified, it returns the current value using os.Getenv. // diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go index 3c7e9edb73..8ec1ceb726 100644 --- a/pkg/sysinfo/sysinfo.go +++ b/pkg/sysinfo/sysinfo.go @@ -69,6 +69,12 @@ type cgroupBlkioInfo struct { // Whether Block IO write limit in bytes per second is supported or not BlkioWriteBpsDevice bool + + // Whether Block IO read limit in IO per second is supported or not + BlkioReadIOpsDevice bool + + // Whether Block IO write limit in IO per second is supported or not + BlkioWriteIOpsDevice bool } type cgroupCpusetInfo struct { diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go index e30e79aed2..ef3410cfae 100644 --- a/pkg/sysinfo/sysinfo_linux.go +++ b/pkg/sysinfo/sysinfo_linux.go @@ -136,11 +136,22 @@ func checkCgroupBlkioInfo(quiet bool) cgroupBlkioInfo { if !quiet && !writeBpsDevice { logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device") } + readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device") + if !quiet && !readIOpsDevice { + logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device") + } + + writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device") + if !quiet && !writeIOpsDevice { + logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device") + } return cgroupBlkioInfo{ - BlkioWeight: weight, - BlkioWeightDevice: weightDevice, - BlkioReadBpsDevice: readBpsDevice, - BlkioWriteBpsDevice: writeBpsDevice, + BlkioWeight: weight, + BlkioWeightDevice: weightDevice, + BlkioReadBpsDevice: readBpsDevice, + BlkioWriteBpsDevice: writeBpsDevice, + BlkioReadIOpsDevice: readIOpsDevice, + BlkioWriteIOpsDevice: writeIOpsDevice, } } diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index 25b3d779a5..20088c0bf1 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -171,22 +171,24 @@ type Resources struct { CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers) // Applicable to UNIX platforms - CgroupParent string // Parent cgroup. - BlkioWeight uint16 // Block IO weight (relative weight vs. other containers) - BlkioWeightDevice []*blkiodev.WeightDevice - BlkioDeviceReadBps []*blkiodev.ThrottleDevice - BlkioDeviceWriteBps []*blkiodev.ThrottleDevice - CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period - CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota - CpusetCpus string // CpusetCpus 0-2, 0,1 - CpusetMems string // CpusetMems 0-2, 0,1 - Devices []DeviceMapping // List of devices to map inside the container - KernelMemory int64 // Kernel memory limit (in bytes) - Memory int64 // Memory limit (in bytes) - MemoryReservation int64 // Memory soft limit (in bytes) - MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap - MemorySwappiness *int64 // Tuning container memory swappiness behaviour - Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container + CgroupParent string // Parent cgroup. + BlkioWeight uint16 // Block IO weight (relative weight vs. other containers) + BlkioWeightDevice []*blkiodev.WeightDevice + BlkioDeviceReadBps []*blkiodev.ThrottleDevice + BlkioDeviceWriteBps []*blkiodev.ThrottleDevice + BlkioDeviceReadIOps []*blkiodev.ThrottleDevice + BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice + CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period + CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota + CpusetCpus string // CpusetCpus 0-2, 0,1 + CpusetMems string // CpusetMems 0-2, 0,1 + Devices []DeviceMapping // List of devices to map inside the container + KernelMemory int64 // Kernel memory limit (in bytes) + Memory int64 // Memory limit (in bytes) + MemoryReservation int64 // Memory soft limit (in bytes) + MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap + MemorySwappiness *int64 // Tuning container memory swappiness behaviour + Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container } // HostConfig the non-portable Config structure of a container. diff --git a/runconfig/parse.go b/runconfig/parse.go index 860af01a4e..e834112c57 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -57,6 +57,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flDeviceReadBps = opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice) flDeviceWriteBps = opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice) flLinks = opts.NewListOpts(ValidateLink) + flDeviceReadIOps = opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice) + flDeviceWriteIOps = opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice) flEnv = opts.NewListOpts(opts.ValidateEnv) flLabels = opts.NewListOpts(opts.ValidateEnv) flDevices = opts.NewListOpts(ValidateDevice) @@ -118,6 +120,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe cmd.Var(&flBlkioWeightDevice, []string{"-blkio-weight-device"}, "Block IO weight (relative device weight)") cmd.Var(&flDeviceReadBps, []string{"-device-read-bps"}, "Limit read rate (bytes per second) from a device") cmd.Var(&flDeviceWriteBps, []string{"-device-write-bps"}, "Limit write rate (bytes per second) to a device") + cmd.Var(&flDeviceReadIOps, []string{"-device-read-iops"}, "Limit read rate (IO per second) from a device") + cmd.Var(&flDeviceWriteIOps, []string{"-device-write-iops"}, "Limit write rate (IO per second) to a device") cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume") cmd.Var(&flTmpfs, []string{"-tmpfs"}, "Mount a tmpfs directory") cmd.Var(&flLinks, []string{"-link"}, "Add link to another container") @@ -343,23 +347,25 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe } resources := Resources{ - CgroupParent: *flCgroupParent, - Memory: flMemory, - MemoryReservation: MemoryReservation, - MemorySwap: memorySwap, - MemorySwappiness: flSwappiness, - KernelMemory: KernelMemory, - CPUShares: *flCPUShares, - CPUPeriod: *flCPUPeriod, - CpusetCpus: *flCpusetCpus, - CpusetMems: *flCpusetMems, - CPUQuota: *flCPUQuota, - BlkioWeight: *flBlkioWeight, - BlkioWeightDevice: flBlkioWeightDevice.GetList(), - BlkioDeviceReadBps: flDeviceReadBps.GetList(), - BlkioDeviceWriteBps: flDeviceWriteBps.GetList(), - Ulimits: flUlimits.GetList(), - Devices: deviceMappings, + CgroupParent: *flCgroupParent, + Memory: flMemory, + MemoryReservation: MemoryReservation, + MemorySwap: memorySwap, + MemorySwappiness: flSwappiness, + KernelMemory: KernelMemory, + CPUShares: *flCPUShares, + CPUPeriod: *flCPUPeriod, + CpusetCpus: *flCpusetCpus, + CpusetMems: *flCpusetMems, + CPUQuota: *flCPUQuota, + BlkioWeight: *flBlkioWeight, + BlkioWeightDevice: flBlkioWeightDevice.GetList(), + BlkioDeviceReadBps: flDeviceReadBps.GetList(), + BlkioDeviceWriteBps: flDeviceWriteBps.GetList(), + BlkioDeviceReadIOps: flDeviceReadIOps.GetList(), + BlkioDeviceWriteIOps: flDeviceWriteIOps.GetList(), + Ulimits: flUlimits.GetList(), + Devices: deviceMappings, } config := &Config{