El contenedor está funcionando más allá de los límites de memoria

En Hadoop v1, he asignado cada 7 mapper y slot reductor con tamaño de 1GB, mis mapeadores y reductores funcionan bien. Mi máquina tiene memoria 8G, 8 procesadores. Ahora con YARN, cuando ejecuto la misma aplicación en la misma máquina, recibo un error de contenedor. Por defecto, tengo esta configuración:

 yarn.scheduler.minimum-allocation-mb 1024   yarn.scheduler.maximum-allocation-mb 8192   yarn.nodemanager.resource.memory-mb 8192  

Me dio error:

 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. 

Luego intenté establecer el límite de memoria en mapred-site.xml:

   mapreduce.map.memory.mb 4096   mapreduce.reduce.memory.mb 4096  

Pero aún recibo un error:

 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. 

Estoy confundido por qué la tarea del mapa necesita tanta memoria. Según entiendo, 1GB de memoria es suficiente para mi tarea de mapa / reducir. ¿Por qué cuando asigno más memoria al contenedor, la tarea usa más? ¿Es porque cada tarea obtiene más divisiones? Creo que es más eficiente disminuir un poco el tamaño del contenedor y crear más contenedores, de modo que se ejecutan más tareas en paralelo. El problema es: ¿cómo puedo asegurarme de que a cada contenedor no se le asignarán más divisiones de las que puede manejar?

También debe configurar correctamente las asignaciones de memoria máxima para MapReduce. De este tutorial de HortonWorks :

[…]

Cada máquina de nuestro clúster tiene 48 GB de RAM. Parte de esta RAM debe> reservarse para el uso del sistema operativo. En cada nodo asignaremos 40 GB de RAM para que utilice YARN y mantengamos 8 GB para el sistema operativo

Para nuestro clúster de ejemplo, tenemos la RAM mínima para un contenedor (yarn.scheduler.minimum-allocation-mb) = 2 GB. Así asignaremos 4 GB para Contenedores de tareas de mapas y 8 GB para Contenedores de tareas de reducción.

En mapred-site.xml:

mapreduce.map.memory.mb : 4096

mapreduce.reduce.memory.mb : 8192

Cada contenedor ejecutará JVM para las tareas de mapa y reducción. El tamaño del almacenamiento dynamic de la JVM debe establecerse en un valor inferior al de la memoria de Mapa y Reducción definida anteriormente, para que estén dentro de los límites de la memoria del Contenedor asignada por YARN.

En mapred-site.xml:

mapreduce.map.java.opts : -Xmx3072m

mapreduce.reduce.java.opts : -Xmx6144m

Las configuraciones anteriores configuran el límite superior de la RAM física que utilizarán las tareas de Asignar y Reducir .

En resumen:

  1. En YARN, debes usar las configuraciones mapreduce , no las mapred . EDITAR: Este comentario ya no se aplica ahora que ha editado su pregunta.
  2. Lo que está configurando es realmente cuánto desea solicitar, no cuál es el máximo para asignar.
  3. Los límites máximos se configuran con la configuración de java.opts enumerada anteriormente.

Finalmente, es posible que desee verificar esta otra pregunta de SO que describe un problema similar (y una solución).

Hay un cheque en el nivel de hilo para la relación de uso de memoria física y vertical. El problema no es solo que la VM no tiene suficiente memoria física. Pero es porque el uso de la memoria virtual es más de lo esperado para la memoria física dada.

Nota : Esto está sucediendo en Centos / RHEL 6 debido a su asignación agresiva de memoria virtual.

Se puede resolver ya sea por:

  1. Deshabilite la verificación de uso de la memoria virtual configurando yarn.nodemanager.vmem-check-enabled en false ;

  2. Aumente la relación VM: PM estableciendo yarn.nodemanager.vmem-pmem-ratio en algún valor más alto.

Referencias

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

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

Agregue la siguiente propiedad en yarn-site.xml

   yarn.nodemanager.vmem-check-enabled false Whether virtual memory limits will be enforced for containers   yarn.nodemanager.vmem-pmem-ratio 4 Ratio between virtual memory to physical memory when setting memory limits for containers  

Tuve un problema muy similar al utilizar HIVE en EMR. Ninguna de las soluciones existentes funcionó para mí, es decir, ninguna de las configuraciones de mapreduce me funcionó; y tampoco lo hizo establecer yarn.nodemanager.vmem-check-enabled en falso.

Sin embargo, lo que terminó funcionando fue establecer tez.am.resource.memory.mb , por ejemplo:

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

Otro ajuste para considerar ajustar es yarn.app.mapreduce.am.resource.mb

No puedo comentar sobre la respuesta aceptada, debido a la baja reputación. Sin embargo, me gustaría agregar, este comportamiento es por diseño. El NodeManager está matando a su contenedor. Parece que está intentando usar la transmisión de hadoop que se ejecuta como un proceso secundario de la tarea de reducción de mapa. El NodeManager supervisa todo el árbol de procesos de la tarea y si consume más memoria que el máximo establecido en mapreduce.map.memory.mb o mapreduce.reduce.memory.mb respectivamente, esperaríamos que el administrador de nodos elimine la tarea, de lo contrario su tarea es robar la memoria perteneciente a otros contenedores, que no desea.

Mientras trabajaba con chispa en EMR estaba teniendo el mismo problema y establecer el valor de maximizeResourceAllocation=true hizo el truco; Espero que ayude a alguien. Debe configurarlo cuando crea el clúster. De los documentos 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 

Donde myConfig.json debería decir:

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

También enfrentamos este problema recientemente. Si el problema está relacionado con la memoria del mapeador, hay algunas cosas que me gustaría sugerir que deben verificarse.

  • Compruebe si el combinador está habilitado o no ? Si es así, significa que la lógica de reducción debe ejecutarse en todos los registros (salida del asignador). Esto sucede en la memoria. Según su aplicación, debe verificar si el combinador habilitante ayuda o no. El intercambio es entre los bytes de transferencia de red y el tiempo empleado / memoria / CPU para la lógica de reducción en el número de registros ‘X’.
    • Si siente que el combinador no tiene mucho valor, simplemente deshabilítelo.
    • Si necesita un combinador y ‘X’ es un número enorme (digamos millones de registros) entonces considerando cambiar su lógica de división (para los formatos de entrada predeterminados use menos tamaño de bloque, normalmente 1 tamaño de bloque = 1 división) para asignar menos cantidad de registros a un solo mapeador.
  • Número de registros que se procesan en un solo mapeador. Recuerde que todos estos registros deben estar ordenados en la memoria (la salida del mapeador está ordenada). Considere establecer mapreduce.task.io.sort.mb (por defecto es 200MB) a un valor mayor si es necesario. mapred-configs.xml
  • Si alguno de los anteriores no fue de ayuda, intente ejecutar la lógica del correlacionador como una aplicación independiente y perfilar la aplicación usando un Analizador (como JProfiler) y ver dónde se usa la memoria. Esto puede darte muy buenas ideas.