如何解决Spark代码与Docker部署的Spark集群连接异常问题
问题分析与解决方案
问题1:Spark代码指定9010端口连接HDFS,却默认访问9000端口导致连接拒绝
原因分析
HDFS NameNode的内部RPC端口默认是9000,你在Spark代码里配置的9010大概率是宿主机的端口映射值,而非容器内部NameNode实际监听的端口。Spark客户端获取HDFS元数据时,会直接使用NameNode返回的内部RPC端口(9000),而非你配置的宿主机映射端口,导致未映射9000端口时出现连接拒绝。
解决步骤
- 修正Docker Compose端口映射:确保NameNode的RPC端口(容器内部9000)映射到宿主机,配置示例:
namenode: ports: - "9000:9000" # 映射NameNode内部RPC端口到宿主机 - "50070:50070" # WebUI端口映射 - 统一Spark代码的HDFS地址:直接使用容器内部服务名+RPC端口(需在Windows Hosts中配置
namenode指向宿主机IP),或宿主机IP+映射的9000端口,示例:
注意:不要用9010,除非你在容器内部修改了spark = SparkSession.builder.appName("HDFSQuery") \ .config("spark.hadoop.fs.defaultFS", "hdfs://namenode:9000") \ .getOrCreate()core-site.xml中fs.defaultFS的端口配置。 - 验证HDFS内部配置:进入namenode容器,检查
/opt/hadoop/etc/hadoop/core-site.xml,确保fs.defaultFS值为hdfs://namenode:9000,保证集群内部地址一致。
问题2:修改端口映射为9000:9000并配置hosts后,Executor反复以退出码1重启
原因分析
核心是Executor无法正常连接集群服务或资源不足,常见诱因:
- 宿主机的hosts配置仅在本地生效,Executor容器内无法解析
namenode地址 - 防火墙或Docker网络模式限制,导致Executor容器无法访问宿主机9000端口
- Spark/YARN资源配置不足,Executor因OOM被强制终止
- HDFS集群内部地址与外部配置不一致,Executor获取的地址无法访问
解决步骤
- 统一集群网络解析:
- 若Spark客户端在宿主机运行,需在所有集群容器(namenode、spark-worker等)的
/etc/hosts中添加宿主机IP与namenode的映射 - 更稳妥的方式是将Spark客户端也运行在Docker容器内,与集群同网络,避免跨网络解析问题
- 若Spark客户端在宿主机运行,需在所有集群容器(namenode、spark-worker等)的
- 查看Executor日志定位根因:进入spark-worker容器,查看Executor的错误日志,示例:
日志会明确显示错误原因,比如docker exec -it spark-worker bash cat /opt/spark/work/app-<应用ID>/<ExecutorID>/stderrUnknownHostException: namenode、Connection refused或OutOfMemoryError等 - 调整Spark资源配置:若为内存不足导致重启,提交任务时增加资源配额:
spark = SparkSession.builder.appName("HDFSQuery") \ .config("spark.hadoop.fs.defaultFS", "hdfs://namenode:9000") \ .config("spark.executor.memory", "2g") \ .config("spark.driver.memory", "1g") \ .getOrCreate() - 检查HDFS集群健康状态:在namenode容器内执行命令,确认DataNode正常连接:
docker exec -it namenode hdfs dfsadmin -report
通用连通性验证建议
- 宿主机执行
ping namenode,确认hosts配置生效 - 宿主机执行
telnet namenode 9000,验证端口连通性 - 在spark-worker容器内执行
hdfs dfs -ls /,验证集群内部HDFS访问正常
内容的提问来源于stack exchange,提问作者Sadegh
相关产品推荐
相关产品推荐

