容器运行超出内存限制


85

在Hadoop v1中,我为每个7个映射器和reducer插槽分配了1GB的大小,我的映射器和reducer运行良好。我的机器有8G内存,8个处理器。现在使用YARN,当在同一台计算机上运行同一应用程序时,出现容器错误。默认情况下,我有以下设置:

  <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
  </property>
  <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>8192</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>8192</value>
  </property>

它给了我错误:

Container [pid=28920,containerID=container_1389136889967_0001_01_000121] is running beyond virtual memory limits. Current usage: 1.2 GB of 1 GB physical memory used; 2.2 GB of 2.1 GB virtual memory used. Killing container.

然后,我尝试在mapred-site.xml中设置内存限制:

  <property>
    <name>mapreduce.map.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>4096</value>
  </property>

但仍然出现错误:

Container [pid=26783,containerID=container_1389136889967_0009_01_000002] is running beyond physical memory limits. Current usage: 4.2 GB of 4 GB physical memory used; 5.2 GB of 8.4 GB virtual memory used. Killing container.

我很困惑为什么map任务需要这么多的内存。据我了解,1GB的内存足以完成我的地图/缩小任务。为什么当我为容器分配更多内存时,任务使用了更多内存?是因为每个任务都会得到更多分割吗?我觉得稍微减少容器的大小并创建更多的容器会更有效,以便更多的任务并行运行。问题是如何确定每个容器分配的拆分数量是否超过其处理能力?



嗨!您的配置'yarn.nodemanager.vmem-pmem-ratio = 2'吗?
雪碧

Answers:


102

您还应该正确配置MapReduce的最大内存分配。从此HortonWorks教程中

[...]

集群中的每台计算机都有48 GB的RAM。此RAM中的某些应保留>以供操作系统使用。在每个节点上,我们将为> YARN分配40 GB RAM以使用,并为操作系统保留8 GB

对于我们的示例集群,我们有一个容器的最小RAM(yarn.scheduler.minimum-allocation-mb)= 2 GB。因此,我们将为Map任务容器分配4 GB,为Reduce任务容器分配8 GB。

在mapred-site.xml中:

mapreduce.map.memory.mb:4096

mapreduce.reduce.memory.mb:8192

每个容器将为Map和Reduce任务运行JVM。JVM堆大小应设置为小于上面定义的“映射和减少”内存,以便它们在YARN分配的容器内存的范围内。

在mapred-site.xml中:

mapreduce.map.java.opts-Xmx3072m

mapreduce.reduce.java.opts-Xmx6144m

以上设置配置了Map和Reduce任务将使用的物理RAM的上限

把它们加起来:

  1. 在YARN中,您应该使用mapreduce配置,而不是mapred那些。编辑:既然您已编辑问题,此评论将不再适用。
  2. 您实际上要配置的是您要请求的数量,而不是要分配的最大数量。
  3. 最大限制使用java.opts上面列出的设置进行配置。

最后,您可能需要检查描述类似问题(和解决方案)的另一个SO问题


是。通过设置mapreduce.map.java.optsmapreduce.reduce.java.opts解决我的问题。您知道分配给任务的实际内存是否仅由定义mapreduce.map/reduce.memory.mb吗?如何yarn.scheduler.minimum-allocation-mb影响实际的内存分配?
Lishu 2014年

@lishu,如果有帮助,请接受答案。关于您的最后一个问题,纱线设置适用于群集中的任何容器分配。这包括映射和归约任务,但是其他类型应用程序中的其他任务也是如此。mapreduce设置仅适用于mapreduce作业。
Cabad 2014年

@cabad,我开发了Lishu正在使用的库。我想知道您是否会更改答案,因为知道MR任务正在产生一个实际上分配了大部分内存(hadoop流)的进程。当然,Xmx设置不会影响外部进程,因为它不是Java程序。谢谢你的帮助。
piccolbo 2014年

2
Hortonworks现在提供了一个方便的工具,称为hdp-configuration-utils,用于获取推荐值。从github.com/hortonworks/hdp-configuration-utils中
2015年

1
如果运用恰当的内存配置没有解决问题(在我的情况一样,其实它的工作就在Hadoop运行在Ubuntu上而不是在CentOS)尝试禁用的vmem检查:blog.cloudera.com/blog/2014/04/...
Bakhshi

47

在“纱线”级别检查虚拟和物理内存使用率。问题不仅在于VM没有足够的物理内存。但这是因为虚拟内存使用量超出了给定物理内存的预期。

