Spark on Kubernetes 故障排查:Pod Pending 与调度取舍

围绕 Executor Pod Pending 与驱逐的事件证据链定位资源调度问题,对比 Gang 调度与预留资源取舍

袋鼠云
袋鼠云
数据下云

Executor Pod 长期 Pending 的答案几乎都写在事件里:kubectl describe pod 的 Events 段会直接给出 FailedScheduling 的具体约束——CPU/内存不足、节点选择器不匹配、污点不容忍、存储卷未绑定、命名空间配额超限。先读事件,再决定改资源、改配额还是改调度策略,顺序错了就会在扩容里空转。本文围绕这条事件证据链展开,并对比默认调度、Gang 调度与预留资源三种方案在批量负载下的取舍。

一、按证据链顺序采集信息

排查顺序固定为五步,每一步都回答一个问题。

  1. Driver 日志:作业卡在哪一步,已经起了几个 Executor,请求了多少资源。
  2. kubectl describe pod 的 Events:Pending 或 Evicted 的直接原因。
  3. 节点状态:可分配资源、污点(taints)、标签,确认期望节点是否真的存在。
  4. 命名空间约束:ResourceQuota 与 LimitRange 的用量与上限。
  5. 调度器侧:队列深度、是否有其它作业长期占用资源。

Events 的读法示例:

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  32s   default-scheduler  0/6 nodes are available:
    3 Insufficient cpu, 2 node(s) didn't match node selector,
    1 node(s) had untolerated taint.

这条消息说明六个候选节点全部被排除,原因有三类:三个节点 CPU 不够、两个节点不匹配节点选择器、一个节点有不容忍的污点。注意它只解释"这一个 Pod"为什么没被调度;如果只有个别 Executor Pending,而其它都起来了,多半是资源余量刚好卡在边界,不是配额问题。

二、把 Pending 原因分四类处置

资源请求与限制不匹配。检查 Spark 侧的 executor 核数与内存配置(spark.kubernetes.executor.request.cores、spark.kubernetes.executor.limit.cores、executor 内存加 spark.kubernetes.executor.memoryOverhead)。关键点是 request 而不是 limit 决定能否调度:request 大于任何节点的可分配余量,Pod 就永远 Pending。反向的错误也常见——为了"先把 Pod 起来"把 request 调到远低于真实用量,调度是过了,运行时却触发节点压力被驱逐。

命名空间配额与范围限制。ResourceQuota 按命名空间限制总 CPU、内存与 Pod 数,LimitRange 给容器设默认值与上下限。批量场景最容易在这里出事:多个作业并发提交,配额被新作业的 request 占满,老作业的 Executor 无法补充,作业互相等待形成事实上的排队甚至死锁。判别方法是对比 kubectl describe quota 的已用量与作业的总 request:已用量接近上限且等待方正是运行中作业的补充分配,就是配额死锁,处置是给不同优先级作业分命名空间或分配额,或给关键作业预留额度。

节点选择与污点。nodeSelector、亲和性与容忍度共同决定候选节点集合。常见失配是模板化的节点标签与集群现状漂移(节点换了标签池),或专用节点带污点而 Executor 没配容忍。统一用 pod 模板(spark.kubernetes.executor.podTemplateFile)沉淀节点选择、容忍与卷挂载配置,避免每个作业各写一份然后各自漂移。

存储卷未绑定。Executor 需要 PVC 而存储类无可用卷、或卷拓扑与节点不匹配时,事件会显示 PVC 相关的绑定失败。检查存储类的供给能力与卷绑定模式,shuffle 本地盘不足的场景还要确认临时盘容量。

大数据基础平台 EasyMR

统一存储、计算与运维,支撑批、流、OLAP 与湖仓一体的国产化大数据底座平台

了解产品

三、被驱逐(Evicted)与它的近亲

Evicted 不是 Pending,但两者常交替出现。节点内存或磁盘压力会触发驱逐,典型诱因是 Executor 实际内存超出 request、shuffle 本地数据写满节点磁盘、临时数据未清理。处置组合是:给 memoryOverhead 留真实余量、控制单节点 Executor 密度(反亲和打散)、为临时数据规划独立磁盘或限制 shuffle 规模。被驱逐后 Driver 会申请新的 Executor Pod,在资源紧张时就表现为"反复 Pending"——所以看到频繁 Evicted,先修驱逐原因,不要只盯着 Pending。

