Breve descrição
Quando um contêiner (executor do Spark) fica sem memória, o YARN elimina automaticamente o contêiner e é possível receber o seguinte erro:
"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"
Resolução
Aumente a memória do driver ou do executor
Para aumentar a memória do contêiner, primeiro conecte o nó primário do cluster e, em seguida, modifique os parâmetros spark.executor.memory ou spark.driver.memory no seu arquivo de configuração do Spark (spark-defaults.conf).
Cluster em execução
Para abrir spark-defaults.conf, execute o seguinte comando:
sudo vim /etc/spark/conf/spark-defaults.conf
Para aumentar a memória do contêiner, adicione ou modifique os seguintes parâmetros em spark-defaults.conf:
spark.executor.memory 10g
spark.driver.memory 10g
Observação: substitua 10g por valores de memória de acordo com os recursos disponíveis e os requisitos de workload do seu cluster.
Trabalho único
Ao executar spark-submit, use a opção --executor-memory ou --driver-memory para aumentar a memória.
Exemplo:
spark-submit
--executor-memory 10g
--driver-memory 10g
...
Observação: substitua 10g por valores de memória apropriados de acordo com os recursos disponíveis e os requisitos de workload do seu cluster.
Adicione mais partições do Spark
Se não for possível aumentar a memória do contêiner, por exemplo, se estiver usando maximizeResourceAllocation no nó, aumente o número de partições do Spark. Isso reduz a quantidade de dados processados por uma única tarefa do Spark e a memória geral usada por um único executor.
Para adicionar mais partições do Spark, primeiro conecte o nó primário do seu cluster e, em seguida, execute os seguintes comandos no shell do Spark:
val numPartitions = 500
val newDF = df.repartition(numPartitions)
Observação: substitua 500 pelo número de partições adequado ao seu tamanho de dados.
Aumente o número de partições embaralhadas
Se o erro ocorrer durante uma transformação ampla, por exemplo, join ou groupBy, primeiro conecte-se ao nó primário do seu cluster e, em seguida, adicione mais partições embaralhadas. O valor padrão é 200.
Cluster em execução
Para abrir spark-defaults.conf, execute o seguinte comando:
sudo vim /etc/spark/conf/spark-defaults.conf
Atualize as partições embaralhadas em seu arquivo de configuração:
spark.sql.shuffle.partitions 500
Observação: substitua 500 pelo número de partições adequado ao seu tamanho de dados.
Trabalho único
Ao executar spark-submit, use a opção --conf spark.sql.shuffle.partitions para adicionar mais partições embaralhadas.
Exemplo:
spark-submit
--conf
spark.sql.shuffle.partitions=500
...
Reduza o número de núcleos do executor
Ao reduzir o número de núcleos do executor, você também reduz o número máximo de tarefas que o executor processa simultaneamente. Isso reduz a quantidade de memória usada pelo contêiner.
Cluster em execução
Primeiro, conecte-se ao nó primário do seu cluster e, em seguida, abra o arquivo spark-defaults.conf no nó primário:
sudo vim /etc/spark/conf/spark-defaults.conf
Para definir o número de núcleos do executor, modifique o parâmetro spark.executor.cores:
spark.executor.cores 1
Observação: substitua 1 pelo número de núcleos do executor necessários para seu caso de uso.
Trabalho único
Use a opção --executor-cores para reduzir o número de núcleos do executor ao executar spark-submit.
Exemplo:
spark-submit
--executor-cores 1
...
Aumente o tamanho da instância
Quando o sistema operacional fica sem memória, o oom_reaper do sistema operacional também pode eliminar os contêineres YARN. Se isso causar o erro, use uma instância maior com mais RAM. Para garantir que os contêineres YARN não usem toda a memória RAM do Amazon Elastic Compute Cloud (Amazon EC2), baixe yarn.nodemanager.resource.memory-mb.
Consulte seus logs de instância do Amazon EMR na saída do comando dmesg para determinar se oom_reaper está causando o erro. Primeiro, use a interface do usuário ou os logs do YARM Resource Manager para encontrar o nó principal ou de tarefa em que o contêiner YARN morto foi executado. Em seguida, verifique os logs de estado da instância do Amazon EMR nesse nó antes e depois da eliminação do contêiner para saber se oom_reaper interrompeu o processo.
No exemplo a seguir, o kernel (eliminador de OOM do Linux) encerra o processo com o ID 36787 que corresponde a 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
Verifique a utilização do disco e a degradação do nó
Se as opções de solução de problemas anteriores não resolverem o erro, verifique a utilização do disco e a degradação do nó. Use o sinalizador df-h dentro dos logs de estado da instância para verificar a utilização do disco do cluster e do nó. Verifique também a condição do nó em Amazon Health dashboard.
Informações relacionadas
Como resolvo o erro “Contêiner eliminado pelo YARN por exceder os limites de memória” do Spark no Amazon EMR?
Como posso solucionar falhas de estágio em trabalhos do Spark no Amazon EMR?