带有docker容器

时间:2015-09-22 14:02:21

标签: networking apache-spark docker

到目前为止,我只在Linux机器和虚拟机(桥接网络)上运行Spark,但现在我对使用更多计算机作为奴隶感兴趣。在计算机上分发Spark Slave Docker容器并让它们自动连接到硬编码的Spark master ip会很方便。这个缺点已经完成,但我在从属容器上配置正确的SPARK_LOCAL_IP(或start-slave.sh的--host参数)时遇到了问题。

我认为我正确配置了SPARK_PUBLIC_DNS env变量以匹配主机的网络可访问ip(来自10.0.xx地址空间),至少它显示在Spark主Web UI上并且可供所有计算机访问。

我还按照http://sometechshit.blogspot.ru/2015/04/running-spark-standalone-cluster-in.html的指示设置了SPARK_WORKER_OPTS和Docker端口转发,但在我的情况下,Spark主控器在另一台机器上运行,而不是在Docker内运行。我正在从网络中的其他机器启动Spark作业,也可能自己运行从机。

我尝试过的事情:

  1. 根本没有配置SPARK_LOCAL_IP,slave绑定到容器的ip(如172.17.0.45),无法连接到master或driver,计算大部分时间仍然有效,但并非总是如此
  2. 绑定到0.0.0.0,奴隶与主人交谈并建立一些连接但它死了,另一个奴隶出现并消失,他们继续像这样循环
  3. 绑定到主机ip,启动失败,因为在容器中看不到ip,但是当配置端口转发时其他人可以访问
  4. 我想知道为什么连接到从设备时未使用配置的SPARK_PUBLIC_DNS?我以为SPARK_LOCAL_IP只会影响本地绑定,但不会泄露给外部计算机。

    https://databricks.gitbooks.io/databricks-spark-knowledge-base/content/troubleshooting/connectivity_issues.html,他们指示将SPARK_LOCAL_IP设置为驱动程序,主服务器和工作进程的集群可寻址主机名",这是唯一的选择吗?我会避免额外的DNS配置,只需使用ips配置计算机之间的流量。或者有一种简单的方法来实现这一目标吗?

    编辑: 总结当前的设置:

    • Master在Linux上运行(在Windows上使用桥接网络的VirtualBox上运行VM)
    • 驱动程序从其他Windows计算机提交作业,效果很好
    • 用于启动从站的Docker镜像以"已保存的"分发。 .tar.gz文件,加载(curl xyz | gunzip | docker load)并在网络中的其他机器上启动,这个probem具有私有/公共ip配置

3 个答案:

答案 0 :(得分:10)

我在我的机器上运行3种不同类型的docker容器,目的是在我们需要的所有软件添加到云中时将它们部署到云中:Master,Worker和Jupyter笔记本(带有Scala,R和Python内核) )。

到目前为止,我的观察结果如下:

  • 我无法将其绑定到Docker主机IP。相反,我将一个组成的域名传递给它:-h "dockerhost-master" -e SPARK_MASTER_IP="dockerhost-master"。我找不到一种方法让Akka绑定容器的IP,但接受针对主机IP的消息。我知道这可能与Akka 2.4有关,但也许不适用于Spark。
  • 我正在传递-e SPARK_LOCAL_IP="${HOST_IP}",导致Web UI绑定到该地址而不是容器的IP,但Web UI可以正常工作。

<强>工人:

  • 我为worker容器提供了一个不同的主机名,并将其作为--host传递给Spark org.apache.spark.deploy.master.Worker类。它不能与主人或Akka群集相同:-h "dockerhost-worker"
  • 我正在使用Docker的add-host,因此容器可以将主机名解析为主IP:--add-host dockerhost-master:${HOST_IP}
  • 需要传递的主网址是spark://dockerhost-master:7077

<强> Jupyter:

  • 此网站需要主网址,add-host才能解析
  • SparkContext存在于笔记本中,而且是启动Spark应用程序的Web UI的地方,而不是主数据库。默认情况下,它绑定到Docker容器的内部IP地址。要改变我必须传递的内容:-e SPARK_PUBLIC_DNS="${VM_IP}" -p 4040:4040。笔记本电脑的后续应用程序将在4041,4042等上进行。

通过这些设置,三个组件可以相互通信。我正在使用spark-class的自定义启动脚本在前台启动类,并防止Docker容器暂时退出。

还有一些其他端口可以暴露,例如历史服务器,我还没有遇到过。使用--net host似乎更简单。

答案 1 :(得分:7)

我想我找到了一个用例(一个Spark容器/主机操作系统)的解决方案:

  1. --net host =&gt;使用docker run主机的eth0在容器中可见
  2. SPARK_PUBLIC_DNSSPARK_LOCAL_IP设置为主持人的IP,忽略docker0的172.x.x.x地址
  3. Spark可以绑定到主机的ip,其他机器也可以与它通信,端口转发负责其余部分。不需要DNS或任何复杂的配置,我没有彻底测试过这个,但到目前为止还不错。

    编辑:请注意,这些说明适用于Spark 1.x,在Spark 2.x中只需要SPARK_PUBLIC_DNS,我认为{@ 1}}已被弃用。

答案 2 :(得分:6)

我也在不同的docker主机上的容器中运行spark。使用这些参数启动worker容器对我有用:

docker run \
-e SPARK_WORKER_PORT=6066 \
-p 6066:6066 \
-p 8081:8081 \
--hostname $PUBLIC_HOSTNAME \
-e SPARK_LOCAL_HOSTNAME=$PUBLIC_HOSTNAME \
-e SPARK_IDENT_STRING=$PUBLIC_HOSTNAME \
-e SPARK_PUBLIC_DNS=$PUBLIC_IP \
spark ...

其中$PUBLIC_HOSTNAME是可从主服务器访问的主机名。

缺失的部分是SPARK_LOCAL_HOSTNAME,一个未记录的选项AFAICT。

https://github.com/apache/spark/blob/v2.1.0/core/src/main/scala/org/apache/spark/util/Utils.scala#L904