Breve descrição
Quando um contêiner fica sem memória, o YARN interrompe automaticamente o contêiner e é possível receber a seguinte mensagem de 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 contêiner
Para aumentar a memória do contêiner do seu cluster em execução ou do trabalho único, primeiro conecte o nó primário do seu cluster. Em seguida, modifique os parâmetros spark.executor.memory ou spark.driver.memory no seu arquivo de configuração spark-defaults.conf do Spark.
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 o parâmetro spark.executor.memory ou spark.driver.memory em spark-defaults.conf:
spark.executor.memory 10g
spark.driver.memory 10g
Observação: substitua 10g por um valor apropriado para os recursos disponíveis e os requisitos de workload do seu cluster.
Trabalho único
Para aumentar a memória, use a opção --executor-memory ou --driver-memory ao executar o seguinte comando spark-submit:
spark-submit
--executor-memory 10g
--driver-memory 10g
...
Observação: substitua 10g por um valor apropriado para os recursos disponíveis e os requisitos de workload do seu cluster.
Também é possível definir maximizeResourceAllocation como true em sua classificação de configuração do Spark.
Adicione mais partições do Spark
Se não for possível aumentar a memória do contêiner, aumente o número de partições do Spark para reduzir a quantidade de dados processados e a memória usada.
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 problema ocorrer durante uma transformação ampla, como uma join ou groupBy, conecte-se ao nó primário do seu cluster e 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
Para adicionar partições embaralhadas ao seu arquivo de configuração, execute o seguinte comando:
spark.sql.shuffle.partitions 500
Observação: substitua 500 pelo número de partições adequado ao seu tamanho de dados.
Trabalho único
Use a opção --conf spark.sql.shuffle.partitions para adicionar mais partições embaralhadas ao executar spark-submit:
spark-submit
--conf
spark.sql.shuffle.partitions=500
...
Observação: substitua 500 pelo número de partições adequado ao seu tamanho de dados.
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. Para reduzir o número de núcleos do executor, primeiro conecte-se ao nó primário do seu cluster e, em seguida, modifique o parâmetro dos núcleos do executor.
Cluster em execução
Abra o arquivo spark-defaults.conf no nó primário:
sudo vim /etc/spark/conf/spark-defaults.conf
Para reduzir 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 mínimo de núcleos do executor necessários.
Trabalho único
Use a opção --executor-cores para reduzir o número de núcleos do executor ao executar spark-submit:
spark-submit
--executor-cores 1
...
Aumente o tamanho da instância
Quando o sistema operacional (SO) fica sem memória, o sistema operacional oom_reaper também pode interromper os contêineres YARN. Se oom_reaper causou o erro, use uma instância maior do Amazon Elastic Compute Cloud (Amazon EC2) com mais RAM. Para garantir que os contêineres YARN não usem toda a RAM, diminua yarn.nodemanager.resource.memory-mb.
Consulte seus logs de instância do Amazon EMR na saída do comando dmesg para saber se oom_reaper causou 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 interrompido foi executado. Em seguida, verifique os logs de estado da instância do Amazon EMR no nó antes e depois da interrupção do contêiner.
No exemplo a seguir, o kernel interrompe o processo que tem o ID 36787 e corresponde ao 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 problema, use o sinalizador df-h nos logs de estado da instância para verificar a utilização do disco e a degradação do nó. Verifique também a condição do nó em AWS Health Dashboard.
Informações relacionadas
Como resolvo o erro "Container killed by YARN for exceeding memory limits" do Spark no Amazon EMR?
Como posso solucionar falhas de estágio em trabalhos do Spark no Amazon EMR?