Spark客户端应用在K8s远程作业完成后仍挂起的原因排查
在K8s中搭建Spark远程服务器,处理7000万条记录的数据集,执行关联操作后成功将数据写入数据库。Spark UI无任何活动,但Spark客户端应用多数情况下会挂起,无法正常退出。
尝试过调整分区数量、取消DataFrame持久化操作,问题未解决。
Spark配置
spark.app.name spark spark.submit.deployMode client spark.scheduler.mode FIFO spark.ui.port 4040 spark.connect.grpc.binding.port 15002 spark.kubernetes.namespace default spark.kubernetes.container.image.pullSecrets pregistrykey spark.driver.bindAddress 0.0.0.0 spark.driver.host connect-server-headless-service.default.svc.cluster.local spark.speculation false spark.executor.instances 9 spark.dynamicAllocation.executorIdleTimeout 180s spark.driver.memory 8g spark.executor.memory 21g spark.executor.cores 6 spark.sql.autoBroadcastJoinThreshold 2m spark.network.timeout 100000s spark.kubernetes.executor.container.image xxxxx spark.executor.extraClassPath /opt/spark/jars/postgresql-42.7.1.jar spark.kubernetes.container.image.pullPolicy Always spark.master k8s://https://kubernetes.default.svc spark.kubernetes.authenticate.executor.serviceAccountName spark spark.kubernetes.authenticate.driver.serviceAccountName spark spark.stage.maxConsecutiveAttempts 1 spark.kubernetes.executor.deleteOnTermination true spark.task.maxFailures 1
驱动端最后日志
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1130_piece0 on 10.244.3.136:35345 in memory (size: 4.1 KiB, free: 12.4 GiB)
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1130_piece0 on 10.244.4.185:36247 in memory (size: 4.1 KiB, free: 12.4 GiB)
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1130_piece0 on 10.244.6.84:36919 in memory (size: 4.1 KiB, free: 12.4 GiB)
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1130_piece0 on 10.244.2.33:45801 in memory (size: 4.1 KiB, free: 12.4 GiB)
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1203_piece0 on connect-server-headless-service.default.svc.cluster.local:38109 in memory (size: 16.6 KiB, free: 4.6 GiB)
24/06/24 13:36:54 INFO BlockManagerInfo: Removed broadcast_1203_piece0 on 10.244.7.193:39017 in memory (size: 16.6 KiB, free: 12.4 GiB)
驱动进程资源回收阻塞
client模式下驱动运行在本地,数据写入完成后,Spark可能在清理广播变量、释放Executor连接时卡住。你设置的spark.network.timeout过大(100000s),会延长驱动等待资源释放的超时时间,导致进程挂起。
建议:添加spark.driver.extraJavaOptions "-Dspark.cleaner.periodicGC.interval=10s"强制定期触发GC,同时将spark.network.timeout调整为合理值(如300s),避免无限等待。K8s Executor Pod清理延迟
配置spark.kubernetes.executor.deleteOnTermination true后,K8s删除Executor Pod可能存在延迟:比如Pod的preStop钩子执行缓慢、节点资源紧张导致Pod终止流程卡住,驱动会一直等待Executor状态更新,无法退出。
建议:检查Executor Pod的终止日志,确认是否有钩子执行慢的情况;尝试设置spark.kubernetes.executor.terminationGracePeriodSeconds=30缩小Pod终止等待时间。Spark Connect线程泄漏
你启用了Spark Connect(spark.connect.grpc.binding.port 15002),如果任务通过Connect提交,可能存在GRPC服务端线程未正确关闭的情况,比如残留的客户端连接未释放,导致驱动进程无法退出。
建议:如果不需要Spark Connect,直接移除spark.connect.grpc.binding.port配置;如果必须使用,在任务执行完成后显式调用SparkSession.stop()关闭Connect服务端。数据库连接未完全释放
虽然数据写入成功,但JDBC writer可能残留未关闭的数据库连接或连接池,持有资源导致驱动进程无法退出。
建议:检查JDBC写入配置,添加连接超时、连接池关闭相关参数;如果是代码层面,确保写入完成后显式关闭连接池(如Java/Scala中调用相关关闭方法)。动态分配线程阻塞
开启动态分配(spark.dynamicAllocation.executorIdleTimeout 180s)同时固定了spark.executor.instances=9,可能导致动态分配线程在回收Executor时卡住,比如Executor未正常发送终止信号,驱动一直等待确认。
建议:暂时关闭动态分配(spark.dynamicAllocation.enabled false),验证是否还会出现挂起,排查是否为动态分配逻辑导致的问题。
内容的提问来源于stack exchange,提问作者Tonmoy Sagar

