commit 8a0a4bdfbfaa202dc4b2d3c74269854ca0c04d8f Author: Eric Yang Date: Mon Mar 5 20:02:40 2018 -0500 YARN-7654. Added support for docker ENTRY_PONT. Contributed by Eric Yang diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java index 7015591..d4a0aef 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/main/java/org/apache/hadoop/yarn/service/provider/AbstractProviderService.java @@ -18,6 +18,7 @@ package org.apache.hadoop.yarn.service.provider; import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.records.Container; @@ -49,6 +50,10 @@ protected static final Logger log = LoggerFactory.getLogger(AbstractProviderService.class); + @InterfaceAudience.Private + public static final String ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE = + "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE"; + public abstract void processArtifact(AbstractLauncher launcher, ComponentInstance compInstance, SliderFileSystem fileSystem, Service service) @@ -100,7 +105,12 @@ public void buildContainerLaunchContext(AbstractLauncher launcher, .substituteStrWithTokens(launchCommand, tokensForSubstitution); CommandLineBuilder operation = new CommandLineBuilder(); operation.add(launchCommand); - operation.addOutAndErrFiles(OUT_FILE, ERR_FILE); + if (component.getConfiguration() + .getEnv(ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE) == null || + component.getConfiguration() + .getEnv(ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE).equals("false")) { + operation.addOutAndErrFiles(OUT_FILE, ERR_FILE); + } launcher.addCommand(operation.build()); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java index 01cd992..46fb7e4 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java @@ -51,6 +51,7 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.ContainerDiagnosticsUpdateEvent; import org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch; 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.executor.ContainerPrepareContext; import org.apache.hadoop.yarn.server.nodemanager.util.NodeManagerHardwareUtils; import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerLivenessContext; @@ -66,6 +67,8 @@ import static org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.CONTAINER_PRE_LAUNCH_STDERR; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.CONTAINER_PRE_LAUNCH_STDOUT; +import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE; +import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_RUN_CMD; /** * This class is abstraction of the mechanism used to launch a container on the @@ -429,8 +432,21 @@ public void writeLaunchEnv(OutputStream out, Map environment, new Path(logDir, outFilename)); sb.listDebugInformation(new Path(logDir, DIRECTORY_CONTENTS)); } + sb.initializeLogs(user, logDir); sb.echo("Launching container"); - sb.command(command); + if (environment.containsKey(ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE) && + environment.containsKey(ContainerRuntimeConstants.ENV_CONTAINER_TYPE) && + environment.get(ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE) + .equalsIgnoreCase("true") && + environment.get(ContainerRuntimeConstants.ENV_CONTAINER_TYPE) + .equals("docker") + ) { + for (String launchCmd : command) { + sb.env(ENV_DOCKER_CONTAINER_RUN_CMD,launchCmd); + } + } else { + sb.command(command); + } PrintStream pout = null; try { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java index b4f03fc..490f7c7 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java @@ -1221,6 +1221,8 @@ boolean doRedirectStdErr() { return redirectStdErr; } + public abstract void initializeLogs(String user, Path logDir); + } private static final class UnixShellScriptBuilder extends ShellScriptBuilder { @@ -1317,6 +1319,14 @@ public void listDebugInformation(Path output) throws IOException { public void setExitOnFailure() { line("set -o pipefail -e"); } + + @Override + public void initializeLogs(String user, Path logDir) { + line("touch ", logDir.toUri().getPath(), "/stderr.txt"); + line("touch ", logDir.toUri().getPath(), "/stdout.txt"); + line("chown ", user, " ", logDir.toUri().getPath(), "/*"); + + } } private static final class WindowsShellScriptBuilder @@ -1403,6 +1413,10 @@ public void listDebugInformation(Path output) throws IOException { String.format("@echo \"dir:\" > \"%s\"", output.toString())); lineWithLenCheck(String.format("dir >> \"%s\"", output.toString())); } + + @Override + public void initializeLogs(String user, Path logDir) { + } } private static void putEnvIfNotNull( diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java index 48c802f..774bfb8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java @@ -202,6 +202,9 @@ public static final String ENV_DOCKER_CONTAINER_RUN_OVERRIDE_DISABLE = "YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE"; @InterfaceAudience.Private + public static final String ENV_DOCKER_CONTAINER_RUN_CMD = + "YARN_CONTAINER_RUNTIME_DOCKER_RUN_CMD"; + @InterfaceAudience.Private public static final String ENV_DOCKER_CONTAINER_NETWORK = "YARN_CONTAINER_RUNTIME_DOCKER_CONTAINER_NETWORK"; @InterfaceAudience.Private @@ -778,7 +781,6 @@ public void launchContainer(ContainerRuntimeContext ctx) @SuppressWarnings("unchecked") DockerRunCommand runCommand = new DockerRunCommand(containerIdStr, dockerRunAsUser, imageName) - .detachOnRun() .setContainerWorkDir(containerWorkDir.toString()) .setNetworkType(network); setHostname(runCommand, containerIdStr, hostname); @@ -853,6 +855,11 @@ public void launchContainer(ContainerRuntimeContext ctx) if (disableOverride != null && disableOverride.equals("true")) { LOG.info("command override disabled"); + runCommand.setOverrideDisabled(true); + List overrideCommands = new ArrayList<>(); + overrideCommands.add("$YARN_CONTAINER_RUNTIME_DOCKER_RUN_CMD"); + runCommand.setOverrideCommandWithArgs(overrideCommands); + runCommand.disableDetach(); } else { List overrideCommands = new ArrayList<>(); Path launchDst = @@ -861,6 +868,7 @@ public void launchContainer(ContainerRuntimeContext ctx) overrideCommands.add("bash"); overrideCommands.add(launchDst.toUri().getPath()); runCommand.setOverrideCommandWithArgs(overrideCommands); + runCommand.detachOnRun(); } if(enableUserReMapping) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java index b7e84d7..9aafeed 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerRunCommand.java @@ -160,4 +160,13 @@ public DockerRunCommand setOverrideCommandWithArgs( public Map> getDockerCommandWithArguments() { return super.getDockerCommandWithArguments(); } + + public DockerRunCommand setOverrideDisabled(boolean toggle) { + String value = "false"; + if (toggle) { + value = "true"; + } + super.addCommandArguments("use-entry-point", value); + return this; + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c index 5ce6a00..e91d637 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c @@ -1394,9 +1394,9 @@ int create_local_dirs(const char * user, const char *app_id, goto cleanup; } - // Copy script file with permissions 700 + // Copy script file with permissions 751 if (copy_file(container_file_source, script_name, script_file_dest,S_IRWXU) != 0) { - fprintf(ERRORFILE, "Could not create copy file %d %s\n", container_file_source, script_file_dest); + fprintf(ERRORFILE, "Could not create copy file %s %s (%d)\n", script_name, script_file_dest, container_file_source); fflush(ERRORFILE); exit_code = COULD_NOT_CREATE_SCRIPT_COPY; goto cleanup; @@ -1434,6 +1434,7 @@ int launch_docker_container_as_user(const char * user, const char *app_id, char *cred_file_dest = NULL; char *exit_code_file = NULL; char *docker_command_with_binary = NULL; + char *executable_binary = NULL; char *docker_wait_command = NULL; char *docker_logs_command = NULL; char *docker_inspect_command = NULL; @@ -1499,15 +1500,29 @@ int launch_docker_container_as_user(const char * user, const char *app_id, goto cleanup; } - snprintf(docker_command_with_binary, command_size, "%s %s", docker_binary, docker_command); + if (use_entry_point(command_file)) { + snprintf(docker_command_with_binary, command_size, "%s %s 1>>$LOG_DIR/stdout.txt 2>>$LOG_DIR/stderr.txt", docker_binary, docker_command); + executable_binary = get_container_launcher_file(work_dir); + FILE *LAUNCH_SCRIPT_FP = fopen(executable_binary, "a"); + if (LAUNCH_SCRIPT_FP == NULL) { + fprintf(LOGFILE, "write to %s failed.\n", executable_binary); + goto cleanup; + } + fprintf(LAUNCH_SCRIPT_FP, "%s\n", docker_command_with_binary); + fflush(LAUNCH_SCRIPT_FP); + fclose(LAUNCH_SCRIPT_FP); + } else { + snprintf(docker_command_with_binary, command_size, "%s %s", docker_binary, docker_command); + executable_binary = docker_command_with_binary; + } fprintf(LOGFILE, "Launching docker container...\n"); - fprintf(LOGFILE, "Docker run command: %s\n", docker_command_with_binary); - FILE* start_docker = popen(docker_command_with_binary, "r"); + fprintf(LOGFILE, "Docker run command: %s\n", executable_binary); + FILE* start_docker = popen(executable_binary, "r"); if (pclose (start_docker) != 0) { fprintf (ERRORFILE, - "Could not invoke docker %s.\n", docker_command_with_binary); + "Could not invoke docker %s.\n", executable_binary); fflush(ERRORFILE); exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; goto cleanup; @@ -1665,6 +1680,7 @@ cleanup: free(docker_logs_command); free(docker_inspect_command); free(docker_rm_command); + free(executable_binary); return exit_code; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c index 6b003a2..a267df3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c @@ -294,6 +294,21 @@ char *get_docker_binary(const struct configuration *conf) { return docker_binary; } +int use_entry_point(const char *command_file) { + int use_entry_point = 0; + int ret = 0; + struct configuration command_config = {0, NULL}; + ret = read_config(command_file, &command_config); + if (ret != 0) { + return NULL; + } + char *value = get_configuration_value("use-entry-point", DOCKER_COMMAND_FILE_SECTION, &command_config); + if (strcasecmp(value, "true") == 0) { + use_entry_point = 1; + } + return use_entry_point; +} + int docker_module_enabled(const struct configuration *conf) { struct section *section = get_configuration_section(CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf); if (section != NULL) { @@ -1409,8 +1424,12 @@ int get_docker_run_command(const char *command_file, const struct configuration if (launch_command != NULL) { for (i = 0; launch_command[i] != NULL; ++i) { memset(tmp_buffer, 0, tmp_buffer_size); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "", launch_command[i]); - ret = add_to_buffer(out, outlen, tmp_buffer); + if (use_entry_point(command_file)) { + ret = add_to_buffer(out, outlen, launch_command[i]); + } else { + quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "", launch_command[i]); + ret = add_to_buffer(out, outlen, tmp_buffer); + } if (ret != 0) { free_values(launch_command); free(tmp_buffer); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h index 8299acd..c87862b 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h @@ -69,6 +69,13 @@ enum docker_error_codes { char *get_docker_binary(const struct configuration *conf); /** + * Check if use-entry-point flag is set. + * @param command_file File containing the params for the Docker command + * @return 1 when use-entry-point flag is set. + */ +int use_entry_point(const char *command_file); + +/** * Get the Docker command line string. The function will inspect the params file to determine the command to be run. * @param command_file File containing the params for the Docker command * @param conf Configuration struct containing the container-executor.cfg details