四、三种调度方案的取舍

默认调度器(逐个调度)。优点是零额外组件、行为直观,交互式与小规模作业最合适。缺点在批量负载下被放大:Pod 逐个进入调度,部分 Executor 起不来时作业以残缺并行度慢速运行,占着资源不释放,多作业并发时互相饿死,出现"大家都能跑一点、大家都跑不完"的僵局。

Gang 调度(一组 Pod 要么同时满足要么都不调度)。通过指定第三方调度器(spark.kubernetes.scheduler.name)配合其队列与最小可用数配置实现。它从机制上消除部分占用与死锁——一组 Executor 不凑齐就整体排队,资源够了整体起飞。代价是排队变长、需要部署和运维调度器组件,单个小作业的启动延迟可能反而变高。适合大规模批处理、多作业并发争抢同一资源池的场景。

预留资源(优先级 + 额度预留)。用 PriorityClass、抢占与配额预留给关键作业保住额度。优点是关键作业的启动时间可预期;缺点是整体利用率下降——预留的额度别人用不了,空闲时浪费。适合有明确 SLA 的关键流水线,通常与配额管理组合使用。

实践上的取舍:交互式和开发作业用默认调度器配合理 request;大规模批量作业上 Gang 调度加队列管理;混合负载则"分区资源池 + 优先级 + 配额"三层叠加,让批量作业吃空闲、关键作业保底线。参考实践(Kubernetes 上的 Spark 性能优化、批量负载调度实践)里给出的批量场景调优方向与这个取舍一致。

五、提交前的对齐走查

大部分 Pending 可以在提交前消掉,做法是把作业侧配置与集群侧约束做一次对齐核对。对着节点可分配余量核算 executor 的 request(核数、内存加 memoryOverhead),确认不大于目标节点池的单节点余量;对着 ResourceQuota 核算并发作业的总 request,并为关键作业留出余量;对着节点标签与污点核对 pod 模板里的选择器与容忍;对着存储类核对 PVC 的绑定模式与供给能力。四条对齐都通过再提交批量作业。运行中再次出现 Pending,回看是哪一条被运行期变化打破了——节点下线、配额被其它作业占满、标签池调整,事件证据链会指出具体是哪一条。

数据下云

帮助企业把公有云上的数据任务、计算资源与调度体系,分批、平稳、低风险迁回自主可控的数据平台。

了解解决方案

六、预防与自查清单

  • 用 pod 模板统一节点选择、容忍、卷挂载与 label,防止配置漂移。
  • request 按真实用量配置,宁可少调度几个 Executor,也不要制造驱逐;limit 用于隔离,不用于调度。
  • 提交批量作业前检查 ResourceQuota 余量,为关键作业预留额度或单独命名空间。
  • 打开动态分配并配合 shuffle 跟踪(spark.dynamicAllocation.shuffleTracking.enabled),让空闲 Executor 及时回收,减少配额占压。
  • 监控 Pending 事件数、Evicted 次数与队列深度三个信号,它们比"作业慢了"更早暴露问题。
  • 作业卡住先采集五步证据链再动手,避免把污点不匹配、配额死锁误判为资源不足而盲目扩容。

Spark 官方的 Kubernetes 运行文档对资源请求、动态分配与调度器集成有完整参数说明,改动调度方案前值得逐项核对。

七、走查示例:反复 Pending 的定位(示意)

一个批量作业提交后,Driver 正常启动,Executor 只起来一部分,其余反复 Pending。按证据链走:describe pod 的 Events 显示 Insufficient cpu 与配额相关的排除原因并存;核对 ResourceQuota,发现命名空间的 CPU 配额已被另一个批量作业的 request 占满,老作业的 Executor 补充分配被挡住,两个作业互相等待——这是配额死锁而不是集群资源不够。处置是给两个作业分额度(或分命名空间),而不是扩容节点:节点整体仍有余量,扩出来的容量照样进不了这个命名空间。修完配额,Pending 的 Pod 在下一次调度周期整体通过,也印证了事件证据链指向的结论。

开启Data+AI 之旅

填写表单,获取专属解决方案

400-002-1024

工作日 9:00-18:00

关注公众号

获取最新产品动态与技术干货

关注公众号

企业微信

扫码添加企业微信