YARN-6674 Add memory cgroup settings for opportunistic containers. (Miklos Szegedi via Haibo Chen)

This commit is contained in:
Haibo Chen 2017-08-03 09:52:35 -07:00
parent f64cfeaf61
commit c5d256c760
2 changed files with 63 additions and 17 deletions

View File

@ -25,7 +25,9 @@
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
@ -46,6 +48,8 @@ public class CGroupsMemoryResourceHandlerImpl implements MemoryResourceHandler {
CGroupsMemoryResourceHandlerImpl.class); CGroupsMemoryResourceHandlerImpl.class);
private static final CGroupsHandler.CGroupController MEMORY = private static final CGroupsHandler.CGroupController MEMORY =
CGroupsHandler.CGroupController.MEMORY; CGroupsHandler.CGroupController.MEMORY;
private static final int OPPORTUNISTIC_SWAPPINESS = 100;
private static final int OPPORTUNISTIC_SOFT_LIMIT = 0;
private CGroupsHandler cGroupsHandler; private CGroupsHandler cGroupsHandler;
private int swappiness = 0; private int swappiness = 0;
@ -85,13 +89,15 @@ public List<PrivilegedOperation> bootstrap(Configuration conf)
+ ". Value must be between 0 and 100."); + ". Value must be between 0 and 100.");
} }
float softLimitPerc = conf.getFloat( float softLimitPerc = conf.getFloat(
YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE, YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE,
YarnConfiguration.DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE); YarnConfiguration.
DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE);
softLimit = softLimitPerc / 100.0f; softLimit = softLimitPerc / 100.0f;
if (softLimitPerc < 0.0f || softLimitPerc > 100.0f) { if (softLimitPerc < 0.0f || softLimitPerc > 100.0f) {
throw new ResourceHandlerException( throw new ResourceHandlerException(
"Illegal value '" + softLimitPerc + "' " "Illegal value '" + softLimitPerc + "' "
+ YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE + YarnConfiguration.
NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE
+ ". Value must be between 0 and 100."); + ". Value must be between 0 and 100.");
} }
return null; return null;
@ -122,12 +128,23 @@ public List<PrivilegedOperation> preStart(Container container)
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId, cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
CGroupsHandler.CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES, CGroupsHandler.CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES,
String.valueOf(containerHardLimit) + "M"); String.valueOf(containerHardLimit) + "M");
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId, ContainerTokenIdentifier id = container.getContainerTokenIdentifier();
CGroupsHandler.CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES, if (id != null && id.getExecutionType() ==
String.valueOf(containerSoftLimit) + "M"); ExecutionType.OPPORTUNISTIC) {
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId, cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
CGroupsHandler.CGROUP_PARAM_MEMORY_SWAPPINESS, CGroupsHandler.CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES,
String.valueOf(swappiness)); String.valueOf(OPPORTUNISTIC_SOFT_LIMIT) + "M");
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
CGroupsHandler.CGROUP_PARAM_MEMORY_SWAPPINESS,
String.valueOf(OPPORTUNISTIC_SWAPPINESS));
} else {
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
CGroupsHandler.CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES,
String.valueOf(containerSoftLimit) + "M");
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
CGroupsHandler.CGROUP_PARAM_MEMORY_SWAPPINESS,
String.valueOf(swappiness));
}
} catch (ResourceHandlerException re) { } catch (ResourceHandlerException re) {
cGroupsHandler.deleteCGroup(MEMORY, cgroupId); cGroupsHandler.deleteCGroup(MEMORY, cgroupId);
LOG.warn("Could not update cgroup for container", re); LOG.warn("Could not update cgroup for container", re);

View File

@ -20,8 +20,10 @@
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.security.ContainerTokenIdentifier;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation; import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
import org.junit.Before; import org.junit.Before;
@ -32,6 +34,9 @@
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
/**
* Unit test for CGroupsMemoryResourceHandlerImpl.
*/
public class TestCGroupsMemoryResourceHandlerImpl { public class TestCGroupsMemoryResourceHandlerImpl {
private CGroupsHandler mockCGroupsHandler; private CGroupsHandler mockCGroupsHandler;
@ -60,8 +65,7 @@ public void testBootstrap() throws Exception {
try { try {
cGroupsMemoryResourceHandler.bootstrap(conf); cGroupsMemoryResourceHandler.bootstrap(conf);
Assert.fail("Pmem check should not be allowed to run with cgroups"); Assert.fail("Pmem check should not be allowed to run with cgroups");
} } catch(ResourceHandlerException re) {
catch(ResourceHandlerException re) {
// do nothing // do nothing
} }
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false); conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
@ -69,8 +73,7 @@ public void testBootstrap() throws Exception {
try { try {
cGroupsMemoryResourceHandler.bootstrap(conf); cGroupsMemoryResourceHandler.bootstrap(conf);
Assert.fail("Vmem check should not be allowed to run with cgroups"); Assert.fail("Vmem check should not be allowed to run with cgroups");
} } catch(ResourceHandlerException re) {
catch(ResourceHandlerException re) {
// do nothing // do nothing
} }
} }
@ -84,8 +87,7 @@ public void testSwappinessValues() throws Exception {
try { try {
cGroupsMemoryResourceHandler.bootstrap(conf); cGroupsMemoryResourceHandler.bootstrap(conf);
Assert.fail("Negative values for swappiness should not be allowed."); Assert.fail("Negative values for swappiness should not be allowed.");
} } catch (ResourceHandlerException re) {
catch (ResourceHandlerException re) {
// do nothing // do nothing
} }
try { try {
@ -93,8 +95,7 @@ public void testSwappinessValues() throws Exception {
cGroupsMemoryResourceHandler.bootstrap(conf); cGroupsMemoryResourceHandler.bootstrap(conf);
Assert.fail("Values greater than 100 for swappiness" Assert.fail("Values greater than 100 for swappiness"
+ " should not be allowed."); + " should not be allowed.");
} } catch (ResourceHandlerException re) {
catch (ResourceHandlerException re) {
// do nothing // do nothing
} }
conf.setInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS, 60); conf.setInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS, 60);
@ -169,4 +170,32 @@ public void testPostComplete() throws Exception {
public void testTeardown() throws Exception { public void testTeardown() throws Exception {
Assert.assertNull(cGroupsMemoryResourceHandler.teardown()); Assert.assertNull(cGroupsMemoryResourceHandler.teardown());
} }
@Test
public void testOpportunistic() throws Exception {
Configuration conf = new YarnConfiguration();
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, false);
cGroupsMemoryResourceHandler.bootstrap(conf);
ContainerTokenIdentifier tokenId = mock(ContainerTokenIdentifier.class);
when(tokenId.getExecutionType()).thenReturn(ExecutionType.OPPORTUNISTIC);
Container container = mock(Container.class);
String id = "container_01_01";
ContainerId mockContainerId = mock(ContainerId.class);
when(mockContainerId.toString()).thenReturn(id);
when(container.getContainerId()).thenReturn(mockContainerId);
when(container.getContainerTokenIdentifier()).thenReturn(tokenId);
when(container.getResource()).thenReturn(Resource.newInstance(1024, 2));
cGroupsMemoryResourceHandler.preStart(container);
verify(mockCGroupsHandler, times(1))
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
CGroupsHandler.CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES, "0M");
verify(mockCGroupsHandler, times(1))
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
CGroupsHandler.CGROUP_PARAM_MEMORY_SWAPPINESS, "100");
verify(mockCGroupsHandler, times(1))
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
CGroupsHandler.CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES, "1024M");
}
} }