Browse Source

MAPREDUCE-7456. Extend add-opens flag to container launch commands on JDK17 nodes. Contributed by Peter Szucs

Szilard Nemeth 1 year ago
parent
commit
2d871fab78

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

@@ -2232,6 +2232,14 @@ public class YarnConfiguration extends Configuration {
   public static final String NM_CONTAINER_LOCALIZER_JAVA_OPTS_DEFAULT =
       "-Xmx256m";
 
+  /*
+   * Flag to indicate whether JDK17's required add-exports flags should be added to
+   * container localizers regardless of the user specified JAVA_OPTS.
+   */
+  public static final String NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_KEY =
+      NM_PREFIX + "container-localizer.java.opts.add-exports-as-default";
+  public static final boolean NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_DEFAULT = true;
+
   /** The log level of container localizer process. */
   public static final String NM_CONTAINER_LOCALIZER_LOG_LEVEL=
       NM_PREFIX + "container-localizer.log.level";

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

@@ -1484,6 +1484,17 @@
     <value>-Xmx256m</value>
   </property>
 
+  <property>
+    <name>yarn.nodemanager.container-localizer.java.opts.add-exports-as-default</name>
+    <value>true</value>
+    <description>Since on JDK17 it is no longer possible to use the reflection API to
+      access public fields and methods, add-exports flags should be added to container
+      localizers regardless of the user specified JAVA_OPTS. Setting this to true will
+      add the flags to the container localizer on nodes with JDK17 or higher.
+      Defaults to true, but the setting has no effect on nodes using JDK16 and before.
+    </description>
+  </property>
+
   <property>
     <description>
       The log level for container localizer while it is an independent process.

+ 6 - 2
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

@@ -123,6 +123,11 @@ public class ContainerLaunch implements Callable<Integer> {
   private static final String PID_FILE_NAME_FMT = "%s.pid";
   static final String EXIT_CODE_FILE_SUFFIX = ".exitcode";
 
+  private static final String ADDITIONAL_JDK17_PLUS_OPTIONS =
+      "--add-opens=java.base/java.lang=ALL-UNNAMED " +
+      "--add-exports=java.base/sun.net.dns=ALL-UNNAMED " +
+      "--add-exports=java.base/sun.net.util=ALL-UNNAMED";
+
   protected final Dispatcher dispatcher;
   protected final ContainerExecutor exec;
   protected final Application app;
@@ -171,8 +176,7 @@ public class ContainerLaunch implements Callable<Integer> {
       File.pathSeparator);
 
     if (Shell.isJavaVersionAtLeast(17)) {
-      var = var.replace(ApplicationConstants.JVM_ADD_OPENS_VAR,
-              "--add-opens=java.base/java.lang=ALL-UNNAMED");
+      var = var.replace(ApplicationConstants.JVM_ADD_OPENS_VAR, ADDITIONAL_JDK17_PLUS_OPTIONS);
     } else {
       var = var.replace(ApplicationConstants.JVM_ADD_OPENS_VAR, "");
     }

+ 15 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/ContainerLocalizer.java

@@ -103,6 +103,14 @@ public class ContainerLocalizer {
       new FsPermission((short) 0755);
   public static final String CSI_VOLIUME_MOUNTS_ROOT = "csivolumes";
 
+  /*
+   * Testing discovered that these Java options are needed for Spark service
+   * running on JDK17 and Isilon clusters.
+   */
+  private static final String ADDITIONAL_JDK17_PLUS_OPTIONS =
+    "--add-exports=java.base/sun.net.dns=ALL-UNNAMED " +
+    "--add-exports=java.base/sun.net.util=ALL-UNNAMED";
+
   private final String user;
   private final String appId;
   private final List<Path> localDirs;
@@ -400,6 +408,13 @@ public class ContainerLocalizer {
   public static List<String> getJavaOpts(Configuration conf) {
     String opts = conf.get(YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_KEY,
         YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_DEFAULT);
+    boolean isExtraJDK17OptionsConfigured =
+        conf.getBoolean(YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_KEY,
+        YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_DEFAULT);
+
+    if (Shell.isJavaVersionAtLeast(17) && isExtraJDK17OptionsConfigured) {
+      opts = opts.trim().concat(" " + ADDITIONAL_JDK17_PLUS_OPTIONS);
+    }
     return Arrays.asList(opts.split(" "));
   }
 

+ 6 - 2
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/TestContainerLaunch.java

@@ -580,8 +580,12 @@ public class TestContainerLaunch extends BaseContainerManagerTest {
 
     String res = ContainerLaunch.expandEnvironment(input, logPath);
 
-    String expectedAddOpens = Shell.isJavaVersionAtLeast(17) ?
-        "--add-opens=java.base/java.lang=ALL-UNNAMED" : "";
+    String additionalJdk17PlusOptions =
+        "--add-opens=java.base/java.lang=ALL-UNNAMED " +
+        "--add-exports=java.base/sun.net.dns=ALL-UNNAMED " +
+        "--add-exports=java.base/sun.net.util=ALL-UNNAMED";
+    String expectedAddOpens = Shell.isJavaVersionAtLeast(17) ? additionalJdk17PlusOptions : "";
+
     if (Shell.WINDOWS) {
       Assert.assertEquals("%HADOOP_HOME%/share/hadoop/common/*;"
           + "%HADOOP_HOME%/share/hadoop/common/lib/*;"

+ 35 - 0
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/localizer/TestContainerLocalizer.java

@@ -702,4 +702,39 @@ static DataInputBuffer createFakeCredentials(Random r, int nTok)
         lfs.getFileStatus(destDirPath.getParent().getParent()).getPermission());
   }
 
+  @Test
+  public void testDefaultJavaOptionsWhenExtraJDK17OptionsAreConfigured() throws Exception {
+    ContainerLocalizerWrapper wrapper = new ContainerLocalizerWrapper();
+    ContainerLocalizer localizer = wrapper.setupContainerLocalizerForTest();
+
+    Configuration conf = new Configuration();
+    conf.setBoolean(YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_KEY,
+        true);
+
+    List<String> javaOpts = localizer.getJavaOpts(conf);
+
+    if (Shell.isJavaVersionAtLeast(17)) {
+      Assert.assertTrue(javaOpts.contains("--add-exports=java.base/sun.net.dns=ALL-UNNAMED"));
+      Assert.assertTrue(javaOpts.contains("--add-exports=java.base/sun.net.util=ALL-UNNAMED"));
+    }
+    Assert.assertTrue(javaOpts.contains("-Xmx256m"));
+  }
+
+  @Test
+  public void testDefaultJavaOptionsWhenExtraJDK17OptionsAreNotConfigured() throws Exception {
+    ContainerLocalizerWrapper wrapper = new ContainerLocalizerWrapper();
+    ContainerLocalizer localizer = wrapper.setupContainerLocalizerForTest();
+
+    Configuration conf = new Configuration();
+    conf.setBoolean(YarnConfiguration.NM_CONTAINER_LOCALIZER_JAVA_OPTS_ADD_EXPORTS_KEY,
+        false);
+
+    List<String> javaOpts = localizer.getJavaOpts(conf);
+
+    if (Shell.isJavaVersionAtLeast(17)) {
+      Assert.assertFalse(javaOpts.contains("--add-exports=java.base/sun.net.dns=ALL-UNNAMED"));
+      Assert.assertFalse(javaOpts.contains("--add-exports=java.base/sun.net.util=ALL-UNNAMED"));
+    }
+    Assert.assertTrue(javaOpts.contains("-Xmx256m"));
+  }
 }