docker 创建多网卡 docker 多台服务器_IP


一、概述

就目前Docker自身默认的网络来说,单台主机上的不同Docker容器可以借助docker0网桥直接通信,这没毛病,而不同主机上的Docker容器之间只能通过在主机上用映射端口的方法来进行通信,有时这种方式会很不方便,甚至达不到我们的要求,因此位于不同物理机上的Docker容器之间直接使用本身的IP地址进行通信很有必要。再者说,如果将Docker容器起在不同的物理主机上,我们不可避免的会遭遇到Docker容器的跨主机通信问题。

二、情景

如下图所示,我们有两个物理主机1和主机2,我们在各自宿主机上启动一个centos容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的IP地址分配如图所示,这也是Docker自身默认的网络。


docker 创建多网卡 docker 多台服务器_Docker_02


此时两台主机上的Docker容器如何直接通过IP地址进行通信?

一种直接想到的方案便是通过分别在各自主机中 添加路由

三、方案原理分析

由于使用容器的IP进行路由,就需要避免不同主机上的容器使用了相同的IP,为此我们应该为不同的主机分配不同的子网来保证。于是我们构造一下两个容器之间通信的路由方案,如下图所示。


docker 创建多网卡 docker 多台服务器_IP_03


各项配置如下:

  • 主机1的IP地址为:192.168.91.128
  • 主机2的IP地址为:192.168.91.129
  • 为主机1上的Docker容器分配的子网:10.0.128.0/24
  • 为主机2上的Docker容器分配的子网:10.0.129.0/24

这样配置之后,两个主机上的Docker容器就肯定不会使用相同的IP地址从而避免了IP冲突。

我们接下来 定义两条路由规则

  • 所有目的地址为10.0.128.0/24的包都被转发到主机1上
  • 所有目的地址为10.0.129.0/24的包都被转发到主机2上

综上所述,数据包在两个容器间的传递过程如下:

  • 从container1 发往 container2 的数据包,首先发往container1的“网关”docker0,然后通过查找主机1的路由得知需要将数据包发给主机2,数据包到达主机2后再转发给主机2的docker0,最后由其将数据包转到container2中;反向原理相同,不再赘述。

四、实际试验

操作系统服务器地址Dockerd地址ubuntu-16.04.5-server-amd64192.168.91.12810.0.128.2ubuntu-16.04.5-server-amd64192.168.91.12910.0.129.2

请确保已经安装好了docker,这里是使用以下命令安装的

修改docker0

1、第一种方案 :直接修改 /etc/default/docker 文件,添加 DOCKER_OPTS 参数即可

分别对主机1和主机2上的docker0进行配置

主机1

编辑主机1上的 /etc/default/docker 文件,最后一行添加


DOCKER_OPTS="--bip 10.0.128.1/24"


特别注意,DOCKER_OPTS参数后面必须有引号。--bip后面的ip就是docker0的ip地址,一般从第一个ip开始!

不要修改 /etc/docker/daemon.json 文件添加bip,我测试了一些,重启docker会报错!

主机2

编辑主机1上的 /etc/default/docker 文件,最后一行添加


DOCKER_OPTS="--bip 10.0.129.1/24"


2、第二种方案 :直接修改 /etc/docker/daemon.json下的文件(没有,则创建此文件)

主机1


{
    "bip": "10.0.128.1/24"
}


主机2


{
    "bip": "10.0.129.1/24"
}


重启docker服务

主机1和主机2上均执行如下命令重启docker服务以使修改后的docker0网段生效


systemctl restart docker


查看主机1上docker0的ip地址


root@ubuntu:~# ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:8a:46:e2:eb
          inet addr:10.0.128.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


查看主机2上docker0的ip地址


root@ubuntu:~# ifconfig docker0
docker0   Link encap:Ethernet  HWaddr 02:42:22:b1:25:66
          inet addr:10.0.129.1  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


发现默认的网段已经改变了!

添加路由规则

主机1

查看路由表


root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.91.2    0.0.0.0         UG    0      0        0 ens32
10.0.128.0      0.0.0.0         255.255.255.0   U     0      0        0 docker0192.168.91.0    0.0.0.0         255.255.255.0   U     0      0        0 ens32


默认只有自己本身的路由,如果需要访问 10.0.129.0/24 网段,需要添加路由

主机1上添加路由规则如下:


-- 临时路由
route add -net 10.0.129.0/24 gw 192.168.91.129
-- 永久路由,在/etc/rc.d/rc.local 文件下

vim /etc/rc.d/rc.local
#增量添加
route add -net 10.0.129.0/24 gw 192.168.91.129
# 保存
给文件赋权限
chmod +x /etc/rc.d/rc.local


gw 表示下一跳地址,这里的地址就是主机2的ip地址

再次查看路由,发现已经添加上了,重启也生效


root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.91.2    0.0.0.0         UG    0      0        0 ens32
10.0.128.0      0.0.0.0         255.255.255.0   U     0      0        0 docker0
10.0.129.0      192.168.91.129  255.255.255.0   UG    0      0        0 ens32
192.168.91.0    0.0.0.0         255.255.255.0   U     0      0        0 ens32


主机2

于上,同理,主机2上添加路由规则如下:


route add -net 10.0.128.0/24 gw 192.168.91.128


启动微服务应用

注意:对台服务器情况下,设置静态路由相对较为繁琐

解决方案为:

如果有10台host都需要这样配置的话,每台host上就要敲九条路由信息 如果批量部署的情况下是自寻死路,根本无法管理。所以我想到了使用“动态路由”来让主机与主机之间互相学习对方的网段。

Linux上安装路由器的软件名为Quagga,它可以配置很多种企业级的动态路由协议。我使用的是RIPV2和OSPF同时开启,但安装Quagga的方法和配置命令,太过于繁琐。所以我将Quagga Docker化了。

下载quagga路由器


docker pull index.alauda.cn/georce/router


启动路由器

首先请确定你的所有的docker0网桥不在同一个网段!!!

如:


VM1#ifconfig docker0 1.1.1.1/24
VM2#ifconfig docker0 2.2.2.2/24
VM1#docker run -itd --name=router --privileged --net=host index.alauda.cn/georce/router
VM2#docker run -itd --name=router --privileged --net=host index.alauda.cn/georce/router


就算过几分钟后你也看不出任何变化,但请你查看你的路由表。


VM1或VM2#route -n或者ip route


是不是出现了别的docker0的路由信息?请让容器1 ping下容器2,发现ping成功。

局域网里的Windows平台也直接访问容器1和容器2