• 1
  • 2
  • 3
  • 4
  • 5
阿里云应用开发 首 页  »  帮助中心  »  云服务器  »  阿里云应用开发
利用ambassador实现container跨主机连接
发布日期:2016-8-3 14:8:51


  图1

  我们以阿里云主机为例,针对于同一个阿里云主机上的两个container,我们可使用docker的link机制来它们间的连接。

  但目前针对于不同主机上的两个container,docker并没有提供直接有效的方法来实现它们间的连接,须借助其它工具来实现。docker主页的文章Link via an Ambassador Container介绍了一种方法,通过ambassador pattern来实现container跨主机连接,这里对这种方法做一下解释。

  主机VM1上有装有Redis Server的container,主机VM2上有装有Redis Client的container,为实现Redis Client与Redis Server之间跨主机的连接,需要借助Ambassador容器,这里VM1上有一个Ambassador容器Ambassador1,VM2上有一个Ambassador容器Ambassador2。

  这个方法是怎样工作的呢?我们看一下下面的流程:

  Ambassador1容器通过link方式确定Redis Server容器的ip地址与开放的6379端口,然后利用socat将容器内部的6379端口收到的信息重定向到RedisServer容器的6379端口;

  VM1将自己的6379端口绑定到Ambassador1容器的6379端口;

  Ambassador2通过传入环境变量的方式确定VM1的ip地址与6379端口,然后利用socat将容器内部的6379端口收到的信息重定向到VM1的6379端口;

  Redis Client容器通过link方式确定Ambassador2容器的ip地址与开放的6379端口,然后用redis-cli直接连接,连接请求将经过Ambassador2、Ambassador1,最后发送到Redis Server的6379端口。

  启动这4个container的命令如下所示:

  启动Redis Server:

  

  启动Ambassador1:

  

  启动Ambassador2:(其中x.x.x.x表示VM1的ip地址)

 

  启动Redis Client:

  

  而Ambassador容器是如何利用linux端口映射socat来实现跨主机的通讯呢?

  在svendowideit/Ambassador的Dockerfile里面,有一行关键的代码:

  

  这行代码的用法是在环境变量中找到包含"_TCP"的行,然后将从满足正则表达式".*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)"的环境变量中提取ip与端口号,并执行"socat TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&",其中:

  (1)/1表示环境变量名中指示端口号

  (2)/2表示ip地址

  (3)/3表示端口号

  这个环境变量这么命名的原因,是以为docker link的机制是将被link的container的ip、端口、协议等信息以环境变量的形式放到link中去。

  以Ambassador1为例,我们在启动Ambassador1后,可查看里面的环境变量:


  图2

  这里REDIS_PORT_6379_TCP=tcp://172.17.0.2:6379就是用于提取信息的环境变量,其中REDIS为Redis Server的在Ambassador1中的别名,是我们在link时制定的;6379为Redis Server开放的6379端口,用来提供Redis服务;172.17.0.2为Redis Server的ip地址。这样的话,Ambassador1就能知道Redis Server服务的ip和端口,就能够通过socat将redis访问请求转发给Redis Server。同理,我们就可建立Redis Client——Ambassador2——Ambassador1——Redis Server的连接。

  这种方式有一个缺点,就是在Ambassador2与Ambassador1建立连接的时候,Ambassador2必须要知道Ambassador1所在主机VM1的ip地址,从而硬编码设置环境变量REDIS_PORT_6379_TCP,这样灵活性就比较差,且当我们不知道VM1的ip地址时,这种方法是无法使用的。