本地Spark应用连接Docker中HDFS集群写入文件失败求助
问题分析与解决方案
核心问题
本地Spark客户端无法连接Docker容器内DataNode的数据传输端口(9866):
- NameNode返回给Spark的是DataNode在Docker内部网络的IP(172.18.0.3)和未映射的9866端口
- 宿主机无法直接访问Docker容器的内部IP与未暴露端口,导致连接超时、文件写入失败
解决方案
方案1:端口映射+HDFS配置修正(生产/开发通用)
更新Docker Compose配置
给DataNode添加9866端口映射,并配置对外暴露的地址:version: "3.9" networks: hadoop-net: driver: bridge services: hdfs-namenode: container_name: "hdfs-namenode" image: "apache/hadoop:3" hostname: "hdfs-namenode" command: ["hdfs", "namenode"] ports: - "8020:8020" - "9870:9870" env_file: - ./hadoop-config/config.env environment: ENSURE_NAMENODE_DIR: "/tmp/hadoop-root/dfs/name" networks: - hadoop-net hdfs-datanode: depends_on: hdfs-namenode: condition: service_started container_name: "hdfs-datanode" image: "apache/hadoop:3" hostname: "hdfs-datanode" command: ["hdfs", "datanode"] ports: - "9864:9864" - "9866:9866" # 新增数据传输端口映射 env_file: - ./hadoop-config/config.env environment: # 配置DataNode对外暴露的地址与端口 HDFS_DATANODE_ADDRESS: 0.0.0.0:9866 HDFS_DATANODE_IPC_ADDRESS: 0.0.0.0:9867 HDFS_DATANODE_HTTP_ADDRESS: 0.0.0.0:9864 networks: - hadoop-net配置HDFS全局参数
在./hadoop-config/config.env文件中添加以下内容(无文件则新建):CORE_CONF_fs_defaultFS=hdfs://hdfs-namenode:8020 # 关闭DataNode注册时的IP/主机名检查 HDFS_CONF_dfs_namenode_datanode_registration_ip___hostname___check=false # 让客户端使用DataNode的主机名而非IP访问 HDFS_CONF_dfs_client_use_datanode_hostname=true HDFS_CONF_dfs_datanode_use_datanode_hostname=true重启集群
docker-compose down -v docker-compose up -d
方案2:让Spark接入Docker网络(开发测试快速解决)
直接让Spark客户端加入Docker的hadoop-net网络,绕过宿主机与容器的网络隔离:
- 获取Docker网络名称:
docker network ls | grep hadoop-net - 在Docker网络内运行Spark:
在该Shell环境中执行你的Spark代码即可。docker run --network big-data-project-2_hadoop-net -it --rm apache/spark:3.5.1 spark-shell \ --conf spark.hadoop.fs.defaultFS=hdfs://hdfs-namenode:8020
方案3:Spark客户端配置代理访问(临时测试用,性能差)
通过强制Spark使用NameNode代理读写数据,避免直接连接DataNode:
spark = SparkSession.builder \ .config("spark.hadoop.fs.defaultFS", "hdfs://localhost:8020") \ .config("spark.hadoop.dfs.client.use.datanode.hostname", "false") \ .config("spark.hadoop.dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER") \ .appName("Spark SQL") \ .getOrCreate()
验证方法
重启集群后,执行Spark代码,再通过以下命令检查文件内容:
docker exec -it hdfs-namenode hdfs dfs -cat /user/hadoop/data/people.csv/*
内容的提问来源于stack exchange,提问作者Paul Hartmann
相关产品推荐
相关产品推荐

