You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Docker环境下PySpark应用无法连接Spark-Master的问题求助

解决PySpark应用无法连接Docker中Spark集群的问题

从你的错误日志里java.net.UnknownHostException: spark-master可以明确看出,核心问题是你的PySpark应用所在的环境无法解析spark-master这个主机名,导致无法连接到Spark Master节点。下面分两种常用场景给出针对性解决方案:

场景1:Python应用用Docker容器运行(推荐)

既然你的Spark集群是用Docker Compose搭建的,最稳妥的方式是把Python应用也加入到同一个Docker网络(也就是你定义的spark网络)里,这样容器之间可以通过服务名互相解析通信。

步骤1:扩展Docker Compose文件,添加Python应用服务

在原有的docker-compose.yml里新增一个服务节点:

version: '3'
services:
  spark-master:
    # 保留你原有的spark-master配置
    image: docker.io/bitnami/spark:2
    environment:
      - SPARK_MODE=master
      - SPARK_RPC_AUTHENTICATION_ENABLED=no
      - SPARK_RPC_ENCRYPTION_ENABLED=no
      - SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
      - SPARK_SSL_ENABLED=no
    volumes:
      - type: bind
        source: ./conf/log4j.properties
        target: /opt/bitnami/spark/conf/log4j.properties
    ports:
      - '8080:8080'
      - '7077:7077'
    networks:
      - spark
  spark-worker-1:
    # 保留你原有的spark-worker-1配置
    image: docker.io/bitnami/spark:2
    environment:
      - SPARK_MODE=worker
      - SPARK_MASTER_URL=spark://spark-master:7077
      - SPARK_WORKER_MEMORY=1G
      - SPARK_WORKER_CORES=1
      - SPARK_RPC_AUTHENTICATION_ENABLED=no
      - SPARK_RPC_ENCRYPTION_ENABLED=no
      - SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
      - SPARK_SSL_ENABLED=no
    volumes:
      - type: bind
        source: ./conf/log4j.properties
        target: /opt/bitnami/spark/conf/log4j.properties
    ports:
      - '8081:8081'
    networks:
      - spark
    depends_on:
      - spark-master
  # 新增Python应用服务
  pyspark-app:
    build: . # 假设你的Python项目根目录有Dockerfile,构建包含PySpark的运行环境
    volumes:
      - ./your-app-code:/app # 挂载本地代码目录到容器内
    working_dir: /app
    environment:
      - SPARK_MASTER_URL=spark://spark-master:7077
      - SPARK_DRIVER_HOST=pyspark-app # 用服务名作为driver主机名,让worker能回调连接
    networks:
      - spark
    depends_on:
      - spark-master
networks:
  spark:
    driver: bridge

步骤2:调整Spark Session配置

把代码里的spark.driver.host配置改成容器服务名(也就是上面的pyspark-app),或者通过环境变量动态获取:

def get_spark_context(app_name: str) -> SparkSession:
    conf = SparkConf()
    conf.setAll(
        [
            ( "spark.master", os.environ.get("SPARK_MASTER_URL", "spark://spark-master:7077"), ),
            ("spark.driver.host", os.environ.get("SPARK_DRIVER_HOST", "pyspark-app")), # 修改此处
            ("spark.submit.deployMode", "client"),
            ('spark.ui.showConsoleProgress', 'true'),
            ("spark.driver.bindAddress", "0.0.0.0"),
            ("spark.app.name", app_name)
        ]
    )
    return SparkSession.builder.config(conf=conf).getOrCreate()

步骤3:启动所有服务

运行docker-compose up -d,这样Python应用容器和Spark集群容器处于同一个网络,就能正常解析spark-master主机名了。

场景2:Python应用在宿主机本地运行

如果不想把Python应用放进Docker,需要调整配置让宿主机能访问Spark集群,同时Spark Worker能连接回宿主机的Driver:

步骤1:修改Spark Master地址

spark.master改成宿主机的localhost(因为你已经把7077端口映射到宿主机了):

conf.set("spark.master", "spark://localhost:7077")

步骤2:配置Driver主机名

必须把spark.driver.host设置为宿主机的真实IP地址(不能是localhostlocal[*]),因为Spark Worker容器需要通过这个IP访问到你的宿主机Driver:

# 替换成你的宿主机IP,比如192.168.1.100
conf.set("spark.driver.host", "192.168.1.100")

步骤3:开放防火墙端口

Spark Driver默认会使用随机端口,你可以固定端口避免防火墙拦截:

conf.set("spark.driver.port", "4040") # 固定Driver端口

然后在宿主机防火墙开放这个端口,让Spark Worker容器能正常访问。

错误原因说明

你用Docker Compose创建的spark网络是自定义桥接网络,只有加入这个网络的容器才能互相通过服务名(比如spark-master)解析IP。如果你的Python应用不在这个网络里(不管是宿主机还是其他外部容器),就无法解析spark-master的主机名,从而抛出UnknownHostException

内容的提问来源于stack exchange,提问作者Tavis

火山引擎 最新活动