如何从不同主机外部访问在docker容器(overlay)中运行的服务

时间:2016-09-09 22:11:48

标签: hadoop apache-spark docker yarn

我有一个在覆盖网络上运行的docker容器。我的要求是从不同的主机外部访问在此容器中运行的服务。该服务绑定到容器的内部IP地址,在这种情况下,端口绑定到主机不是解决方案。

实际情景

在容器内运行的服务是使用 yarn-client 配置的 spark driver 。火花驱动程序绑定到容器内部IP(10.x.x.x)。当火花驱动器与在不同群集上运行的hadoop纱线通信时,纱线上的应用程序主机会尝试与驱动程序的容器内部ip上的spark驱动程序进行通信,但由于显而易见的原因,它无法连接到内部IP上的驱动程序

如果有办法实现从应用程序主人(纱线)到火花司机(码头集装箱)的成功通信,请告诉我。

Swarm版本:1.2.5

scalac AplusB.scala -deprecation
AplusB.scala:5: warning: method readLine in class DeprecatedConsole is deprecated: Use the method in scala.io.StdIn
val rawInput = Console.readLine()

运行容器的命令:我使用docker-compose运行它:

docker info:

Containers: 3
 Running: 2
 Paused: 0
 Stopped: 1
Images: 42
Server Version: swarm/1.2.5
Role: primary
Strategy: spread
Filters: health, port, containerslots, dependency, affinity, constraint
Nodes: 1
 ip-172-30-0-175: 172.30.0.175:2375
  └ ID: YQ4O:WGSA:TGQL:3U5F:ONL6:YTJ2:TCZJ:UJBN:T5XA:LSGL:BNGA:UGZW
  └ Status: Healthy
  └ Containers: 3 (2 Running, 0 Paused, 1 Stopped)
  └ Reserved CPUs: 0 / 16
  └ Reserved Memory: 0 B / 66.06 GiB
  └ Labels: kernelversion=3.13.0-91-generic, operatingsystem=Ubuntu 14.04.4 LTS, storagedriver=aufs
  └ UpdatedAt: 2016-09-10T05:01:32Z
  └ ServerVersion: 1.12.1
Plugins:
 Volume: 
 Network: 
Swarm: 
 NodeID: 
 Is Manager: false
 Node Address: 
Security Options:
Kernel Version: 3.13.0-91-generic
Operating System: linux
Architecture: amd64
CPUs: 16
Total Memory: 66.06 GiB
Name: 945b4af662a4
Docker Root Dir: 
Debug Mode (client): false
Debug Mode (server): false

1 个答案:

答案 0 :(得分:1)

似乎yarn and spark need to be able to see the each other directly on the network。如果你可以把它们放在同一个覆盖网络上,一切都可以直接通信,如果不是......

重叠

可以通过docker_gwbridge将数据直接路由到Docker节点上的覆盖网络,所有覆盖容器都连接到但是,并且它是一个很大的但是,只有在运行容器的Docker节点上才有效。

所以在2节点non swarm mode overlay 10.0.9.0/24 network上运行2个容器...

我可以在demo0上ping本地容器,但不能在demo1

上ping远程
docker@mhs-demo0:~$ sudo ip ro add 10.0.9.0/24 dev docker_gwbridge
docker@mhs-demo0:~$ ping -c 1 10.0.9.2
PING 10.0.9.2 (10.0.9.2): 56 data bytes
64 bytes from 10.0.9.2: seq=0 ttl=64 time=0.086 ms
docker@mhs-demo0:~$  ping -c 1 10.0.9.3
PING 10.0.9.3 (10.0.9.3): 56 data bytes
^C
--- 10.0.9.3 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss

然后在另一台主机上,容器被反转,但它仍然是可访问的本地容器。

docker@mhs-demo1:~$ sudo ip ro add 10.0.9.0/24 dev docker_gwbridge
docker@mhs-demo1:~$ ping 10.0.9.2
PING 10.0.9.2 (10.0.9.2): 56 data bytes
^C
--- 10.0.9.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
docker@mhs-demo1:~$  ping 10.0.9.3
PING 10.0.9.3 (10.0.9.3): 56 data bytes
64 bytes from 10.0.9.3: seq=0 ttl=64 time=0.094 ms
64 bytes from 10.0.9.3: seq=1 ttl=64 time=0.068 ms

所以最大的问题是网络需要知道容器在哪里运行并相应地路由数据包。如果网络能够实现这样的路由,那么您可能首先不需要覆盖网络。

桥接网络

另一种可能性是在每个Docker节点上使用可路由IP的普通网桥。因此,每个网桥都分配了一个IP范围,您的网络可以识别并可以从任何地方路由到该范围。

192.168.9.0/24        10.10.2.0/24
Yarn                  DockerC

             router

10.10.0.0/24          10.10.1.0/24     
DockerA               DockerB          

将网络连接到每个节点。

DockerA:$ docker network create --subnet 10.10.0.0/24 sparknet
DockerB:$ docker network create --subnet 10.10.1.0/24 sparknet
DockerC:$ docker network create --subnet 192.168.2.0/24 sparknet

然后,路由器通过10.10.0.0/24等配置DockerA的路由。

这与Kubernetes does its networking的方法类似。

Weave Net

Weave类似于覆盖,因为它创建了一个通过UDP传输数据的虚拟网络。它虽然是and can integrate with a host network,但它更像是一种通用的网络解决方案。