跳至内容

如何解决 Amazon EMR 上 Spark 中的“Container killed on request. Exit code is 137”错误?

2 分钟阅读
0

我在 Amazon EMR 上的 Apache Spark 作业失败,并出现“Container killed on request.Exit code is 137”错误。

简短描述

当容器(Spark 执行程序)耗尽内存时,YARN 会自动终止容器,您可能会收到以下错误:
“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”

解决方法

增加驱动程序或执行程序内存

要增加容器内存,请先连接集群的主节点,然后修改 Spark 配置文件 (spark-defaults.conf) 中的 spark.executor.memoryspark.driver.memory 参数。

正在运行的集群

要打开 spark-defaults.conf,请运行以下命令:

sudo vim /etc/spark/conf/spark-defaults.conf

要增加容器内存,请在 spark-defaults.conf 中添加或修改以下参数:

spark.executor.memory 10g
spark.driver.memory 10g

**注意:**根据集群的可用资源和工作负载要求,将 10g 替换为内存值。

单个作业

运行 spark-submit 时,使用 --executor-memory--driver-memory 选项来增加内存。

示例:

spark-submit
  --executor-memory 10g
  --driver-memory 10g
  ...

**注意:**根据集群的可用资源和工作负载要求,将 10g 替换为适当的内存值。

添加更多 Spark 分区

如果无法增加容器内存(例如,在节点上使用的是 maximizeResourceAllocation),则可增加 Spark 分区的数量。这样可以减少单个 Spark 任务处理的数据量,从而减少单个执行程序使用的总内存。

要添加更多 Spark 分区,请先连接集群的主节点,然后在 Spark Shell 中运行以下命令:

val numPartitions = 500
val newDF = df.repartition(numPartitions)

**注意:**将 500 替换为适合您的数据大小的分区数量。

增加随机分区的数量

如果错误发生在广泛转换(例如 joingroupBy)期间,请先连接到集群的主节点,然后添加更多随机分区。默认值为 200。

正在运行的集群

要打开 spark-defaults.conf,请运行以下命令:

sudo vim /etc/spark/conf/spark-defaults.conf

更新配置文件中的随机分区:

spark.sql.shuffle.partitions 500

**注意:**将 500 替换为适合您的数据大小的分区数量。

单个作业

运行 spark-submit 时,使用 --conf spark.sql.shuffle.partitions 选项添加更多随机分区。

示例:

spark-submit
  --conf
  spark.sql.shuffle.partitions=500
  ...

减少执行程序内核的数量

当您减少执行程序内核的数量时,还会减少执行程序同时处理的最大任务数。由此可以减少容器使用的内存量。

正在运行的集群

首先连接到集群的主节点,然后在主节点上打开 spark-defaults.conf 文件:

sudo vim /etc/spark/conf/spark-defaults.conf

要设置执行程序内核的数量,请修改 spark.executor.cores 参数:

spark.executor.cores  1

**注意:**将 1 替换为使用案例所需的执行程序内核数。

单个作业

运行 spark-submit 时,使用 --executor-cores 选项减少执行程序内核的数量。

示例:

spark-submit
   --executor-cores 1
   ...

增加实例大小

当操作系统内存不足时,操作系统 oom_reaper 也可能会终止 YARN 容器。如果这样导致错误,请使用具有更多 RAM 的更大实例。为确保 YARN 容器不会耗尽 Amazon Elastic Compute Cloud (Amazon EC2) 的所有 RAM,请降低 yarn.nodemanager.resource.memory-mb

查看您的 Amazon EMR 实例日志中的 dmesg 命令输出,以确定 oom_reaper 是否导致了错误。首先,使用 YARM 资源管理器用户界面或日志来查找被终止的 YARN 容器运行的核心或任务节点。然后,查看容器被终止之前和之后此节点上的 Amazon EMR 实例状态日志,以确定导致进程终止的 oom_reaper

在以下示例中,内核(Linux 的 OOM 终止程序)终止了 ID 为 36787 的进程,该进程对应于 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

检查磁盘利用率和节点降级

如果前面的故障排除选项无法解决错误,请检查磁盘利用率和节点降级。使用实例状态日志中的 df-h 标志来检查集群和节点磁盘利用率。还可以在Amazon Health Dashboard 上查看节点状况。

相关信息

如何解决 Amazon EMR 上 Spark 中的错误“Container killed by YARN for exceeding memory limits”?

如何解决 Amazon EMR 上 Spark 作业中的阶段故障?

AWS 官方已更新 4 个月前