实现Docker的跨主机网络通讯的方案有不少,好比在以前博文中写到的经过部署consul服务实现Docker容器跨主机通讯 ,而这篇博文将Macvlan写下来docker
Macvlan工做原理:vim
- Macvlan是Linux内核支持的网络接口。要求的Linux内部版本是v3.9–3.19和4.0+;
- 经过为物理网卡建立Macvlan子接口,容许一块物理网卡拥有多个独立的MAC地址和IP地址。虚拟出来的子接口将直接暴露在相邻物理网络中。从外部看来,就像是把网线隔开多股,分别接受了不一样的主机上同样;
- 物理网卡收到包后,会根据收到包的目的MAC地址判断这个包须要交给其中虚拟网卡。
当容器须要直连入物理网络时,可使用Macvlan。Macvlan自己不建立网络,本质上首先使宿主机物理网卡工做在‘混杂模式’,这样物理网卡的MAC地址将会失效,全部二层网络中的流量物理网卡都能收到。接下来就是在这张物理网卡上建立虚拟网卡,并为虚拟网卡指定MAC地址,实现一卡多用,在物理网络看来,每张虚拟网卡都是一个单独的接口。centos
使用Macvlan有几点须要注意:服务器
- 容器直接链接物理网络,由物理网络负责分配IP地址,可能的结果是物理网络IP地址被耗尽,另外一个后果是网络性能问题,物理网络中接入的主机变多,广播包占比快速升高而引发的网络性能降低问题;
- 宿主机上的某张网上须要工做在‘混乱模式’下;
- 前面说到,工做在混乱模式下的物理网卡,其MAC地址会失效,因此,此模式中运行的容器并不能与外网进行通讯,可是不会影响宿主机与外网通讯;
- 从长远来看bridge网络与overlay网络是更好的选择,缘由就是虚拟网络应该与物理网络隔离而不是共享。
工做示意图以下:网络
实现效果:ide
- 两台centos 7.5,分别运行着docker服务;
- 两台docker服务器建立相同的一个MacVlan网络,使docker服务器上的容器能够实现跨主机通讯。
开始配置:
(1)第一台docker服务器配置以下:性能
[root@docker ~]# ip link set ens33 promisc on #开启ens33网卡的混杂模式。 #也就是开启网卡的多个虚拟interface(接口) [root@docker ~]# ip link show ens33 #肯定查看的信息包含如下标红的字样 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1 #建立macvlan网络,指定网段、网关等信息,“-o”指定绑定在哪张网卡之上 [root@docker ~]# docker run -tid --name box1 --ip 172.22.16.10 --network mac_net1 busybox #基于新建立的macvlan网络运行一个容器,并指定其IP。
确认运行的容器的IP地址:
(1)第二台docker服务器配置以下(与第一台docker服务器的配置基本类似):测试
[root@docker02 ~]# ip link set ens33 promisc on #开启ens33网卡的混杂模式。 [root@docker02 ~]# ip link show ens33 #肯定查看的信息包含如下标红的字样 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:c6:57:bc brd ff:ff:ff:ff:ff:ff [root@docker02 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway=172.22.16.1 -o parent=ens33 mac_net1 #建立一个与第一台docker服务器的网段、网关相同的macvlan。并绑定到物理网卡上。 #为了能够直观的看出其余docker服务器上的macvlan和第这台是在同一个网段的。 #因此,建议设置的网络名称同样。 [root@docker02 ~]# docker run -tid --name box2 --ip 172.22.16.11 --network mac_net1 busybox #运行一个容器,并指定是基于macvlan网络的 #注意,其IP地址不要与其余docker服务器上的容器IP地址冲突
确认运行的容器的IP地址:code
使用第二台docker服务器上的容器box2对第一台docker服务器上的容器box1进行ping测试:blog
OK,跨主机的容器通讯就经过macvlan实现了。因为使用混杂模式会形成物理网卡的MAC地址失效,因此容器并不能经过此模式进行与外网的通讯。
实现的效果以下:
- 两台centos 7.5,分别运行着docker服务;
- 每台宿主机建立了两个MacVlan网段供容器使用(172.10.16.0/24和172.20.16.0/24);
- 第一台docker服务器上运行容器bbox1和bbox2,第二台docker服务器运行容器bbox3和bbox4。
- 最终实现跨主机的同网段容器互相通讯。
开始配置:
(1)第一台docker服务器配置以下:
[root@docker ~]# ip link set ens33 promisc on #开启ens33网卡的混杂模式。 #也就是开启网卡的多个虚拟interface(接口) [root@docker ~]# ip link show ens33 #肯定查看的信息包含如下标红的字样 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker ~]# modinfo 8021q #查看是否加载8021q模块,若是有信息返回,则表示该模块已经加载
modinfo 8021q命令返回的信息以下:
[root@docker ~]# modprobe 8021q #若没有加载8021q模块,则执行此命令 [root@docker ~]# cd /etc/sysconfig/network-scripts/ [root@docker network-scripts]# vim ifcfg-ens33 #更改物理网卡配置 ...............#省略部份内容 BOOTPROTO=manual #将此配置项该为“manual”,也是手动的意思 ...............#省略部份内容 #更改完成后,保存退出便可 [root@docker network-scripts]# cp -p ifcfg-ens33 ifcfg-ens33.10 #将网卡配置文件复制一份 # “-p”表示保留文件本来的属性 [root@docker network-scripts]# vim ifcfg-ens33.10 #更改复制出来的配置文件以下 BOOTPROTO=none NAME=ens33.10 #注意更更名称 DEVICE=ens33.10 #注意更更名称 ONBOOT=yes IPADDR=192.168.10.10 #给虚拟网卡设置一个IP PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes #更改完成后,保存退出便可,注意,以上的IP与容器将要使用的IP并非同一网段 [root@docker network-scripts]# cp ifcfg-ens33.10 ifcfg-ens33.20 [root@docker network-scripts]# vim ifcfg-ens33.20 #编辑以下 BOOTPROTO=none NAME=ens33.20 #注意更更名称 DEVICE=ens33.20 #注意更更名称 ONBOOT=yes IPADDR=192.168.30.10 #注意,此处的IP与ens33.10并不在同一网段 PREFIX=24 GATEWAY=192.168.30.2 VLAN=yes #更改完成后,保存退出便可 [root@docker network-scripts]# ifdown ens33;ifup ens33 #重启网卡,使更改生效 [root@docker network-scripts]# ifup ens33.10 #开启ens33.10 [root@docker network-scripts]# ifup ens33.20 #开启ens33.20 [root@docker ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10 #建立一个macvlan网络,给其定义一个网段、网关及绑定到ens33.10 [root@docker ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20 #建立一个macvlan网络,给其定义一个网段、网关及绑定到ens33.20 #接下来分别基于刚刚建立的macvlan网络运行一个容器 [root@docker ~]# docker run -itd --name bbox1 --network mac_net10 --ip 172.10.16.10 busybox #基于网络mac_net10运行一个容器,并指定其IP [root@docker ~]# docker run -itd --name bbox2 --network mac_net20 --ip 172.20.16.20 busybox #基于网络mac_net10运行一个容器,并指定其IP
(2)第二台docker服务器配置以下(基本与第一台操做相似,只是要注意IP不要冲突):
[root@docker02 ~]# ip link set ens33 promisc on #开启ens33网卡的混杂模式。 #也就是开启网卡的多个虚拟interface(接口) [root@docker02 ~]# ip link show ens33 #肯定查看的信息包含如下标红的字样 2: ens33: <BROADCAST,MULTICAST,'PROMISC',UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:2f:89:cb brd ff:ff:ff:ff:ff:ff [root@docker02 ~]# modinfo 8021q #查看是否加载8021q模块,若是有信息返回,则表示该模块已经加载
modinfo 8021q命令返回的信息以下:
[root@docker02 ~]# modprobe 8021q #若没有加载8021q模块,则执行此命令 [root@docker02 ~]# cd /etc/sysconfig/network-scripts/ [root@docker02 network-scripts]# vim ifcfg-ens33 #更改物理网卡配置 ...............#省略部份内容 BOOTPROTO=manual #将此配置项该为“manual”,也是手动的意思 ...............#省略部份内容 #更改完成后,保存退出便可 [root@docker02 network-scripts]# scp root@192.168.20.7:/etc/sysconfig/network-scripts/ifcfg-ens33.* . #将第一台docker服务器上的虚拟网卡配置文件复制过来 root@192.168.20.7 s password: #输入第一台docker服务器的用户密码 ifcfg-ens33.10 100% 117 0.1KB/s 00:00 ifcfg-ens33.20 100% 117 0.1KB/s 00:00 [root@docker02 network-scripts]# vim ifcfg-ens33.10 #只是更改其IP便可 BOOTPROTO=none NAME=ens33.10 DEVICE=ens33.10 ONBOOT=yes IPADDR=192.168.10.11 #更改IP是为了避免要和第一台docker服务器的虚接口IP冲突 PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes [root@docker02 network-scripts]# vim ifcfg-ens33.20 #同上 BOOTPROTO=none NAME=ens33.20 DEVICE=ens33.20 ONBOOT=yes IPADDR=192.168.30.11 #更改其IP地址 PREFIX=24 GATEWAY=192.168.30.2 VLAN=yes [root@docker02 network-scripts]# ifdown ens33;ifup ens33 #重启网卡,使更改生效 [root@docker02 network-scripts]# ifup ens33.10 #启动ens33.10 [root@docker02 network-scripts]# ifup ens33.20 #启动ens33.20 #接下来建立macvlan网络,与第一台docker服务器建立的网络同样 [root@docker02 ~]# docker network create -d macvlan --subnet 172.10.16.0/24 --gateway 172.10.16.1 -o parent=ens33.10 mac_net10 [root@docker02 ~]# docker network create -d macvlan --subnet 172.20.16.0/24 --gateway 172.20.16.1 -o parent=ens33.20 mac_net20 #接下来基于刚刚建立的网络运行两个容器 #基于mac_net10运行容器bbox3 [root@docker02 ~]# docker run -tid --name bbox3 --network mac_net10 --ip 172.10.16.11 busybox #基于mac_net20运行容器bbox4 [root@docker02 ~]# docker run -itd --name bbox4 --network mac_net20 --ip 172.20.16.21 busybox
配置至此,便可进行ping测试了,若是配置无误,则bbox3应该和bbox1互通(由于其都是基于mac_net1010网络);bbox4应该和bbox2互通(同理)。
但bbox3和bbox1不能和bbox4和bbox2互通(由于其不是基于同一个虚拟局域网)。
容器bbox3 ping 容器bbox1测试(注意:如果使用vmware虚拟机进行测试,因为vmware的特性,需将其网络适配器改成“桥接模式”,而不是NAT模式等。不然没法通讯):
容器bbox4 ping 容器bbox2测试:
至此,跨主机网络多网段已经实现,一样,各个容器没法与外网进行通讯。
docker网络是一个比较复杂的概念,如有耐心,仍是建议阅读docker官方文档
———————— 本文至此结束,感谢阅读 ————————