YARN-1856. Added cgroups based memory monitoring for containers as another alternative to custom memory-monitoring. Contributed by Varun Vasudev.
(cherry picked from commit 4e7d32c0db
)
This commit is contained in:
parent
a5c74cd921
commit
d9b9a75928
|
@ -6,6 +6,9 @@ Release 2.9.0 - UNRELEASED
|
||||||
|
|
||||||
NEW FEATURES
|
NEW FEATURES
|
||||||
|
|
||||||
|
YARN-1856. Added cgroups based memory monitoring for containers as another
|
||||||
|
alternative to custom memory-monitoring. (Varun Vasudev via vinodkv)
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
|
|
||||||
YARN-4072. ApplicationHistoryServer, WebAppProxyServer, NodeManager and
|
YARN-4072. ApplicationHistoryServer, WebAppProxyServer, NodeManager and
|
||||||
|
|
|
@ -905,6 +905,30 @@ public class YarnConfiguration extends Configuration {
|
||||||
public static final boolean DEFAULT_NM_ENABLE_HARDWARE_CAPABILITY_DETECTION =
|
public static final boolean DEFAULT_NM_ENABLE_HARDWARE_CAPABILITY_DETECTION =
|
||||||
false;
|
false;
|
||||||
|
|
||||||
|
@Private
|
||||||
|
public static final String NM_MEMORY_RESOURCE_PREFIX = NM_PREFIX
|
||||||
|
+ "resource.memory.";
|
||||||
|
|
||||||
|
@Private
|
||||||
|
public static final String NM_MEMORY_RESOURCE_ENABLED =
|
||||||
|
NM_MEMORY_RESOURCE_PREFIX + "enabled";
|
||||||
|
@Private
|
||||||
|
public static final boolean DEFAULT_NM_MEMORY_RESOURCE_ENABLED = false;
|
||||||
|
|
||||||
|
@Private
|
||||||
|
public static final String NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS =
|
||||||
|
NM_MEMORY_RESOURCE_PREFIX + "cgroups.swappiness";
|
||||||
|
@Private
|
||||||
|
public static final int DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS = 0;
|
||||||
|
|
||||||
|
@Private
|
||||||
|
public static final String NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE =
|
||||||
|
NM_MEMORY_RESOURCE_PREFIX + "cgroups.soft-limit-percentage";
|
||||||
|
@Private
|
||||||
|
public static final float
|
||||||
|
DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE =
|
||||||
|
90.0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix for disk configurations. Work in progress: This configuration
|
* Prefix for disk configurations. Work in progress: This configuration
|
||||||
* parameter may be changed/removed in the future.
|
* parameter may be changed/removed in the future.
|
||||||
|
|
|
@ -108,6 +108,8 @@ public class TestYarnConfigurationFields extends TestConfigurationFieldsBase {
|
||||||
.add(YarnConfiguration.NM_NETWORK_RESOURCE_OUTBOUND_BANDWIDTH_YARN_MBIT);
|
.add(YarnConfiguration.NM_NETWORK_RESOURCE_OUTBOUND_BANDWIDTH_YARN_MBIT);
|
||||||
configurationPrefixToSkipCompare
|
configurationPrefixToSkipCompare
|
||||||
.add(YarnConfiguration.NM_DISK_RESOURCE_ENABLED);
|
.add(YarnConfiguration.NM_DISK_RESOURCE_ENABLED);
|
||||||
|
configurationPrefixToSkipCompare
|
||||||
|
.add(YarnConfiguration.NM_MEMORY_RESOURCE_PREFIX);
|
||||||
|
|
||||||
// Set by container-executor.cfg
|
// Set by container-executor.cfg
|
||||||
configurationPrefixToSkipCompare.add(YarnConfiguration.NM_USER_HOME_DIR);
|
configurationPrefixToSkipCompare.add(YarnConfiguration.NM_USER_HOME_DIR);
|
||||||
|
|
|
@ -31,10 +31,12 @@ import org.apache.hadoop.classification.InterfaceStability;
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
@InterfaceStability.Unstable
|
@InterfaceStability.Unstable
|
||||||
public interface CGroupsHandler {
|
public interface CGroupsHandler {
|
||||||
|
|
||||||
public enum CGroupController {
|
public enum CGroupController {
|
||||||
CPU("cpu"),
|
CPU("cpu"),
|
||||||
NET_CLS("net_cls"),
|
NET_CLS("net_cls"),
|
||||||
BLKIO("blkio");
|
BLKIO("blkio"),
|
||||||
|
MEMORY("memory");
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@ -51,6 +53,11 @@ public interface CGroupsHandler {
|
||||||
public static final String CGROUP_PARAM_CLASSID = "classid";
|
public static final String CGROUP_PARAM_CLASSID = "classid";
|
||||||
public static final String CGROUP_PARAM_BLKIO_WEIGHT = "weight";
|
public static final String CGROUP_PARAM_BLKIO_WEIGHT = "weight";
|
||||||
|
|
||||||
|
String CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES = "limit_in_bytes";
|
||||||
|
String CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES = "soft_limit_in_bytes";
|
||||||
|
String CGROUP_PARAM_MEMORY_SWAPPINESS = "swappiness";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mounts a cgroup controller
|
* Mounts a cgroup controller
|
||||||
* @param controller - the controller being mounted
|
* @param controller - the controller being mounted
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ContainerId;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler class to handle the memory controller. YARN already ships a
|
||||||
|
* physical memory monitor in Java but it isn't as
|
||||||
|
* good as CGroups. This handler sets the soft and hard memory limits. The soft
|
||||||
|
* limit is set to 90% of the hard limit.
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
@InterfaceStability.Unstable
|
||||||
|
public class CGroupsMemoryResourceHandlerImpl implements MemoryResourceHandler {
|
||||||
|
|
||||||
|
static final Log LOG = LogFactory.getLog(
|
||||||
|
CGroupsMemoryResourceHandlerImpl.class);
|
||||||
|
private static final CGroupsHandler.CGroupController MEMORY =
|
||||||
|
CGroupsHandler.CGroupController.MEMORY;
|
||||||
|
|
||||||
|
private CGroupsHandler cGroupsHandler;
|
||||||
|
private int swappiness = 0;
|
||||||
|
// multiplier to set the soft limit - value should be between 0 and 1
|
||||||
|
private float softLimit = 0.0f;
|
||||||
|
|
||||||
|
CGroupsMemoryResourceHandlerImpl(CGroupsHandler cGroupsHandler) {
|
||||||
|
this.cGroupsHandler = cGroupsHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrivilegedOperation> bootstrap(Configuration conf)
|
||||||
|
throws ResourceHandlerException {
|
||||||
|
boolean pmemEnabled =
|
||||||
|
conf.getBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED,
|
||||||
|
YarnConfiguration.DEFAULT_NM_PMEM_CHECK_ENABLED);
|
||||||
|
boolean vmemEnabled =
|
||||||
|
conf.getBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED,
|
||||||
|
YarnConfiguration.DEFAULT_NM_VMEM_CHECK_ENABLED);
|
||||||
|
if (pmemEnabled || vmemEnabled) {
|
||||||
|
String msg = "The default YARN physical and/or virtual memory health"
|
||||||
|
+ " checkers as well as the CGroups memory controller are enabled. "
|
||||||
|
+ "If you wish to use the Cgroups memory controller, please turn off"
|
||||||
|
+ " the default physical/virtual memory checkers by setting "
|
||||||
|
+ YarnConfiguration.NM_PMEM_CHECK_ENABLED + " and "
|
||||||
|
+ YarnConfiguration.NM_VMEM_CHECK_ENABLED + " to false.";
|
||||||
|
throw new ResourceHandlerException(msg);
|
||||||
|
}
|
||||||
|
this.cGroupsHandler.mountCGroupController(MEMORY);
|
||||||
|
swappiness = conf
|
||||||
|
.getInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS,
|
||||||
|
YarnConfiguration.DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS);
|
||||||
|
if (swappiness < 0 || swappiness > 100) {
|
||||||
|
throw new ResourceHandlerException(
|
||||||
|
"Illegal value '" + swappiness + "' for "
|
||||||
|
+ YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS
|
||||||
|
+ ". Value must be between 0 and 100.");
|
||||||
|
}
|
||||||
|
float softLimitPerc = conf.getFloat(
|
||||||
|
YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE,
|
||||||
|
YarnConfiguration.DEFAULT_NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE);
|
||||||
|
softLimit = softLimitPerc / 100.0f;
|
||||||
|
if (softLimitPerc < 0.0f || softLimitPerc > 100.0f) {
|
||||||
|
throw new ResourceHandlerException(
|
||||||
|
"Illegal value '" + softLimitPerc + "' "
|
||||||
|
+ YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SOFT_LIMIT_PERCENTAGE
|
||||||
|
+ ". Value must be between 0 and 100.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
int getSwappiness() {
|
||||||
|
return swappiness;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrivilegedOperation> reacquireContainer(ContainerId containerId)
|
||||||
|
throws ResourceHandlerException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrivilegedOperation> preStart(Container container)
|
||||||
|
throws ResourceHandlerException {
|
||||||
|
|
||||||
|
String cgroupId = container.getContainerId().toString();
|
||||||
|
//memory is in MB
|
||||||
|
long containerSoftLimit =
|
||||||
|
(long) (container.getResource().getMemory() * this.softLimit);
|
||||||
|
long containerHardLimit = container.getResource().getMemory();
|
||||||
|
cGroupsHandler.createCGroup(MEMORY, cgroupId);
|
||||||
|
try {
|
||||||
|
cGroupsHandler.updateCGroupParam(MEMORY, cgroupId,
|
||||||
|
CGroupsHandler.CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES,
|
||||||
|
String.valueOf(containerHardLimit) + "M");
|
||||||
|
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) {
|
||||||
|
cGroupsHandler.deleteCGroup(MEMORY, cgroupId);
|
||||||
|
LOG.warn("Could not update cgroup for container", re);
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
|
List<PrivilegedOperation> ret = new ArrayList<>();
|
||||||
|
ret.add(new PrivilegedOperation(
|
||||||
|
PrivilegedOperation.OperationType.ADD_PID_TO_CGROUP,
|
||||||
|
PrivilegedOperation.CGROUP_ARG_PREFIX
|
||||||
|
+ cGroupsHandler.getPathForCGroupTasks(MEMORY, cgroupId)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrivilegedOperation> postComplete(ContainerId containerId)
|
||||||
|
throws ResourceHandlerException {
|
||||||
|
cGroupsHandler.deleteCGroup(MEMORY, containerId.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrivilegedOperation> teardown() throws ResourceHandlerException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
|
||||||
|
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
|
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
@InterfaceStability.Unstable
|
||||||
|
public interface MemoryResourceHandler extends ResourceHandler {
|
||||||
|
}
|
|
@ -50,6 +50,8 @@ public class ResourceHandlerModule {
|
||||||
private static volatile CGroupsHandler cGroupsHandler;
|
private static volatile CGroupsHandler cGroupsHandler;
|
||||||
private static volatile CGroupsBlkioResourceHandlerImpl
|
private static volatile CGroupsBlkioResourceHandlerImpl
|
||||||
cGroupsBlkioResourceHandler;
|
cGroupsBlkioResourceHandler;
|
||||||
|
private static volatile CGroupsMemoryResourceHandlerImpl
|
||||||
|
cGroupsMemoryResourceHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an initialized, thread-safe CGroupsHandler instance.
|
* Returns an initialized, thread-safe CGroupsHandler instance.
|
||||||
|
@ -69,7 +71,7 @@ public class ResourceHandlerModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TrafficControlBandwidthHandlerImpl
|
private static TrafficControlBandwidthHandlerImpl
|
||||||
getTrafficControlBandwidthHandler(Configuration conf)
|
getTrafficControlBandwidthHandler(Configuration conf)
|
||||||
throws ResourceHandlerException {
|
throws ResourceHandlerException {
|
||||||
if (conf.getBoolean(YarnConfiguration.NM_NETWORK_RESOURCE_ENABLED,
|
if (conf.getBoolean(YarnConfiguration.NM_NETWORK_RESOURCE_ENABLED,
|
||||||
YarnConfiguration.DEFAULT_NM_NETWORK_RESOURCE_ENABLED)) {
|
YarnConfiguration.DEFAULT_NM_NETWORK_RESOURCE_ENABLED)) {
|
||||||
|
@ -92,7 +94,7 @@ public class ResourceHandlerModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OutboundBandwidthResourceHandler
|
public static OutboundBandwidthResourceHandler
|
||||||
getOutboundBandwidthResourceHandler(Configuration conf)
|
getOutboundBandwidthResourceHandler(Configuration conf)
|
||||||
throws ResourceHandlerException {
|
throws ResourceHandlerException {
|
||||||
return getTrafficControlBandwidthHandler(conf);
|
return getTrafficControlBandwidthHandler(conf);
|
||||||
}
|
}
|
||||||
|
@ -119,6 +121,29 @@ public class ResourceHandlerModule {
|
||||||
return cGroupsBlkioResourceHandler;
|
return cGroupsBlkioResourceHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemoryResourceHandler getMemoryResourceHandler(
|
||||||
|
Configuration conf) throws ResourceHandlerException {
|
||||||
|
if (conf.getBoolean(YarnConfiguration.NM_MEMORY_RESOURCE_ENABLED,
|
||||||
|
YarnConfiguration.DEFAULT_NM_MEMORY_RESOURCE_ENABLED)) {
|
||||||
|
return getCgroupsMemoryResourceHandler(conf);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CGroupsMemoryResourceHandlerImpl
|
||||||
|
getCgroupsMemoryResourceHandler(
|
||||||
|
Configuration conf) throws ResourceHandlerException {
|
||||||
|
if (cGroupsMemoryResourceHandler == null) {
|
||||||
|
synchronized (MemoryResourceHandler.class) {
|
||||||
|
if (cGroupsMemoryResourceHandler == null) {
|
||||||
|
cGroupsMemoryResourceHandler =
|
||||||
|
new CGroupsMemoryResourceHandlerImpl(getCGroupsHandler(conf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cGroupsMemoryResourceHandler;
|
||||||
|
}
|
||||||
|
|
||||||
private static void addHandlerIfNotNull(List<ResourceHandler> handlerList,
|
private static void addHandlerIfNotNull(List<ResourceHandler> handlerList,
|
||||||
ResourceHandler handler) {
|
ResourceHandler handler) {
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
|
@ -132,6 +157,7 @@ public class ResourceHandlerModule {
|
||||||
|
|
||||||
addHandlerIfNotNull(handlerList, getOutboundBandwidthResourceHandler(conf));
|
addHandlerIfNotNull(handlerList, getOutboundBandwidthResourceHandler(conf));
|
||||||
addHandlerIfNotNull(handlerList, getDiskResourceHandler(conf));
|
addHandlerIfNotNull(handlerList, getDiskResourceHandler(conf));
|
||||||
|
addHandlerIfNotNull(handlerList, getMemoryResourceHandler(conf));
|
||||||
resourceHandlerChain = new ResourceHandlerChain(handlerList);
|
resourceHandlerChain = new ResourceHandlerChain(handlerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.yarn.api.records.ContainerId;
|
||||||
|
import org.apache.hadoop.yarn.api.records.Resource;
|
||||||
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
|
||||||
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
public class TestCGroupsMemoryResourceHandlerImpl {
|
||||||
|
|
||||||
|
private CGroupsHandler mockCGroupsHandler;
|
||||||
|
private CGroupsMemoryResourceHandlerImpl cGroupsMemoryResourceHandler;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
mockCGroupsHandler = mock(CGroupsHandler.class);
|
||||||
|
cGroupsMemoryResourceHandler =
|
||||||
|
new CGroupsMemoryResourceHandlerImpl(mockCGroupsHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBootstrap() throws Exception {
|
||||||
|
Configuration conf = new YarnConfiguration();
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, false);
|
||||||
|
List<PrivilegedOperation> ret =
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.mountCGroupController(CGroupsHandler.CGroupController.MEMORY);
|
||||||
|
Assert.assertNull(ret);
|
||||||
|
Assert.assertEquals("Default swappiness value incorrect", 0,
|
||||||
|
cGroupsMemoryResourceHandler.getSwappiness());
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, true);
|
||||||
|
try {
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
Assert.fail("Pmem check should not be allowed to run with cgroups");
|
||||||
|
}
|
||||||
|
catch(ResourceHandlerException re) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, true);
|
||||||
|
try {
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
Assert.fail("Vmem check should not be allowed to run with cgroups");
|
||||||
|
}
|
||||||
|
catch(ResourceHandlerException re) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwappinessValues() throws Exception {
|
||||||
|
Configuration conf = new YarnConfiguration();
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, false);
|
||||||
|
conf.setInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS, -1);
|
||||||
|
try {
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
Assert.fail("Negative values for swappiness should not be allowed.");
|
||||||
|
}
|
||||||
|
catch (ResourceHandlerException re) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
conf.setInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS, 101);
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
Assert.fail("Values greater than 100 for swappiness"
|
||||||
|
+ " should not be allowed.");
|
||||||
|
}
|
||||||
|
catch (ResourceHandlerException re) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
conf.setInt(YarnConfiguration.NM_MEMORY_RESOURCE_CGROUPS_SWAPPINESS, 60);
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
Assert.assertEquals("Swappiness value incorrect", 60,
|
||||||
|
cGroupsMemoryResourceHandler.getSwappiness());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreStart() throws Exception {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_PMEM_CHECK_ENABLED, false);
|
||||||
|
conf.setBoolean(YarnConfiguration.NM_VMEM_CHECK_ENABLED, false);
|
||||||
|
cGroupsMemoryResourceHandler.bootstrap(conf);
|
||||||
|
String id = "container_01_01";
|
||||||
|
String path = "test-path/" + id;
|
||||||
|
ContainerId mockContainerId = mock(ContainerId.class);
|
||||||
|
when(mockContainerId.toString()).thenReturn(id);
|
||||||
|
Container mockContainer = mock(Container.class);
|
||||||
|
when(mockContainer.getContainerId()).thenReturn(mockContainerId);
|
||||||
|
when(mockCGroupsHandler
|
||||||
|
.getPathForCGroupTasks(CGroupsHandler.CGroupController.MEMORY, id))
|
||||||
|
.thenReturn(path);
|
||||||
|
int memory = 1024;
|
||||||
|
when(mockContainer.getResource())
|
||||||
|
.thenReturn(Resource.newInstance(memory, 1));
|
||||||
|
List<PrivilegedOperation> ret =
|
||||||
|
cGroupsMemoryResourceHandler.preStart(mockContainer);
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.createCGroup(CGroupsHandler.CGroupController.MEMORY, id);
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
|
||||||
|
CGroupsHandler.CGROUP_PARAM_MEMORY_HARD_LIMIT_BYTES,
|
||||||
|
String.valueOf(memory) + "M");
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
|
||||||
|
CGroupsHandler.CGROUP_PARAM_MEMORY_SOFT_LIMIT_BYTES,
|
||||||
|
String.valueOf((int) (memory * 0.9)) + "M");
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.updateCGroupParam(CGroupsHandler.CGroupController.MEMORY, id,
|
||||||
|
CGroupsHandler.CGROUP_PARAM_MEMORY_SWAPPINESS, String.valueOf(0));
|
||||||
|
Assert.assertNotNull(ret);
|
||||||
|
Assert.assertEquals(1, ret.size());
|
||||||
|
PrivilegedOperation op = ret.get(0);
|
||||||
|
Assert.assertEquals(PrivilegedOperation.OperationType.ADD_PID_TO_CGROUP,
|
||||||
|
op.getOperationType());
|
||||||
|
List<String> args = op.getArguments();
|
||||||
|
Assert.assertEquals(1, args.size());
|
||||||
|
Assert.assertEquals(PrivilegedOperation.CGROUP_ARG_PREFIX + path,
|
||||||
|
args.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReacquireContainer() throws Exception {
|
||||||
|
ContainerId containerIdMock = mock(ContainerId.class);
|
||||||
|
Assert.assertNull(
|
||||||
|
cGroupsMemoryResourceHandler.reacquireContainer(containerIdMock));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostComplete() throws Exception {
|
||||||
|
String id = "container_01_01";
|
||||||
|
ContainerId mockContainerId = mock(ContainerId.class);
|
||||||
|
when(mockContainerId.toString()).thenReturn(id);
|
||||||
|
Assert
|
||||||
|
.assertNull(cGroupsMemoryResourceHandler.postComplete(mockContainerId));
|
||||||
|
verify(mockCGroupsHandler, times(1))
|
||||||
|
.deleteCGroup(CGroupsHandler.CGroupController.MEMORY, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTeardown() throws Exception {
|
||||||
|
Assert.assertNull(cGroupsMemoryResourceHandler.teardown());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue