YARN-4553. Add cgroups support for docker containers. Contributed by Sidharta Seethana.
This commit is contained in:
parent
62b0d61513
commit
3ddb92bd30
|
@ -94,6 +94,9 @@ Release 2.9.0 - UNRELEASED
|
|||
YARN-4551. Address the duplication between StatusUpdateWhenHealthy and
|
||||
StatusUpdateWhenUnhealthy transitions. (Sunil G via kasha)
|
||||
|
||||
YARN-4553. Add cgroups support for docker containers.
|
||||
(Sidharta Seethana via vvasudev)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
BUG FIXES
|
||||
|
|
|
@ -27,6 +27,9 @@ import org.apache.hadoop.classification.InterfaceStability;
|
|||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsHandler;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.ResourceHandlerException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.ResourceHandlerModule;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext;
|
||||
|
||||
|
@ -45,12 +48,19 @@ public class DelegatingLinuxContainerRuntime implements LinuxContainerRuntime {
|
|||
throws ContainerExecutionException {
|
||||
PrivilegedOperationExecutor privilegedOperationExecutor =
|
||||
PrivilegedOperationExecutor.getInstance(conf);
|
||||
CGroupsHandler cGroupsHandler;
|
||||
try {
|
||||
cGroupsHandler = ResourceHandlerModule.getCGroupsHandler(conf);
|
||||
} catch (ResourceHandlerException e) {
|
||||
LOG.error("Unable to get cgroups handle.");
|
||||
throw new ContainerExecutionException(e);
|
||||
}
|
||||
|
||||
defaultLinuxContainerRuntime = new DefaultLinuxContainerRuntime(
|
||||
privilegedOperationExecutor);
|
||||
defaultLinuxContainerRuntime.initialize(conf);
|
||||
dockerLinuxContainerRuntime = new DockerLinuxContainerRuntime(
|
||||
privilegedOperationExecutor);
|
||||
privilegedOperationExecutor, cGroupsHandler);
|
||||
dockerLinuxContainerRuntime.initialize(conf);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileg
|
|||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsHandler;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.ResourceHandlerException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.ResourceHandlerModule;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerClient;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRunCommand;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException;
|
||||
|
@ -76,6 +74,7 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
|||
private Configuration conf;
|
||||
private DockerClient dockerClient;
|
||||
private PrivilegedOperationExecutor privilegedOperationExecutor;
|
||||
private CGroupsHandler cGroupsHandler;
|
||||
private AccessControlList privilegedContainersAcl;
|
||||
|
||||
public static boolean isDockerContainerRequested(
|
||||
|
@ -90,8 +89,9 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
|||
}
|
||||
|
||||
public DockerLinuxContainerRuntime(PrivilegedOperationExecutor
|
||||
privilegedOperationExecutor) {
|
||||
privilegedOperationExecutor, CGroupsHandler cGroupsHandler) {
|
||||
this.privilegedOperationExecutor = privilegedOperationExecutor;
|
||||
this.cGroupsHandler = cGroupsHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,30 +116,23 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
|||
if (resourcesOptions.equals(
|
||||
(PrivilegedOperation.CGROUP_ARG_PREFIX + PrivilegedOperation
|
||||
.CGROUP_ARG_NO_TASKS))) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("no resource restrictions specified. not using docker's "
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("no resource restrictions specified. not using docker's "
|
||||
+ "cgroup options");
|
||||
}
|
||||
} else {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("using docker's cgroups options");
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("using docker's cgroups options");
|
||||
}
|
||||
|
||||
try {
|
||||
CGroupsHandler cGroupsHandler = ResourceHandlerModule
|
||||
.getCGroupsHandler(conf);
|
||||
String cGroupPath = "/" + cGroupsHandler.getRelativePathForCGroup(
|
||||
containerIdStr);
|
||||
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("using cgroup parent: " + cGroupPath);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("using cgroup parent: " + cGroupPath);
|
||||
}
|
||||
|
||||
runCommand.setCGroupParent(cGroupPath);
|
||||
} catch (ResourceHandlerException e) {
|
||||
LOG.warn("unable to use cgroups handler. Exception: ", e);
|
||||
throw new ContainerExecutionException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,11 +249,7 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
|
|||
|
||||
String resourcesOpts = ctx.getExecutionAttribute(RESOURCES_OPTIONS);
|
||||
|
||||
/** Disabling docker's cgroup parent support for the time being. Docker
|
||||
* needs to use a more recent libcontainer that supports net_cls. In
|
||||
* addition we also need to revisit current cgroup creation in YARN.
|
||||
*/
|
||||
//addCGroupParentIfRequired(resourcesOpts, containerIdStr, runCommand);
|
||||
addCGroupParentIfRequired(resourcesOpts, containerIdStr, runCommand);
|
||||
|
||||
Path nmPrivateContainerScriptPath = ctx.getExecutionAttribute(
|
||||
NM_PRIVATE_CONTAINER_SCRIPT_PATH);
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Cont
|
|||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperation;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.privileged.PrivilegedOperationExecutor;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.resources.CGroupsHandler;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker.DockerRunCommand;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeConstants;
|
||||
import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerRuntimeContext;
|
||||
|
@ -62,6 +64,7 @@ public class TestDockerContainerRuntime {
|
|||
.getLog(TestDockerContainerRuntime.class);
|
||||
private Configuration conf;
|
||||
PrivilegedOperationExecutor mockExecutor;
|
||||
CGroupsHandler mockCGroupsHandler;
|
||||
String containerId;
|
||||
Container container;
|
||||
ContainerId cId;
|
||||
|
@ -94,6 +97,7 @@ public class TestDockerContainerRuntime {
|
|||
|
||||
mockExecutor = Mockito
|
||||
.mock(PrivilegedOperationExecutor.class);
|
||||
mockCGroupsHandler = Mockito.mock(CGroupsHandler.class);
|
||||
containerId = "container_id";
|
||||
container = mock(Container.class);
|
||||
cId = mock(ContainerId.class);
|
||||
|
@ -118,7 +122,7 @@ public class TestDockerContainerRuntime {
|
|||
pidFilePath = new Path("/test_pid_file_path");
|
||||
localDirs = new ArrayList<>();
|
||||
logDirs = new ArrayList<>();
|
||||
resourcesOptions = "cgroups:none";
|
||||
resourcesOptions = "cgroups=none";
|
||||
|
||||
localDirs.add("/test_local_dir");
|
||||
logDirs.add("/test_log_dir");
|
||||
|
@ -204,7 +208,7 @@ public class TestDockerContainerRuntime {
|
|||
throws ContainerExecutionException, PrivilegedOperationException,
|
||||
IOException {
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
String[] testCapabilities = {"NET_BIND_SERVICE", "SYS_CHROOT"};
|
||||
|
@ -256,7 +260,7 @@ public class TestDockerContainerRuntime {
|
|||
throws ContainerExecutionException, PrivilegedOperationException,
|
||||
IOException{
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER",
|
||||
|
@ -284,7 +288,7 @@ public class TestDockerContainerRuntime {
|
|||
throws ContainerExecutionException, PrivilegedOperationException,
|
||||
IOException{
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER",
|
||||
|
@ -307,7 +311,7 @@ public class TestDockerContainerRuntime {
|
|||
true);
|
||||
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER",
|
||||
|
@ -338,7 +342,7 @@ public class TestDockerContainerRuntime {
|
|||
whitelistedUser);
|
||||
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER",
|
||||
|
@ -365,7 +369,7 @@ public class TestDockerContainerRuntime {
|
|||
submittingUser);
|
||||
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
|
||||
mockExecutor);
|
||||
mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
env.put("YARN_CONTAINER_RUNTIME_DOCKER_RUN_PRIVILEGED_CONTAINER",
|
||||
|
@ -388,4 +392,34 @@ public class TestDockerContainerRuntime {
|
|||
+ ": " + command, command.contains("--privileged"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCGroupParent() throws ContainerExecutionException {
|
||||
String hierarchy = "hadoop-yarn-test";
|
||||
conf.set(YarnConfiguration.NM_LINUX_CONTAINER_CGROUPS_HIERARCHY,
|
||||
hierarchy);
|
||||
|
||||
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime
|
||||
(mockExecutor, mockCGroupsHandler);
|
||||
runtime.initialize(conf);
|
||||
|
||||
String resourceOptionsNone = "cgroups=none";
|
||||
DockerRunCommand command = Mockito.mock(DockerRunCommand.class);
|
||||
|
||||
Mockito.when(mockCGroupsHandler.getRelativePathForCGroup(containerId))
|
||||
.thenReturn(hierarchy + "/" + containerIdStr);
|
||||
runtime.addCGroupParentIfRequired(resourceOptionsNone, containerIdStr,
|
||||
command);
|
||||
|
||||
//no --cgroup-parent should be added here
|
||||
Mockito.verifyZeroInteractions(command);
|
||||
|
||||
String resourceOptionsCpu = "/sys/fs/cgroup/cpu/" + hierarchy +
|
||||
containerIdStr;
|
||||
runtime.addCGroupParentIfRequired(resourceOptionsCpu, containerIdStr,
|
||||
command);
|
||||
|
||||
//--cgroup-parent should be added for the containerId in question
|
||||
String expectedPath = "/" + hierarchy + "/" + containerIdStr;
|
||||
Mockito.verify(command).setCGroupParent(expectedPath);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue