我正在尝试在Docker容器中运行Spark 2,这对我来说很难。我认为已经走了很长一段路,能够将一个独立主服务器部署到主机A,一个工作服部署到主机B.我配置了Docker容器的/ etc / hosts,以便主服务器和工作服务器可以访问它们各自的主机。他们看到对方,一切看起来都很好。
我使用这组打开的端口部署master:
docker run -ti --rm \
--name sparkmaster \
--hostname=host.a \
--add-host host.a:xx.xx.xx.xx \
--add-host host.b:xx.xx.xx.xx \
-p 18080:18080 \
-p 7001:7001 \
-p 7002:7002 \
-p 7003:7003 \
-p 7004:7004 \
-p 7005:7005 \
-p 7006:7006 \
-p 4040:4040 \
-p 7077:7077 \
malkab/spark:ablative_alligator
然后我提交这个Spark配置选项:
export SPARK_MASTER_OPTS="-Dspark.driver.port=7001
-Dspark.fileserver.port=7002
-Dspark.broadcast.port=7003 -Dspark.replClassServer.port=7004
-Dspark.blockManager.port=7005 -Dspark.executor.port=7006
-Dspark.ui.port=4040 -Dspark.broadcast.blockSize=4096"
export SPARK_MASTER_PORT=7077
export SPARK_MASTER_WEBUI_PORT=18080
我使用前面提到的env变量的SPARK_WORKER_XXX版本以及类似的docker run来在其主机上部署worker。
然后我进入主容器并点火提交工作:
spark-submit --master spark://host.a:7077 /src/Test06.py
一切都很顺利:我可以看到工作正在分配给工人。但是当块管理器尝试注册块时,它似乎使用了一个随机端口,该端口在容器外是不可访问的:
INFO BlockManagerMasterEndpoint: Registering block manager host.b:39673 with 366.3 MB RAM, BlockManagerId(0, host.b, 39673, None)
然后我收到此错误:
WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, host.b, executor 0): java.io.IOException: org.apache.spark.SparkException: Failed to get broadcast_0_piece0 of broadcast_0
工人报告:
java.io.IOException: Failed to connect to host.a/xx.xx.xx.xx:55638
到目前为止,我已经能够避免使用先前设置的随机端口,但特别是这个Block Manager端口似乎是随机的。我虽然它是由spark.blockManager.port控制的,但似乎并非如此。我已经审查了所有配置选项但无济于事。
所以,最后一个问题:这个端口是什么,可以避免它是随机的?
提前致谢。
修改
这是启动的执行者。如您所见,随机端口在驱动程序(与主服务器位于同一主机上)和工作程序中都是打开的:
我理解一个worker实例化了许多执行器,并且他们应该分配一个端口。有没有办法,至少限制这种通信的端口范围?那么人们如何处理紧密防火墙背后的Spark呢?
编辑2:
我终于开始工作了。如果我通过,如前所述,SPARK_MASTER_OPTS和SPARK_WORKER_OPTS中的属性spark.driver.host = host.a它将无法工作,但是,如果我在上下文配置的代码中配置它:
conf = SparkConf().setAppName("Test06") \
.set("spark.driver.port", "7001") \
.set("spark.driver.host", "host.a") \
.set("spark.fileserver.port", "7002") \
.set("spark.broadcast.port", "7003") \
.set("spark.replClassServer.port", "7004") \
.set("spark.blockManager.port", "7005") \
.set("spark.executor.port", "7006") \
.set("spark.ui.port", "4040") \
.set("spark.broadcast.blockSize", "4096") \
.set("spark.local.dir", "/tmp") \
.set("spark.driver.extraClassPath", "/classes/postgresql.jar") \
.set("spark.executor.extraClassPath", "/classes/postgresql.jar")
它以某种方式工作了。为什么SPARK_MASTER_OPTS或SPARK_WORKER_OPTS中的设置不受尊重?