Skip to content

Commit 254efc9

Browse files
committed
YARN-9379. Can't specify docker runtime through environment. Contributed by caozhiqiang
1 parent 7fa73fa commit 254efc9

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,6 +2030,16 @@ public static boolean isAclEnabled(Configuration conf) {
20302030
public static final String DEFAULT_NM_DOCKER_DEFAULT_CONTAINER_NETWORK =
20312031
"host";
20322032

2033+
/** The set of runtimes allowed when launching containers using the
2034+
* DockerContainerRuntime. */
2035+
public static final String NM_DOCKER_ALLOWED_CONTAINER_RUNTIMES =
2036+
DOCKER_CONTAINER_RUNTIME_PREFIX + "allowed-container-runtimes";
2037+
2038+
/** The set of runtimes allowed when launching containers using the
2039+
* DockerContainerRuntime. */
2040+
public static final String[] DEFAULT_NM_DOCKER_ALLOWED_CONTAINER_RUNTIMES =
2041+
{"runc"};
2042+
20332043
/** Allow host pid namespace for containers. Use with care. */
20342044
public static final String NM_DOCKER_ALLOW_HOST_PID_NAMESPACE =
20352045
DOCKER_CONTAINER_RUNTIME_PREFIX + "host-pid-namespace.allowed";

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/resources/yarn-default.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,6 +1803,13 @@
18031803
<value>host</value>
18041804
</property>
18051805

1806+
<property>
1807+
<description>The set of runtimes allowed when launching containers using the
1808+
DockerContainerRuntime.</description>
1809+
<name>yarn.nodemanager.runtime.linux.docker.allowed-container-runtimes</name>
1810+
<value>runc</value>
1811+
</property>
1812+
18061813
<property>
18071814
<description>This configuration setting determines whether the host's PID
18081815
namespace is allowed for docker containers on this cluster.

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
265265
@InterfaceAudience.Private
266266
public static final String ENV_DOCKER_CONTAINER_YARN_SYSFS =
267267
"YARN_CONTAINER_RUNTIME_YARN_SYSFS_ENABLE";
268+
@InterfaceAudience.Private
269+
public static final String ENV_DOCKER_CONTAINER_DOCKER_RUNTIME =
270+
"YARN_CONTAINER_RUNTIME_DOCKER_RUNTIME";
268271
public static final String YARN_SYSFS_PATH =
269272
"/hadoop/yarn/sysfs";
270273
private Configuration conf;
@@ -275,7 +278,9 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime {
275278
private String defaultImageName;
276279
private Boolean defaultImageUpdate;
277280
private Set<String> allowedNetworks = new HashSet<>();
281+
private Set<String> allowedRuntimes = new HashSet<>();
278282
private String defaultNetwork;
283+
private String defaultRuntime;
279284
private CGroupsHandler cGroupsHandler;
280285
private AccessControlList privilegedContainersAcl;
281286
private boolean enableUserReMapping;
@@ -349,6 +354,7 @@ public void initialize(Configuration conf, Context nmContext)
349354
this.conf = conf;
350355
dockerClient = new DockerClient();
351356
allowedNetworks.clear();
357+
allowedRuntimes.clear();
352358
defaultROMounts.clear();
353359
defaultRWMounts.clear();
354360
defaultTmpfsMounts.clear();
@@ -363,6 +369,10 @@ public void initialize(Configuration conf, Context nmContext)
363369
defaultNetwork = conf.getTrimmed(
364370
YarnConfiguration.NM_DOCKER_DEFAULT_CONTAINER_NETWORK,
365371
YarnConfiguration.DEFAULT_NM_DOCKER_DEFAULT_CONTAINER_NETWORK);
372+
allowedRuntimes.addAll(Arrays.asList(
373+
conf.getTrimmedStrings(
374+
YarnConfiguration.NM_DOCKER_ALLOWED_CONTAINER_RUNTIMES,
375+
YarnConfiguration.DEFAULT_NM_DOCKER_ALLOWED_CONTAINER_RUNTIMES)));
366376

367377
if(!allowedNetworks.contains(defaultNetwork)) {
368378
String message = "Default network: " + defaultNetwork
@@ -529,6 +539,19 @@ private void validateContainerNetworkType(String network)
529539
throw new ContainerExecutionException(msg);
530540
}
531541

542+
private void validateContainerRuntimeType(String runtime)
543+
throws ContainerExecutionException {
544+
if (runtime == null || runtime.isEmpty()
545+
|| allowedRuntimes.contains(runtime)) {
546+
return;
547+
}
548+
549+
String msg = "Disallowed runtime: '" + runtime
550+
+ "' specified. Allowed networks: are " + allowedRuntimes
551+
.toString();
552+
throw new ContainerExecutionException(msg);
553+
}
554+
532555
/**
533556
* Return whether the YARN container is allowed to run using the host's PID
534557
* namespace for the Docker container. For this to be allowed, the submitting
@@ -801,6 +824,7 @@ public void launchContainer(ContainerRuntimeContext ctx)
801824
String imageName = environment.get(ENV_DOCKER_CONTAINER_IMAGE);
802825
String network = environment.get(ENV_DOCKER_CONTAINER_NETWORK);
803826
String hostname = environment.get(ENV_DOCKER_CONTAINER_HOSTNAME);
827+
String runtime = environment.get(ENV_DOCKER_CONTAINER_DOCKER_RUNTIME);
804828
boolean useEntryPoint = checkUseEntryPoint(environment);
805829

806830
if (imageName == null || imageName.isEmpty()) {
@@ -816,6 +840,8 @@ public void launchContainer(ContainerRuntimeContext ctx)
816840

817841
validateImageName(imageName);
818842

843+
validateContainerRuntimeType(runtime);
844+
819845
if (defaultImageUpdate) {
820846
pullImageFromRemote(containerIdStr, imageName);
821847
}
@@ -886,6 +912,9 @@ public void launchContainer(ContainerRuntimeContext ctx)
886912
}
887913

888914
runCommand.setCapabilities(capabilities);
915+
if (runtime != null && !runtime.isEmpty()) {
916+
runCommand.addRuntime(runtime);
917+
}
889918

890919
runCommand.addAllReadWriteMountLocations(containerLogDirs);
891920
runCommand.addAllReadWriteMountLocations(applicationLocalDirs);

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,56 @@ public void testDockerContainerRelaunch()
24812481
dockerCommands.get(counter));
24822482
}
24832483

2484+
@Test
2485+
public void testLaunchContainersWithSpecificDockerRuntime()
2486+
throws ContainerExecutionException, PrivilegedOperationException,
2487+
IOException {
2488+
DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime(
2489+
mockExecutor, mockCGroupsHandler);
2490+
runtime.initialize(conf, nmContext);
2491+
2492+
env.put(DockerLinuxContainerRuntime
2493+
.ENV_DOCKER_CONTAINER_DOCKER_RUNTIME, "runc");
2494+
runtime.launchContainer(builder.build());
2495+
List<String> dockerCommands = readDockerCommands();
2496+
Assert.assertEquals(14, dockerCommands.size());
2497+
Assert.assertEquals(" runtime=runc", dockerCommands.get(11));
2498+
}
2499+
2500+
@Test
2501+
@SuppressWarnings("unchecked")
2502+
public void testContainerLaunchWithAllowedRuntimes()
2503+
throws ContainerExecutionException, IOException,
2504+
PrivilegedOperationException {
2505+
DockerLinuxContainerRuntime runtime =
2506+
new DockerLinuxContainerRuntime(mockExecutor, mockCGroupsHandler);
2507+
runtime.initialize(conf, nmContext);
2508+
2509+
String disallowedRuntime = "runc2";
2510+
2511+
try {
2512+
env.put(DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_DOCKER_RUNTIME,
2513+
disallowedRuntime);
2514+
runtime.launchContainer(builder.build());
2515+
Assert.fail("Runtime was expected to be disallowed: " +
2516+
disallowedRuntime);
2517+
} catch (ContainerExecutionException e) {
2518+
LOG.info("Caught expected exception: " + e);
2519+
}
2520+
2521+
String allowedRuntime = "runc";
2522+
env.put(DockerLinuxContainerRuntime.ENV_DOCKER_CONTAINER_DOCKER_RUNTIME,
2523+
allowedRuntime);
2524+
//this should cause no failures.
2525+
2526+
runtime.launchContainer(builder.build());
2527+
List<String> dockerCommands = readDockerCommands();
2528+
2529+
//This is the expected docker invocation for this case
2530+
Assert.assertEquals(14, dockerCommands.size());
2531+
Assert.assertEquals(" runtime=runc", dockerCommands.get(11));
2532+
}
2533+
24842534
private static void verifyStopCommand(List<String> dockerCommands,
24852535
String signal) {
24862536
Assert.assertEquals(4, dockerCommands.size());

0 commit comments

Comments
 (0)