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 網絡。