Docker容器技术:多机器通信

1,289 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

之前的redis和flask容器相当于是同一个机器里面的,但是如果此时这两个容器是在两台机器里面,无法通过docker-bridge直接通信,应该如何解决呢?

两台Linux机器,两个docker0,跨机器多容器如何通信?

这里有一个前提就是redis和flask的IP地址一定是不一样的,如果一样是没办法通信的。

5.1 概述

这里有两台Linux机器,一个是10,一个是11,现在这两台机器是可以ping通的。

从redis机器出去的数据包会包括src的IP地址:205.10,dist的IP地址:205.11。而现在其实是需要从172.17.0.2 去ping 172.17.0.3。

redis的数据包到网卡的时候其实是没办法出去的,因为src和dist是不能直接通信的,如果要通信就需要把来自172.17.0.2的数据包整个放到eth0出去的数据包的数据中,然后跟着到192.168.205.11,然后另一边取数据,这里就读到一个dist是172.17.0.3的数据,然后他知道这个IP是flask-redis容器,就可以把这个数据包转发过去。

回去的也是类似的。

这个具体概念叫channel--隧道,具体可以看docker的多机通信,底层原理是VXLAN:

image.png

VXLAN的数据包组成是有讲究的,docker容器的数据包是在UDP层的。

5.2 underlay和overlay

上述图片里面最底层的Ethernet,IPv4,UDP(VXLAN左边的)称之为underlay,右边对应的overlay。

这里具体的可以去网上了解VXLAN的概念和细节。

5.3 实验环境

看一下实验环境,之前我们通过vagarant创建了两台docker-host:

都有各自的IP地址,我们可以分别进入虚拟机看一下:

这两个host是可以互相ping通:

也就是说之前VXLAN里面的underlay是可以ping通。

5.4 实验进行(overlay网络)

这里根据之前的原理概述,我们尝试创建docker的overlay网络来进行多机通信。

这里我们需要依赖一个第三方的分布式存储,因为我们首先在第一台机器里面创建了一个容器,这时候会分配一个IP地址,例如:172.17.0.2,但是另一个机器里面创建的容器的IP是不能重复的,他怎么知道这个不能重复的IP地址是什么呢?所以这里需要一个存储的数据表来让他知道0.2被用过了。

这里我们用开源的分布式存储etcd:

image.png

安装etcd

首先我们需要在两个docker-host上面安装etcd的cluster,具体的步骤如下:

安装好了之后我们需要启动一个etcd的进程,两个机器都要启动,然后我们进入docker-node1中来运行:

这里集群时候我们会把node1和2的IP都放进去,同样node2也执行:(参数不一样)

接着我们尝试运行-在etcd文件夹里面执行:

./etcdctl cluster-health

另外一个机器执行这个命令应该也都是一样的,这样我们就搭建了一个分布式存储,两边的IP数据都存进去了

重启两个docker服务

接着我们需要把本地的docker停掉:

目的是让docker知道我们要去使用etcd,然后手动启动docker,执行:

sudo /user/bin/dockerd -H tcp://0.0.0.0:2375 ...

然后此时docker就会在后台运行(自定义了一些cluster参数)

这里其实双方都知道对方的存在了~

overlay-network的创建

通过之前类似创建bridge的命令来创建overlay网络,只不过-d会选择overlay这种driver:

sudo docker network create -d overlay demo

此时多了一个demo的network,这里我们可能感觉还需要去node2执行这个,但其实node2里面已经有这个网络了:

其实这里就是通过etcd完成了同步工作,我们看一下其实etcd已经存储了对应的信息:

overlay上创建容器

我们可以通过inpsect命令看一下这个overlay网络:

包括IP地址的范围,container目前为空。

然后我们利用busybox来创建一个使用该网络的容器:

sudo docker run -d --name test1 --net demo busybox sh -c ...

然后我们去node2上面也创建一个name为test1的容器时候会发现报错了:

也就是说node1上面创建的容器已经被用过了,因为已经被存到过etcd里面了,所以node2创建会去查找,发现已经创建过了,这里我们命名为test2就可以了。

基于overlay的访问

这里我们分别看一下两者的IP地址:

node2的容器:

node1的容器:

然后看一下overlay这个network:

两者虽然分在两个机器里面,但是现在已经可以ping通了:

这里就实现了不同机器的容器通信。

这里还推荐多了解一些Docker的网络,例如这里其实除了demo这个overlay之外,还会创建了一个新的bridge:

其实这里单个容器有两个端口,一个是对外通信的,另一个是走overlay隧道的,可以看官方文档