16-多机器通信

16-多机器通信

回顾上节课的思考题。

在这里插入图片描述

flask-redis 想访问 redis,该如何通信?

创建另外一台linux虚拟机

  1. 直接拷贝Vagrantfile文件创建一个 centos 虚拟机

    我们创建一个centos7-2文件夹,然后创建虚拟机

    vagrant up
    

    创建的过程中提示选择网络接口,如果你是wifi选择类似wlp5s0的选项,如果是网线选择类似eth0。具体选择哪个,可以通过ip a查看哪一个接口被分配了实际ip地址则选择哪一个。

  2. 进入虚拟机

    vagrant ssh
    

    查看ip

    ip a
    

    看到 eth1 的地址为 192.168.2.78

  3. 查看之前的虚拟机ip是多少

    在打开一个终端窗口

    vagrant up
    vagrant ssh
    ip a
    

    我们看到 eth1 的地址为 192.168.2.32

    这时这两个ip是可以相互访问的,这个ip地址是由路由器分配的。

  4. 在centos7-2安装docker

    教程参照 docker 安装 这一节。

如何让两台主机中的docker通信

我们讲一下可以通信的过程

  1. 图中的 flask-redis 把要访问 redis 容器的源ip和目标ip以及数据打包存放在http层,也就是在ip层之上。
  2. 发送这个包到另外一台 redis 的主机上
  3. 然后这台主机解包,会得到目标ip是redis容器的ip,这时就会把携带的数据发送到这个redis容器中,返回的时候一样。

这个过程不需要详细了解,我们把这种通信方式叫 隧道(tunnel) ,具体在 docker中这种隧道是使用 VXLAN 实现的。关于 VXLAN 我们不做详细介绍。

想了解关于VXLAN详细信息,可以查看这篇文章 What is VXLAN and how it works?
也可以查看这篇文章 Understanding VXLANs

我们只简单讲一下 VXLAN 的数据包组成。

在这里插入图片描述

从这个 VXLAN 数据包组成可以看到,它在 UDP 上层又增加了 EthernetIPv4TCP,这里其实就是我们docker与docker之间要访问的数据包。而 VXLAN 把它打包在一个数据包内了,一般在网路领域我们把 VXLAN 下面的所有层叫做 underlay。上面的所有层叫 overlay

之前我们讲了docker有 bridge host none 网络,其他docker还有另外一种网络叫 overlay,就是和 VXLANJ技术有关。

通过overlay 我们就可以让分布在两台linux主机上的容器可以通信。那么实现这种方式需要一个第三方的工具,这个工具和分布式存储有关。

关于分布式存储工具有很多,这里我们使用一个开源免费的 etcd。那接下来我们就通过 etcd 来实现分布在两台linux主机上的容器通信。

安装etcd并配置

  1. 下载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  [email protected]:~
    

    第二太虚拟机同样把 etcd 安装包下载下来。

    如果不能scp 注意用户名是 vagrant,并且不需要加端口号,而且需要修改ssh配置,可以查看 0-安装Vagrant和使用 节。

  2. 解压运行

    第一台 虚拟机中执行

    解压

    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-amd64
    
    nohup ./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 &
    
  3. 检查状态

    在第一台虚拟机中执行下面命令,注意必须在 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连接配置

  1. 停止运行docker

    sudo service docker stop
    

    查看docker是否已经停止

    [vagrant@10 etcd-v3.3.12-linux-amd64]$ docker version
    Client:
     Version:           18.09.1
     API version:       1.39
     Go version:        go1.10.6
     Git commit:        4c52b90
     Built:             Wed Jan  9 19:35:01 2019
     OS/Arch:           linux/amd64
     Experimental:      false
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    

    如果只有client说明docker已经停掉

  2. 启动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.1
     API version:       1.39
     Go version:        go1.10.6
     Git commit:        4c52b90
     Built:             Wed Jan  9 19:35:01 2019
     OS/Arch:           linux/amd64
     Experimental:      false
    
    Server: Docker Engine - Community
     Engine:
      Version:          18.09.1
      API version:      1.39 (minimum version 1.12)
      Go version:       go1.10.6
      Git commit:       4c52b90
      Built:            Wed Jan  9 19:06:30 2019
      OS/Arch:          linux/amd64
      Experimental:     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

  1. 创建一个demo的overlay

    在第一台虚拟机中创建

    docker network create -d overlay demo
    

    -d 为选择driver

  2. 查看docker 网络

    查看第一台虚拟机

    $: docker network ls
    b048c448196c        demo                overlay             global
    

    查看第二台虚拟机

    $: docker network ls
    b048c448196c        demo                overlay             global
    

    这个demo的overlay已经成功创建了,这时连接到此网络上的容器就可以相互通信了。相互能够连接就是通过 etcd 实现的。

  3. 创建测试容器

    在第一台虚拟机中执行

    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"
    
  4. 查看两个容器是否连接到 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": ""
        }
    }
    

    我们可以看到 test1test2 已经连接到 demo 网络上了,根据之前的知识,我们可以了解到,test1test2 现在可以互相连接了。

  5. 测试容器互联

    进入 test1 容器,并ping test2

    docker exec -it test1 ping test2
    

    进入 test2 容器,并ping test1

    docker exec -it test1 ping test2
    

    是可以连接的。

到此我们就解决了分布在两台linux主机上的docker通信。解决的方式就是借助 分布式存储工具 etcd 和 docker 的overlay 网络。

发布了145 篇原创文章 · 获赞 357 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/wf19930209/article/details/87381399