摘要
引言在将几个 Spark 批处理管道从本地基础设施迁移到 Azure Kubernetes Service (AKS) 后不久,我们发现其中一个比较大的作业反复出现执行器内存不足 (OOM) 故障。这些故障出现在 shuffle 阶段,起初看起来像是典型的 Spark 内存调优问题。我们尝试了增加执行器内存、调整执行器数量,并多次重启该作业,但这些方法都未奏效。令人费解的是,该管道在迁移前已经稳定运行多年。最终的根本原因根本不是 Spark 配置问题,而是迁移过程中引入的两项基础设施级设置发生了意想不到的交互:基于 RAM 的本地临时目录(spark.kubernetes.local.dirs.tmpfs=true)以及一条严格的强制所有执行器位于同一节点的 podAffinity 规则。这两项设置共同导致了 shuffle 溢写消耗了节点内存而非磁盘空间,从而引发了反复的 OOM 终止。本文记录了调查过程、根本原因以及用于解决该问题的配置变更。系统环境与迁移背景管道环境我们的数据平台负责管理生产环境的批处理管道,支持美国某大型金融机构对交易数据进行大规模地聚合和转换。相关工作负载每天处理约 3GB 的定宽平面文件。该文件包含多种交错的记录布局,需要进行多次解析和合并操作,这使得该任务的 shuffle 操作强度远高于其 3GB 的输入大小所暗示的水平。在本地环境中,这些管道已经稳定运行了三年多,执行情况稳定,而且未出现这样的内存不足(OOM)模式。AKS 集群配置事件发生的环境如下:迁移背景迁移至 AKS 是更广泛的云现代化计划的一部分。这些工作负载被视为“平移”的候选对象,只要匹配 CPU 和内存配置,即可在不修改应用程序的情况下保持运行时行为。但这一假设被证明是错误的:迁移过程中引入的两项基础设施设置改变了 Kubernetes 处理执行器部署和本地存储的方式,而这两项设置在审查过程中均未被标记出来。事件时间线迁移后第一周最初似乎运行得很稳定,比较小的任务都顺利完成了。首次内存不足(OOM)故障出现在定宽多布局批处理任务中,具体发生在该任务需要对大量数据进行 shuffle 的合并阶段。在合并结果之前,该任务使用不同的布局解析器多次读取了同一个 3GB 大小的文件。第二到第三天OOM 故障最初被视为暂时的。任务被手动重启并暂时恢复。