From 096436cf23035655d5809a1423cd87b2f10ae6a3 Mon Sep 17 00:00:00 2001 From: Leno Hou Date: Fri, 14 Dec 2018 10:09:59 +0000 Subject: [PATCH] feature: limit blkio device's read/write Bps/IOps fixes #2509 Signed-off-by: Leno Hou --- apis/types/resources.go | 2 +- cli/update.go | 24 ++++++--- test/cli_run_blkio_test.go | 100 +++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 9 deletions(-) diff --git a/apis/types/resources.go b/apis/types/resources.go index 0397dc291a..261d9a5ab7 100644 --- a/apis/types/resources.go +++ b/apis/types/resources.go @@ -122,7 +122,7 @@ type Resources struct { // Total memory limit (memory + swap). Set as `-1` to enable unlimited swap. MemorySwap int64 `json:"MemorySwap"` - // Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. + // Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100. -1 is also accepted, as a legacy alias of 0. // Maximum: 100 // Minimum: -1 MemorySwappiness *int64 `json:"MemorySwappiness"` diff --git a/cli/update.go b/cli/update.go index 6799a86d69..c93c22705f 100644 --- a/cli/update.go +++ b/cli/update.go @@ -51,6 +51,10 @@ func (uc *UpdateCommand) addFlags() { flagSet.StringSliceVarP(&uc.labels, "label", "l", nil, "Set label for container") flagSet.StringVar(&uc.restartPolicy, "restart", "", "Restart policy to apply when container exits") flagSet.StringSliceVar(&uc.diskQuota, "disk-quota", nil, "Update disk quota for container(/=10g)") + flagSet.Var(&uc.blkioDeviceReadBps, "device-read-bps", "Update read rate (bytes per second) from a device") + flagSet.Var(&uc.blkioDeviceWriteBps, "device-write-bps", "Update write rate (bytes per second) from a device") + flagSet.Var(&uc.blkioDeviceReadIOps, "device-read-iops", "Update read rate (io per second) from a device") + flagSet.Var(&uc.blkioDeviceWriteIOps, "device-write-iops", "Update write rate (io per second) from a device") } // updateRun is the entry of update command. @@ -69,14 +73,18 @@ func (uc *UpdateCommand) updateRun(args []string) error { } resource := types.Resources{ - CPUPeriod: uc.cpuperiod, - CPUShares: uc.cpushare, - CPUQuota: uc.cpuquota, - CpusetCpus: uc.cpusetcpus, - CpusetMems: uc.cpusetmems, - Memory: memory, - MemorySwap: memorySwap, - BlkioWeight: uc.blkioWeight, + CPUPeriod: uc.cpuperiod, + CPUShares: uc.cpushare, + CPUQuota: uc.cpuquota, + CpusetCpus: uc.cpusetcpus, + CpusetMems: uc.cpusetmems, + Memory: memory, + MemorySwap: memorySwap, + BlkioWeight: uc.blkioWeight, + BlkioDeviceReadBps: uc.blkioDeviceReadBps.Value(), + BlkioDeviceWriteBps: uc.blkioDeviceWriteBps.Value(), + BlkioDeviceReadIOps: uc.blkioDeviceReadIOps.Value(), + BlkioDeviceWriteIOps: uc.blkioDeviceWriteIOps.Value(), } restartPolicy, err := opts.ParseRestartPolicy(uc.restartPolicy) diff --git a/test/cli_run_blkio_test.go b/test/cli_run_blkio_test.go index add9fc8275..bdfe7a4b4c 100644 --- a/test/cli_run_blkio_test.go +++ b/test/cli_run_blkio_test.go @@ -139,3 +139,103 @@ func (suite *PouchRunBlkioSuite) TestRunWithBlkioWeight(c *check.C) { defer DelContainerForceMultyTime(c, name) res.Assert(c, icmd.Success) } + +// TestRunWithBlkIODeviceWriteBps is to verify blkio write bps +func (suite *PouchRunBlkioSuite) TestRunBlockIODeviceWriteBps(c *check.C) { + cname := "TestRunBlockIODeviceWriteBps" + testDisk := "/dev/null" + + number, exist := util.GetMajMinNumOfDevice(testDisk) + if !exist { + c.Skip("fail to get major:minor device number") + } + + limitSpeed := "100" + expected := fmt.Sprintf("%s:%d %s\n", number, value, limitSpeed) + + blkioDeviceWriteBpsFile := "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device" + throttleDev := testDisk + ":" + limitSpeed + + res := command.PouchRun("run", "--name", cname, + "--device-write-bps ", throttleDev, busyboxImage, "cat", blkioDeviceWriteBpsFile) + defer DelContainerForceMultyTime(c, cname) + res.Assert(c, icmd.Success) + + out := res.Stdout() + c.Assert(out, check.Equals, expected) +} + +// TestRunWithBlkIODeviceReadBps is to verify blkio read bps +func (suite *PouchRunBlkioSuite) TestRunBlockIODeviceReadBps(c *check.C) { + cname := "TestRunBlockIODeviceReadBps" + testDisk := "/dev/null" + + number, exist := util.GetMajMinNumOfDevice(testDisk) + if !exist { + c.Skip("fail to get major:minor device number") + } + + limitSpeed := "100" + expected := fmt.Sprintf("%s:%d %s\n", number, value, limitSpeed) + + blkioDeviceReadBpsFile := "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device" + throttleDev := testDisk + ":" + limitSpeed + + res := command.PouchRun("run", "--name", cname, + "--device-read-bps ", throttleDev, busyboxImage, "cat", blkioDeviceReadBpsFile) + defer DelContainerForceMultyTime(c, cname) + res.Assert(c, icmd.Success) + + out := res.Stdout() + c.Assert(out, check.Equals, expected) +} + +// TestRunWithBlkIODeviceWriteIOps is to verify blkio write iops +func (suite *PouchRunBlkioSuite) TestRunBlockIODeviceWriteIOps(c *check.C) { + cname := "TestRunBlockIODeviceWriteIOps" + testDisk := "/dev/null" + + number, exist := util.GetMajMinNumOfDevice(testDisk) + if !exist { + c.Skip("fail to get major:minor device number") + } + + limitSpeed := "100" + expected := fmt.Sprintf("%s:%d %s\n", number, value, limitSpeed) + + blkioDeviceWriteIOpsFile := "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device" + throttleDev := testDisk + ":" + limitSpeed + + res := command.PouchRun("run", "--name", cname, + "--device-write-iops ", throttleDev, busyboxImage, "cat", blkioDeviceWriteIOpsFile) + defer DelContainerForceMultyTime(c, cname) + res.Assert(c, icmd.Success) + + out := res.Stdout() + c.Assert(out, check.Equals, expected) +} + +// TestRunWithBlkIODeviceWriteIOps is to verify blkio read iops +func (suite *PouchRunBlkioSuite) TestRunBlockIODeviceReadIOps(c *check.C) { + cname := "TestRunBlockIODeviceReadIOps" + testDisk := "/dev/null" + + number, exist := util.GetMajMinNumOfDevice(testDisk) + if !exist { + c.Skip("fail to get major:minor device number") + } + + limitSpeed := "100" + expected := fmt.Sprintf("%s:%d %s\n", number, value, limitSpeed) + + blkioDeviceReadIOpsFile := "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device" + throttleDev := testDisk + ":" + limitSpeed + + res := command.PouchRun("run", "--name", cname, + "--device-read-iops ", throttleDev, busyboxImage, "cat", blkioDeviceReadIOpsFile) + defer DelContainerForceMultyTime(c, cname) + res.Assert(c, icmd.Success) + + out := res.Stdout() + c.Assert(out, check.Equals, expected) +}