diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DockerContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DockerContainerExecutor.java index c854173..a2e53f1 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DockerContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/DockerContainerExecutor.java @@ -22,7 +22,6 @@ import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Strings; - import org.apache.commons.lang.math.RandomUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,16 +50,16 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; import java.util.regex.Pattern; -import java.net.InetSocketAddress; + import static org.apache.hadoop.fs.CreateFlag.CREATE; import static org.apache.hadoop.fs.CreateFlag.OVERWRITE; @@ -102,10 +101,14 @@ public void init() throws IOException { } String dockerExecutor = getConf().get(YarnConfiguration.NM_DOCKER_CONTAINER_EXECUTOR_EXEC_NAME, YarnConfiguration.NM_DEFAULT_DOCKER_CONTAINER_EXECUTOR_EXEC_NAME); - if (!new File(dockerExecutor).exists()) { + String[] arr = dockerExecutor.split("\\s"); + if (LOG.isDebugEnabled()) { + LOG.debug("dockerExecutor: " + dockerExecutor); + } + if (!new File(arr[0]).exists()) { throw new IllegalStateException("Invalid docker exec path: " + dockerExecutor); } - } + } @Override public synchronized void startLocalizer(Path nmPrivateContainerTokensPath, @@ -146,6 +149,7 @@ public int launchContainer(Container container, List localDirs, List logDirs) throws IOException { String containerImageName = container.getLaunchContext().getEnvironment() .get(YarnConfiguration.NM_DOCKER_CONTAINER_EXECUTOR_IMAGE_NAME); + containerImageName = Strings.isNullOrEmpty(containerImageName) ? getConf().get(YarnConfiguration.NM_DOCKER_CONTAINER_EXECUTOR_IMAGE_NAME) : containerImageName; if (LOG.isDebugEnabled()) { LOG.debug("containerImageName from launchContext: " + containerImageName); } @@ -191,8 +195,8 @@ public int launchContainer(Container container, new Path(containerWorkDir, ContainerLaunch.FINAL_CONTAINER_TOKENS_FILE); lfs.util().copy(nmPrivateTokensPath, tokenDst); - - + int memoryBytes = container.getResource().getMemory(); + int vCores = container.getResource().getVirtualCores(); String localDirMount = toMount(localDirs); String logDirMount = toMount(logDirs); String containerWorkDirMount = toMount(Collections.singletonList(containerWorkDir.toUri().getPath())); @@ -204,6 +208,13 @@ public int launchContainer(Container container, .append("--rm --net=host") .append(" ") .append(" --name " + containerIdStr) + .append(" ") + .append("--memory " + memoryBytes + "m") + .append(" ") + .append("--cpu-shares " + vCores) + .append(" ") + .append("--user " + userName) + .append(" ") .append(localDirMount) .append(logDirMount) .append(containerWorkDirMount) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutor.java index e43ac2e..0c0722c 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutor.java @@ -26,30 +26,22 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.util.Shell; -import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerLaunchContext; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; -import org.apache.hadoop.yarn.util.ConverterUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; -import java.io.LineNumberReader; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -121,7 +113,7 @@ public void setup() { exec.setConf(conf); appSubmitter = System.getProperty("application.submitter"); if (appSubmitter == null || appSubmitter.isEmpty()) { - appSubmitter = "nobody"; + appSubmitter = "root"; } shellExec(dockerExec + " pull " + testImage); @@ -147,9 +139,10 @@ private boolean shouldRun() { private int runAndBlock(ContainerId cId, Map launchCtxEnv, String... cmd) throws IOException { String appId = "APP_" + System.currentTimeMillis(); - Container container = mock(Container.class); + Container container = mock(Container.class, RETURNS_DEEP_STUBS); ContainerLaunchContext context = mock(ContainerLaunchContext.class); - + when(container.getResource().getMemory()).thenReturn(4194304); + when(container.getResource().getVirtualCores()).thenReturn(10); when(container.getContainerId()).thenReturn(cId); when(container.getLaunchContext()).thenReturn(context); when(cId.getApplicationAttemptId().getApplicationId().toString()).thenReturn(appId); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutorWithMocks.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutorWithMocks.java index 3584fed..2480227 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutorWithMocks.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestDockerContainerExecutorWithMocks.java @@ -18,7 +18,6 @@ package org.apache.hadoop.yarn.server.nodemanager; -import com.google.common.base.Strings; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; @@ -49,9 +48,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; /** * Mock tests for docker container executor @@ -219,7 +218,8 @@ public void testContainerLaunch() throws IOException { List logDirs = dirsToMount(dirsHandler.getLogDirs()); List workDirMount = dirsToMount(Collections.singletonList(workDir.toUri().getPath())); List expectedCommands = new ArrayList( - Arrays.asList(DOCKER_LAUNCH_COMMAND, "run", "--rm", "--net=host", "--name", containerId)); + Arrays.asList(DOCKER_LAUNCH_COMMAND, "run", "--rm", "--net=host", "--name", + containerId, "--memory", "0m", "--cpu-shares", "0", "--user", "nobody")); expectedCommands.addAll(localDirs); expectedCommands.addAll(logDirs); expectedCommands.addAll(workDirMount); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/DockerContainerExecutor.apt.vm b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/DockerContainerExecutor.apt.vm index db75de9..785005a 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/DockerContainerExecutor.apt.vm +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/DockerContainerExecutor.apt.vm @@ -84,6 +84,18 @@ jobs are started with the DockerContainerExecutor. ---- + Optionally you can set the following property as a default image: + +---- + + yarn.nodemanager.docker-container-executor.image-name + sequenceiq/hadoop-docker:2.4.1 + + This is the default docker image to use if no images are on the jobconf. + + +---- + Administrators should be aware that DCE doesn't currently provide user name-space isolation. This means, in particular, that software running as root in the YARN container will have root privileges in the @@ -169,7 +181,7 @@ HADOOP_MAPRED_HOME, HADOOP_YARN_HOME, and HADOOP_CONF_DIR ---- yarn.nodemanager.docker-container-executor.exec-name - docker -H=tcp://0.0.0.0:4243 + /usr/bin/docker -H=tcp://0.0.0.0:4243 Name or path to the Docker client. The tcp socket must be where docker daemon is listening.