16-多机器通信
回顾上节课的思考题。
flask-redis 想访问 redis,该如何通信?
创建另外一台linux虚拟机
-
直接拷贝Vagrantfile文件创建一个 centos 虚拟机
我们创建一个centos7-2文件夹,然后创建虚拟机
vagrant up
创建的过程中提示选择网络接口,如果你是wifi选择类似wlp5s0的选项,如果是网线选择类似eth0。具体选择哪个,可以通过
ip a
查看哪一个接口被分配了实际ip地址则选择哪一个。 -
进入虚拟机
vagrant ssh
查看ip
ip a
看到 eth1 的地址为 192.168.2.78。
-
查看之前的虚拟机ip是多少
在打开一个终端窗口
vagrant up vagrant ssh ip a
我们看到 eth1 的地址为 192.168.2.32。
这时这两个ip是可以相互访问的,这个ip地址是由路由器分配的。
-
在centos7-2安装docker
教程参照 docker 安装 这一节。
如何让两台主机中的docker通信
我们讲一下可以通信的过程
- 图中的 flask-redis 把要访问 redis 容器的源ip和目标ip以及数据打包存放在http层,也就是在ip层之上。
- 发送这个包到另外一台 redis 的主机上
- 然后这台主机解包,会得到目标ip是redis容器的ip,这时就会把携带的数据发送到这个redis容器中,返回的时候一样。
这个过程不需要详细了解,我们把这种通信方式叫 隧道(tunnel) ,具体在 docker中这种隧道是使用 VXLAN 实现的。关于 VXLAN 我们不做详细介绍。
想了解关于VXLAN详细信息,可以查看这篇文章 What is VXLAN and how it works?
也可以查看这篇文章 Understanding VXLANs
我们只简单讲一下 VXLAN 的数据包组成。
从这个 VXLAN 数据包组成可以看到,它在 UDP 上层又增加了 Ethernet,IPv4, TCP,这里其实就是我们docker与docker之间要访问的数据包。而 VXLAN 把它打包在一个数据包内了,一般在网路领域我们把 VXLAN 下面的所有层叫做 underlay。上面的所有层叫 overlay。
之前我们讲了docker有 bridge host none 网络,其他docker还有另外一种网络叫 overlay,就是和 VXLANJ技术有关。
通过overlay 我们就可以让分布在两台linux主机上的容器可以通信。那么实现这种方式需要一个第三方的工具,这个工具和分布式存储有关。
关于分布式存储工具有很多,这里我们使用一个开源免费的 etcd。那接下来我们就通过 etcd 来实现分布在两台linux主机上的容器通信。
安装etcd并配置
-
下载etcd
sudo yum install wget wget https://github.com/etcd-io/etcd/releases/download/v3.3.12/etcd-v3.3.12-linux-amd64.tar.gz
下载地址查看。
如果下载太慢,我们可以在主机中先下载好,然后通过scp发送到虚拟机中。
scp etcd-v3.3.12-linux-amd64.tar.gz vagrant@192.168.2.32:~
第二太虚拟机同样把 etcd 安装包下载下来。
如果不能scp 注意用户名是 vagrant,并且不需要加端口号,而且需要修改ssh配置,可以查看
0-安装Vagrant和使用
节。 -
解压运行
第一台 虚拟机中执行
解压
tar zxvf etcd-v3.3.12-linux-amd64.tar.gz
运行
cd etcd-v3.3.12-linux-amd64 nohup ./etcd --name docker-node1 --initial-advertise-peer-urls \ http://192.168.2.32:2380 \ --listen-peer-urls http://192.168.2.32:2380 \ --listen-client-urls http://192.168.2.32:2379,http://127.0.0.1:2379 \ --advertise-client-urls http://192.168.2.32:2379 \ --initial-cluster-token etcd-cluster \ --initial-cluster docker-node1=http://192.168.2.32:2380,docker-node2=http://192.168.2.78:2380 \ --initial-cluster-state new &
192.168.2.32 为第一台虚拟机的ip地址,192.168.2.78 为第二台虚拟机的ip地址。
nohup 命令可以让命令在后台运行,并且关闭终端也不会终止进程,而 & 会。
第二台 虚拟机中执行
解压
tar zxvf etcd-v3.3.12-linux-amd64.tar.gz
运行
cd etcd-v3.3.12-linux-amd64nohup ./etcd --name docker-node2 --initial-advertise-peer-urls \ http://192.168.2.78:2380 \ --listen-peer-urls http://192.168.2.78:2380 \ --listen-client-urls http://192.168.2.78:2379,http://127.0.0.1:2379 \ --advertise-client-urls http://192.168.2.78:2379 \ --initial-cluster-token etcd-cluster \ --initial-cluster docker-node1=http://192.168.2.32:2380,docker-node2=http://192.168.2.78:2380 \ --initial-cluster-state new &
-
检查状态
在第一台虚拟机中执行下面命令,注意必须在
etcd-v3.3.12-linux-amd64
文件夹下执行,否则找不到命令。[vagrant@10 etcd-v3.3.12-linux-amd64]$ ./etcdctl cluster-health member a639ee0bdcf9ca8c is healthy: got healthy result from http://192.168.2.78:2379 member e8b07a1a0cffdc97 is healthy: got healthy result from http://192.168.2.32:2379 cluster is healthy
再到第二台虚拟机中执行一次
[vagrant@10 etcd-v3.3.12-linux-amd64]$ ./etcdctl cluster-health member a639ee0bdcf9ca8c is healthy: got healthy result from http://192.168.2.78:2379 member e8b07a1a0cffdc97 is healthy: got healthy result from http://192.168.2.32:2379 cluster is healthy
我们可以看到 etcd 运行正常,这时我们就搭建好了 分部署存储的 etcd 服务。
docker与etcd连接配置
-
停止运行docker
sudo service docker stop
查看docker是否已经停止
[vagrant@10 etcd-v3.3.12-linux-amd64]$ docker version Client:Version: 18.09.1API version: 1.39Go version: go1.10.6Git commit: 4c52b90Built: Wed Jan 9 19:35:01 2019OS/Arch: linux/amd64Experimental: false Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
如果只有client说明docker已经停掉
-
启动docker的cluster
第一台虚拟机中执行
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.2.32:2379 --cluster-advertise=192.168.2.32:2375 &
查看dockerd是否启动了
docker version
Client:Version: 18.09.1API version: 1.39Go version: go1.10.6Git commit: 4c52b90Built: Wed Jan 9 19:35:01 2019OS/Arch: linux/amd64Experimental: falseServer: Docker Engine - CommunityEngine:Version: 18.09.1API version: 1.39 (minimum version 1.12)Go version: go1.10.6Git commit: 4c52b90Built: Wed Jan 9 19:06:30 2019OS/Arch: linux/amd64Experimental: false
我们可以看到server已经启动,说明工作正常。
第二台虚拟机中停止docker执行
sudo service docker stop sudo dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --cluster-store=etcd://192.168.2.78:2379 --cluster-advertise=192.168.2.78:2375 &
注意参数修改为这台虚拟机的ip地址
查看 docker 是否启动
docker version
可以看到server已经起来了。
创建docker overlay
-
创建一个demo的overlay
在第一台虚拟机中创建
docker network create -d overlay demo
-d 为选择driver
-
查看docker 网络
查看第一台虚拟机
$: docker network ls b048c448196c demo overlay global
查看第二台虚拟机
$: docker network ls b048c448196c demo overlay global
这个demo的overlay已经成功创建了,这时连接到此网络上的容器就可以相互通信了。相互能够连接就是通过 etcd 实现的。
-
创建测试容器
在第一台虚拟机中执行
docker run -d --name test1 --net demo busybox /bin/sh -c "while true; do sleep 3600; done"
在第二台虚拟机中执行
docker run -d --name test1 --net demo busybox /bin/sh -c "while true; do sleep 3600; done"
这时会报错,这是因为 test1 会被当做 key 存储在 etcd 中,创建的时候 etcd 会发现有两个相同的key,不允许创建。那么我们更改名字为 test2
docker run -d --name test2 --net demo busybox /bin/sh -c "while true; do sleep 3600; done"
-
查看两个容器是否连接到 demo的overlay网络上
docker network inspect demo
"Containers": {"214e805562087e57aa643bd855237ea30282afee1c86e14f357838c553558fe8": {"Name": "test1","EndpointID": "79c482ff74e03eca583f2534555d4c2dd257087b4b266557e381932712b2c438","MacAddress": "02:42:0a:00:00:02","IPv4Address": "10.0.0.2/24","IPv6Address": ""},"ep-796a17e471b63ef8af64ff4d67a5dd63be731708e3c57f1cdbd072ea5acd0c76": {"Name": "test2","EndpointID": "796a17e471b63ef8af64ff4d67a5dd63be731708e3c57f1cdbd072ea5acd0c76","MacAddress": "02:42:0a:00:00:03","IPv4Address": "10.0.0.3/24","IPv6Address": ""} }
我们可以看到 test1 和 test2 已经连接到 demo 网络上了,根据之前的知识,我们可以了解到,test1 和 test2 现在可以互相连接了。
-
测试容器互联
进入 test1 容器,并ping test2
docker exec -it test1 ping test2
进入 test2 容器,并ping test1
docker exec -it test1 ping test2
是可以连接的。
到此我们就解决了分布在两台linux主机上的docker通信。解决的方式就是借助 分布式存储工具 etcd 和 docker 的overlay 网络。