From 0aefdc6d342ce98cef991a8dbd68158f406f0266 Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Thu, 3 May 2018 09:30:18 +0200 Subject: [PATCH 1/6] feat(Container): block devices io limits --- Docker/Container.php | 13 +++++++++++++ Tests/Docker/ContainerTest.php | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Docker/Container.php b/Docker/Container.php index c6a8a77f..8886261c 100644 --- a/Docker/Container.php +++ b/Docker/Container.php @@ -384,6 +384,18 @@ public function getRunCommand($containerId) $labels .= ' --label ' . escapeshellarg($label); } + // block devices + $process = new \Symfony\Component\Process\Process("lsblk --nodeps --output NAME --noheadings 2>/dev/null"); + $process->mustRun(); + $devices = array_filter(explode("\n", $process->getOutput()), function($device) { + return !empty($device); + }); + $deviceLimits = ""; + foreach($devices as $device) { + $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; + $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; + } + $command .= " --volume " . escapeshellarg($this->dataDir . ":/data") . " --volume " . escapeshellarg($this->tmpDir . ":/tmp") . " --memory " . escapeshellarg($this->getImage()->getSourceComponent()->getMemory()) @@ -391,6 +403,7 @@ public function getRunCommand($containerId) . " --cpu-shares " . escapeshellarg($this->getImage()->getSourceComponent()->getCpuShares()) . " --net " . escapeshellarg($this->getImage()->getSourceComponent()->getNetworkType()) . " --cpus 2" + . $deviceLimits . $envs . $labels . " --name " . escapeshellarg($containerId) diff --git a/Tests/Docker/ContainerTest.php b/Tests/Docker/ContainerTest.php index 336664a9..0b38ed16 100644 --- a/Tests/Docker/ContainerTest.php +++ b/Tests/Docker/ContainerTest.php @@ -151,6 +151,19 @@ public function testRunCommand() ], $envs), new OutputFilter() ); + + // block devices + $process = new \Symfony\Component\Process\Process("lsblk --nodeps --output NAME --noheadings 2>/dev/null"); + $process->mustRun(); + $devices = array_filter(explode("\n", $process->getOutput()), function($device) { + return !empty($device); + }); + $deviceLimits = ""; + foreach($devices as $device) { + $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; + $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; + } + $expected = "sudo timeout --signal=SIGKILL 3600" . " docker run" . " --volume '/data:/data'" @@ -160,6 +173,7 @@ public function testRunCommand() . " --cpu-shares '1024'" . " --net 'bridge'" . " --cpus 2" + . $deviceLimits . " --env \"var=val\"" . " --env \"příliš=žluťoučký\"" . " --env \"var2=weird = '\\\"value\"" From 8582b78b6736fdeabbabaf28666cf0010324274e Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Thu, 3 May 2018 09:34:53 +0200 Subject: [PATCH 2/6] fix: coding style --- Docker/Container.php | 4 ++-- Tests/Docker/ContainerTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Docker/Container.php b/Docker/Container.php index 8886261c..925e29b1 100644 --- a/Docker/Container.php +++ b/Docker/Container.php @@ -387,11 +387,11 @@ public function getRunCommand($containerId) // block devices $process = new \Symfony\Component\Process\Process("lsblk --nodeps --output NAME --noheadings 2>/dev/null"); $process->mustRun(); - $devices = array_filter(explode("\n", $process->getOutput()), function($device) { + $devices = array_filter(explode("\n", $process->getOutput()), function ($device) { return !empty($device); }); $deviceLimits = ""; - foreach($devices as $device) { + foreach ($devices as $device) { $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; } diff --git a/Tests/Docker/ContainerTest.php b/Tests/Docker/ContainerTest.php index 0b38ed16..5cdbb0de 100644 --- a/Tests/Docker/ContainerTest.php +++ b/Tests/Docker/ContainerTest.php @@ -155,11 +155,11 @@ public function testRunCommand() // block devices $process = new \Symfony\Component\Process\Process("lsblk --nodeps --output NAME --noheadings 2>/dev/null"); $process->mustRun(); - $devices = array_filter(explode("\n", $process->getOutput()), function($device) { + $devices = array_filter(explode("\n", $process->getOutput()), function ($device) { return !empty($device); }); $deviceLimits = ""; - foreach($devices as $device) { + foreach ($devices as $device) { $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; } From 4db95068404fbafe2c9a6ef15d3036ebc556a717 Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Wed, 9 May 2018 12:51:13 +0200 Subject: [PATCH 3/6] feat(LimitsTest): getImageMock method --- Tests/Runner/LimitsTest.php | 71 ++++++++----------------------------- 1 file changed, 14 insertions(+), 57 deletions(-) diff --git a/Tests/Runner/LimitsTest.php b/Tests/Runner/LimitsTest.php index 018060a7..768ee8fa 100644 --- a/Tests/Runner/LimitsTest.php +++ b/Tests/Runner/LimitsTest.php @@ -24,19 +24,9 @@ public function testInstanceLimitsInvalid() [], [] ); - $componentMock = self::getMockBuilder(Component::class) - ->disableOriginalConstructor() - ->getMock(); - $image = self::getMockBuilder(AWSElasticContainerRegistry::class) - ->disableOriginalConstructor() - ->setMethods(['getSourceComponent']) - ->getMock(); - $image->method('getSourceComponent') - ->will(self::returnValue($componentMock)); - /** @var Image $image */ self::expectException(ApplicationException::class); self::expectExceptionMessage('cpu_count is set incorrectly in parameters.yml: This value should be a valid number.'); - $limits->getCpuLimit($image); + $limits->getCpuLimit($this->getImageMock()); } public function testProjectLimitsInvalid() @@ -50,19 +40,9 @@ public function testProjectLimitsInvalid() [], [] ); - $componentMock = self::getMockBuilder(Component::class) - ->disableOriginalConstructor() - ->getMock(); - $image = self::getMockBuilder(AWSElasticContainerRegistry::class) - ->disableOriginalConstructor() - ->setMethods(['getSourceComponent']) - ->getMock(); - $image->method('getSourceComponent') - ->will(self::returnValue($componentMock)); - /** @var Image $image */ self::expectException(ApplicationException::class); self::expectExceptionMessage('runner.cpuParallelism limit is set incorrectly: This value should be 96 or less.'); - $limits->getCpuLimit($image); + $limits->getCpuLimit($this->getImageMock()); } public function testLimitsInstance() @@ -76,17 +56,7 @@ public function testLimitsInstance() ['foo', 'bar'], ['bar', 'kochba'] ); - $componentMock = self::getMockBuilder(Component::class) - ->disableOriginalConstructor() - ->getMock(); - $image = self::getMockBuilder(AWSElasticContainerRegistry::class) - ->disableOriginalConstructor() - ->setMethods(['getSourceComponent']) - ->getMock(); - $image->method('getSourceComponent') - ->will(self::returnValue($componentMock)); - /** @var Image $image */ - self::assertEquals(1, $limits->getCpuLimit($image)); + self::assertEquals(1, $limits->getCpuLimit($this->getImageMock())); self::assertContains('CPU limits - instance: 1 project: 2', $handler->getRecords()[0]['message']); } @@ -99,17 +69,7 @@ public function testLimitsDefault() [], [] ); - $componentMock = self::getMockBuilder(Component::class) - ->disableOriginalConstructor() - ->getMock(); - $image = self::getMockBuilder(AWSElasticContainerRegistry::class) - ->disableOriginalConstructor() - ->setMethods(['getSourceComponent']) - ->getMock(); - $image->method('getSourceComponent') - ->will(self::returnValue($componentMock)); - /** @var Image $image */ - self::assertEquals(2, $limits->getCpuLimit($image)); + self::assertEquals(2, $limits->getCpuLimit($this->getImageMock())); } public function testLimitsProject() @@ -121,17 +81,7 @@ public function testLimitsProject() [], [] ); - $componentMock = self::getMockBuilder(Component::class) - ->disableOriginalConstructor() - ->getMock(); - $image = self::getMockBuilder(AWSElasticContainerRegistry::class) - ->disableOriginalConstructor() - ->setMethods(['getSourceComponent']) - ->getMock(); - $image->method('getSourceComponent') - ->will(self::returnValue($componentMock)); - /** @var Image $image */ - self::assertEquals(10, $limits->getCpuLimit($image)); + self::assertEquals(10, $limits->getCpuLimit($this->getImageMock())); } public function testLimitsProjectInstance() @@ -143,6 +93,14 @@ public function testLimitsProjectInstance() [], [] ); + self::assertEquals(2, $limits->getCpuLimit($this->getImageMock())); + } + + /** + * @return Image + */ + private function getImageMock() + { $componentMock = self::getMockBuilder(Component::class) ->disableOriginalConstructor() ->getMock(); @@ -152,7 +110,6 @@ public function testLimitsProjectInstance() ->getMock(); $image->method('getSourceComponent') ->will(self::returnValue($componentMock)); - /** @var Image $image */ - self::assertEquals(2, $limits->getCpuLimit($image)); + return $image; } } From 69931dc2158f4d925bf6fbaf8a1c93766af07f8e Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Wed, 9 May 2018 12:54:26 +0200 Subject: [PATCH 4/6] feat(Limits): device IO limits --- Docker/Runner/Limits.php | 4 ++++ Tests/Runner/LimitsTest.php | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/Docker/Runner/Limits.php b/Docker/Runner/Limits.php index 5ec9b23b..ffe88a3c 100644 --- a/Docker/Runner/Limits.php +++ b/Docker/Runner/Limits.php @@ -96,6 +96,10 @@ public function getCpuLimit(Image $image) return min($instance, $project); } + public function getDeviceIOLimits(Image $image) { + return '50m'; + } + /** * @return Range[] */ diff --git a/Tests/Runner/LimitsTest.php b/Tests/Runner/LimitsTest.php index 768ee8fa..73d54a01 100644 --- a/Tests/Runner/LimitsTest.php +++ b/Tests/Runner/LimitsTest.php @@ -96,6 +96,18 @@ public function testLimitsProjectInstance() self::assertEquals(2, $limits->getCpuLimit($this->getImageMock())); } + public function testDeviceIOLimits() + { + $limits = new Limits( + new NullLogger(), + [], + [], + [], + [] + ); + self::assertEquals("50m", $limits->getDeviceIOLimits($this->getImageMock())); + } + /** * @return Image */ From f6615c847f2064d9aed834209d45ce16c7a42458 Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Wed, 9 May 2018 12:57:09 +0200 Subject: [PATCH 5/6] feat(Container): device IO limits --- Docker/Container.php | 5 ++--- Tests/Docker/ContainerTest.php | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Docker/Container.php b/Docker/Container.php index 28be8c18..9af2ebf2 100644 --- a/Docker/Container.php +++ b/Docker/Container.php @@ -393,7 +393,6 @@ public function getRunCommand($containerId) $labels .= ' --label ' . escapeshellarg($label); } - // block devices $process = new \Symfony\Component\Process\Process("lsblk --nodeps --output NAME --noheadings 2>/dev/null"); $process->mustRun(); $devices = array_filter(explode("\n", $process->getOutput()), function ($device) { @@ -401,8 +400,8 @@ public function getRunCommand($containerId) }); $deviceLimits = ""; foreach ($devices as $device) { - $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; - $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; + $deviceLimits .= " --device-write-bps /dev/{$device}:{$this->limits->getDeviceIOLimits($this->getImage())}"; + $deviceLimits .= " --device-read-bps /dev/{$device}:{$this->limits->getDeviceIOLimits($this->getImage())}"; } $command .= " --volume " . escapeshellarg($this->dataDir . ":/data") diff --git a/Tests/Docker/ContainerTest.php b/Tests/Docker/ContainerTest.php index db43da4a..dbf3a0c3 100644 --- a/Tests/Docker/ContainerTest.php +++ b/Tests/Docker/ContainerTest.php @@ -163,8 +163,8 @@ public function testRunCommand() }); $deviceLimits = ""; foreach ($devices as $device) { - $deviceLimits .= " --device-write-bps /dev/{$device}:100m"; - $deviceLimits .= " --device-read-bps /dev/{$device}:100m"; + $deviceLimits .= " --device-write-bps /dev/{$device}:50m"; + $deviceLimits .= " --device-read-bps /dev/{$device}:50m"; } $expected = "sudo timeout --signal=SIGKILL 3600" @@ -176,7 +176,7 @@ public function testRunCommand() . " --cpu-shares '1024'" . " --net 'bridge'" . " --cpus '2'" - . $deviceLimits + . $deviceLimits . " --env \"var=val\"" . " --env \"příliš=žluťoučký\"" . " --env \"var2=weird = '\\\"value\"" From 353f8d48976788910d205507e00bf349a6af5a57 Mon Sep 17 00:00:00 2001 From: Ondrej Hlavacek Date: Wed, 9 May 2018 13:12:45 +0200 Subject: [PATCH 6/6] fix: cs --- Docker/Runner/Limits.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Docker/Runner/Limits.php b/Docker/Runner/Limits.php index ffe88a3c..a14ac51f 100644 --- a/Docker/Runner/Limits.php +++ b/Docker/Runner/Limits.php @@ -96,7 +96,8 @@ public function getCpuLimit(Image $image) return min($instance, $project); } - public function getDeviceIOLimits(Image $image) { + public function getDeviceIOLimits(Image $image) + { return '50m'; }