注意:由于Centos / RHEL 6大量分配了虚拟内存,因此发生了这种情况。

可以通过以下方法解决:

  1. 通过将yarn.nodemanager.vmem-check-enabled设置false来禁用虚拟内存使用检查 ;

  2. 通过将yarn.nodemanager.vmem-pmem-ratio设置为更高的值来提高VM:PM比率。

参考文献

https://issues.apache.org/jira/browse/HADOOP-11364

http://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-standing-gotchas/

在yarn-site.xml中添加以下属性

 <property>
   <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
    <description>Whether virtual memory limits will be enforced for containers</description>
  </property>
 <property>
   <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>4</value>
    <description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
  </property>

15

在EMR中使用HIVE,我遇到了一个非常相似的问题。现有的解决方案都不适合我-即,没有mapreduce配置适合我。而且都没有设置yarn.nodemanager.vmem-check-enabled为false。

但是,最终的工作是设置tez.am.resource.memory.mb,例如:

hive -hiveconf tez.am.resource.memory.mb=4096

考虑调整的另一个设置是 yarn.app.mapreduce.am.resource.mb


嗯@hiroprotagonist,您是否知道是否必须在YARN启动之前“调整”纱线参数,或者仅在应用时使用(可以将其从一项工作更改为下一项工作)?
精神法官

1
我已经能够在申请时设定。特别是在蜂巢交互式控制台中。
hiroprotagonist

8

由于声誉低下,我无法评论接受的答案。但是,我想补充一下,这种行为是设计使然。NodeManager正在杀死您的容器。听起来您正在尝试使用hadoop流,该流作为map-reduce任务的子进程运行。NodeManager监视任务的整个过程树,并且如果它消耗的内存超过分别在mapreduce.map.memory.mb或mapreduce.reduce.memory.mb中设置的最大内存,则我们希望Nodemanager终止该任务,否则您的任务是窃取不需要的其他容器的内存。


1

在EMR中使用spark时,我遇到了同样的问题,设置maximizeResourceAllocation=true成功了。希望它能帮助某人。创建集群时必须进行设置。从EMR文档:

aws emr create-cluster --release-label emr-5.4.0 --applications Name=Spark \
--instance-type m3.xlarge --instance-count 2 --service-role EMR_DefaultRole --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json

其中myConfig.json应该说:

[
  {
    "Classification": "spark",
    "Properties": {
      "maximizeResourceAllocation": "true"
    }
  }
]

1

我们最近也遇到了这个问题。如果问题与映射器内存有关,我想建议您检查几件事。

  • 检查是否启用了合并器?如果是,则意味着必须对所有记录(映射器的输出)运行reduce逻辑。这发生在内存中。根据您的应用程序,您需要检查启用组合器是否有帮助。权衡是在网络传输字节与所用时间/内存/ CPU之间进行,以减少记录数量“ X”的逻辑。
    • 如果您认为合并器没有太大价值,请禁用它。
    • 如果您需要组合器,并且“ X”是一个巨大的数字(例如数百万条记录),则可以考虑更改拆分逻辑(对于默认输入格式,请使用较小的块大小,通常为1块大小= 1拆分)以将较少的记录数映射到一个单个映射器。
  • 在单个映射器中处理的记录数。请记住,所有这些记录都需要在内存中排序(对mapper的输出进行排序)。 如果需要,可以考虑将mapreduce.task.io.sort.mb(默认值为200MB)设置为更高的值。mapred-configs.xml
  • 如果上述任何方法都无济于事,请尝试将映射器逻辑作为独立的应用程序运行,并使用探查器(如JProfiler)对应用程序进行探查,并查看内存的使用位置。这可以为您提供很好的见解。

1

在具有Ubunto OS的Windows Linux子系统上运行yarn,错误“超出虚拟内存限制,终止了容器”我通过在文件yarn-site.xml中禁用虚拟内存检查解决了该问题

<property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> 

在WSL上,错误消息具有荒谬的数字(至少对我来说是荒谬的):“ ...正在运行,超出了虚拟内存限制。当前使用情况:已使用338.8 MB的2 GB物理内存;已使用481.1 GB的4.2 GB的虚拟内存。Killing container 。”
Samik R

@SamikR是的,我也有类似的情况,我想这不是hadoop问题,而是WSL问题。也许我需要将演示转移到真正的Linux OS计算机上
Bingoabs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.