diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java index 0581878..a6f5fd5 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/ContainerExecutor.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; +import java.io.PrintWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; @@ -717,6 +718,38 @@ public String getProcessId(ContainerId containerID) { } /** + * Set OS level OOM killer priority for a given container. + * @param pid pid of the given container + * @param oomKillerPriority OOM killer priority + */ + public void setOomKillerPriority(String pid, int oomKillerPriority) { + LOG.info("Setting OOM Killer priority for " + pid); + + File oomAdjFile = new File(getOomAdjFile(pid)); + try { + if (oomAdjFile.exists()) { + try (PrintWriter pw = new PrintWriter(oomAdjFile.getAbsolutePath(), + "UTF-8")) { + pw.write(oomKillerPriority); + if (pw.checkError()) { + LOG.warn("Couldn't set OOM killer priority for " + pid); + } else { + LOG.info("Set OOM Killer priority for " + pid); + } + } + } else { + LOG.info("File " + oomAdjFile + " doesn't exist. Skipping..."); + } + } catch (IOException ioe) { + LOG.warn("Couldn't set OOM killer priority for " + pid, ioe); + } + } + + private String getOomAdjFile(String pid) { + return "/proc/" + pid + "/oom_adj"; + } + + /** * This class will signal a target container after a specified delay. * @see #signalContainer */ diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java index b777311..d244fcd 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/ContainersMonitorImpl.java @@ -28,6 +28,7 @@ import org.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix; import org.apache.hadoop.yarn.api.records.ContainerExitStatus; import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.api.records.ExecutionType; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.conf.YarnConfiguration; @@ -587,6 +588,7 @@ private void initializeProcessTrees( if (LOG.isDebugEnabled()) { LOG.debug("Tracking ProcessTree " + pId + " for the first time"); } + setContainerOomKillerPriority(containerId, pId); ResourceCalculatorProcessTree pt = ResourceCalculatorProcessTree. getResourceCalculatorProcessTree( @@ -624,6 +626,21 @@ private void initializeProcessTrees( } /** + * Set OOM Killer Priority for Opportunistic containers. + */ + private void setContainerOomKillerPriority(ContainerId containerId, + String containerPid) { + Container container = context.getContainers().get(containerId); + if (container != null) { + boolean isOpportunistic = container.getContainerTokenIdentifier(). + getExecutionType().equals(ExecutionType.OPPORTUNISTIC); + if (isOpportunistic) { + containerExecutor.setOomKillerPriority(containerPid, 15); + } + } + } + + /** * Record usage metrics. * @param containerId container id * @param pId process id diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java index e21eea0..76249d0 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/monitor/TestContainersMonitorResourceChange.java @@ -28,12 +28,14 @@ import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.api.records.ExecutionType; import org.apache.hadoop.yarn.api.records.Resource; import org.apache.hadoop.yarn.api.records.ResourceUtilization; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.AsyncDispatcher; import org.apache.hadoop.yarn.event.EventHandler; import org.apache.hadoop.yarn.exceptions.ConfigurationException; +import org.apache.hadoop.yarn.security.ContainerTokenIdentifier; import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor; import org.apache.hadoop.yarn.server.nodemanager.Context; import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container; @@ -137,6 +139,9 @@ public void setup() { context = Mockito.mock(Context.class); containerMap = new ConcurrentSkipListMap<>(); Container container = Mockito.mock(ContainerImpl.class); + ContainerTokenIdentifier cti = Mockito.mock(ContainerTokenIdentifier.class); + Mockito.doReturn(ExecutionType.GUARANTEED).when(cti).getExecutionType(); + Mockito.doReturn(cti).when(container).getContainerTokenIdentifier(); containerMap.put(getContainerId(1), container); Mockito.doReturn(containerMap).when(context).getContainers(); conf = new Configuration();