Descripción corta
Cuando un contenedor se queda sin memoria, YARN lo detiene automáticamente y es posible que recibas el siguiente mensaje de error:
"Container killed on request" stage failure: Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 2 in stage 3.0 failed 4 times, most recent failure: Lost task 2.3 in stage 3.0 (TID 23, ip-###-###-##-###.compute.internal, executor 4): ExecutorLostFailure (executor 4 exited caused by one of the running tasks) Reason: Container marked as failed: container_1516900607498_6585_01_000008 on host: ip-###-###-##-###.compute.internal. Exit status: 137. Diagnostics: Container killed on request. Exit code is 137"
Resolución
Aumento de la memoria del controlador o contenedor
Para aumentar la memoria del contenedor del clúster en ejecución o de un trabajo único, primero conecta el nodo maestro del clúster. A continuación, modifica los parámetros spark.executor.memory o spark.driver.memory en el archivo de configuración de Spark spark-defaults.conf.
Clúster en ejecución
Para abrir spark-defaults.conf, ejecuta el siguiente comando:
sudo vim /etc/spark/conf/spark-defaults.conf
Para aumentar la memoria del contenedor, agrega o modifica el parámetro spark.executor.memory o spark.driver.memory en spark-defaults.conf:
spark.executor.memory 10g
spark.driver.memory 10g
Nota: Sustituye 10g por un valor adecuado para los recursos disponibles y los requisitos de carga de trabajo del clúster.
Trabajo único
Para aumentar la memoria, utiliza la opción --executor-memory o --driver-memory cuando ejecutes el siguiente comando spark-submit:
spark-submit
--executor-memory 10g
--driver-memory 10g
...
Nota: Sustituye 10g por un valor adecuado para los recursos disponibles y los requisitos de carga de trabajo del clúster.
También puedes establecer maximizeResourceAllocation en true en tu clasificación de configuración de Spark.
Adición de más particiones de Spark
Si no puedes aumentar la memoria del contenedor, aumenta la cantidad de particiones de Spark para reducir la cantidad de datos que se procesan y la memoria que se usa.
Para agregar más particiones de Spark, primero conecta el nodo maestro de tu clúster y, a continuación, ejecuta los siguientes comandos en el shell de Spark:
val numPartitions = 500
val newDF = df.repartition(numPartitions)
Nota: Sustituye 500 por la cantidad de particiones que se adapte al tamaño de los datos.
Aumento del número de particiones aleatorias
Si el problema se produce durante una transformación amplia, como una unión o un groupBy, conéctate al nodo maestro del clúster y agrega más particiones aleatorias. El valor predeterminado es 200.
Clúster en ejecución
Para abrir spark-defaults.conf, ejecuta el siguiente comando:
sudo vim /etc/spark/conf/spark-defaults.conf
Para agregar particiones aleatorias al archivo de configuración, ejecuta el siguiente comando:
spark.sql.shuffle.partitions 500
Nota: Sustituye 500 por la cantidad de particiones que se adapte al tamaño de los datos.
Trabajo único
Para agregar más particiones aleatorias, usa la opción --conf spark.sql.shuffle.partitions cuando ejecutes spark-submit:
spark-submit
--conf
spark.sql.shuffle.partitions=500
...
Nota: Sustituye 500 por la cantidad de particiones que se adapte al tamaño de los datos.
Reducción del número de núcleos ejecutores
Al reducir el número de núcleos ejecutores, también se reduce el número máximo de tareas que el ejecutor procesa simultáneamente. De este modo, se reduce la cantidad de memoria que utiliza el contenedor. Para reducir la cantidad de núcleos ejecutores, primero conéctate al nodo maestro del clúster y, a continuación, modifica el parámetro de núcleos ejecutores.
Clúster en ejecución
Abre el archivo spark-defaults.conf en el nodo maestro:
sudo vim /etc/spark/conf/spark-defaults.conf
Para reducir el número de núcleos ejecutores, modifica el parámetro spark.executor.cores:
spark.executor.cores 1
Nota: Sustituye 1 por la cantidad mínima de núcleos ejecutores que necesites.
Trabajo único
Para reducir el número de núcleos ejecutores, usa la opción --executor-cores cuando ejecutes spark-submit:
spark-submit
--executor-cores 1
...
Aumento del tamaño de la instancia
Cuando el sistema operativo (SO) se queda sin memoria, el sistema operativo oom_reaper también puede detener los contenedores YARN. Si oom_reaper provocó el error, utiliza una instancia más grande de Amazon Elastic Compute Cloud (Amazon EC2) con más RAM. Para asegurarte de que los contenedores YARN no utilizan toda la RAM, reduce yarn.nodemanager.resource.memory-mb.
Para determine si oom_reaper provocó el error, revisa los registros de instancias de Amazon EMR Instance para el resultado del comando dmesg. Primero, usa los registros o la interfaz de usuario del administrador de recursos de YARN para encontrar el nodo maestro o de tarea donde se ejecutaba el contenedor YARN detenido. A continuación, comprueba los registros de estado de la instancia de Amazon EMR en el nodo antes y después de que se detuviera el contenedor.
En el siguiente ejemplo, el kernel detiene el proceso que tiene el ID 36787 y corresponde al contenedor YARN container_165487060318_0001_01_000244:
# hows the kernel lookingdmesg | tail -n 25
[ 3910.032284] Out of memory: Kill process 36787 (java) score 96 or sacrifice child
[ 3910.043627] Killed process 36787 (java) total-vm:15864568kB, anon-rss:13876204kB, file-rss:0kB, shmem-rss:0kB
[ 3910.748373] oom_reaper: reaped process 36787 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
Comprobación del uso del disco y la degradación de los nodos
Si las opciones de solución de problemas anteriores no resuelven el problema, usa el indicador df-h en los registros de estado de la instancia para comprobar el uso del disco y la degradación de los nodos. Comprueba también el estado del nodo en el panel de AWS Health.
Información relacionada
¿Cómo puedo resolver el error "Container killed by YARN for exceeding memory limits" en Spark en Amazon EMR?
¿Cómo puedo solucionar los errores de fase de los trabajos de Spark en Amazon EMR?