Docker跨主机网络(manual)的实现
1.Macvlan简介
在Macvlan出现之前,我们只能为一块以太网卡添加多个IP地址,却不能添加多个MAC地址,因为MAC地址正是通过其全球唯一性来标识一块以太网卡的,即便你使用了创建ethx:y这样的方式,你会发现所有这些“网卡”的MAC地址和ethx都是一样的,本质上,它们还是一块网卡,这将限制你做很多二层的操作。有了Macvlan技术,你可以这么做了。
Macvlan允许你在主机的一个网络接口上配置多个虚拟的网络接口,这些网络interface有自己独立的MAC地址,也可以配置上IP地址进行通信。Macvlan下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。Macvlan和Bridge比较相似,但因为它省去了Bridge的存在,所以配置和调试起来比较简单,而且效率也相对高。除此之外,Macvlan自身也完美支持VLAN。
同一VLAN间数据传输是通过二层互访,即MAC地址实现的,不需要使用路由。不同VLAN的用户单播默认不能直接通信,如果想要通信,还需要三层设备做路由,Macvlan也是如此。用Macvlan技术虚拟出来的虚拟网卡,在逻辑上和物理网卡是对等的。物理网卡也就相当于一个交换机,记录着对应的虚拟网卡和MAC地址,当物理网卡收到数据包后,会根据目的MAC地址判断这个包属于哪一个虚拟网卡。这也就意味着,只要是从Macvlan子接口发来的数据包(或者是发往Macvlan子接口的数据包),物理网卡只接收数据包,不处理数据包,所以这就引出了一个问题:本机Macvlan网卡上面的IP无法和物理网卡上面的IP通信!关于这个问题的解决方案我们下一节再讨论。
简单来说,Macvlan虚拟网卡设备是寄生在物理网卡设备上的。发包时调用自己的发包函数,查找到寄生的物理设备,然后通过物理设备发包。收包时,通过注册寄生的物理设备的rx_handler回调函数,处理数据包。
2.简单介绍manual的流程
macvlan就如它的名字一样,是一种网卡虚拟化技术,它能够将一个物理网卡虚拟出多个接口,每个接口都可以配置MAC地址,同样每个接口也可以配自己的IP,每个接口就像交换机的端口一样,可以为它划分VLAN。
macvlan的做法其实就是将这些虚拟出来的接口与Docker容器直连来达到通信的目的。一个macvlan网络对应一个接口,不同的macvlan网络分配不同的子网,因此,相同的macvlan之间可以互相通信,不同的macvlan网络之间在二层上不能通信,需要借助三层的路由器才能完成通信,如下,显示的就是两个不同的macvlan网络之间的通信流程。
我们用一个Linux主机,通过配置其路由表和iptables,将其配成一个路由器(当然是虚拟的),就可以完成不同macvlan网络之间的数据交换,当然用物理路由器也是没毛病的。
3.Macvlan的特点:
1.可让使用者在同一张实体网卡上设定多个MAC地址。
2.承上,带有上述设定的MAC地址的网卡称为子接口(subinterface);而实体网卡则称为父接口(parentinterface)。
3.parentinterface可以是一个物理接口(eth0),可以是一个802.1q的子接口(eth0.10),也可以是bonding接口。
4.可在parent/subinterface上设定的不只是MAC地址,IP地址同样也可以被设定。
5.subinterface无法直接与parentinterface通讯(带有subinterface的VM或容器无法与host直接通讯)。
承上,若VM或容器需要与host通讯,那就必须额外建立一个sub6.interface给host用。
7.subinterface通常以mac0@eth0的形式来命名以方便区別。
用张图来解释一下设定Macvlan后的样子:
4.实验环境
docker01 | docker02 |
---|---|
192.168.1.11 | 192.168.1.13 |
关闭防火墙和禁用selinux,更改主机名
[root@localhost~]#hostnamectlset-hostnamedocker01 [root@localhost~]#su- 上一次登录:二12月1708:20:36CST2019从192.168.1.1pts/0上 [root@docker01~]#systemctlstopfirealld Failedtostopfirealld.service:Unitfirealld.servicenotloaded. [root@docker01~]#setenforce0 setenforce:SELinuxisdisabled [root@docker01~]#systemctldaemon-reload [root@docker01~]#systemctlrestartdocker 4.1macvlan的单网络通信
4.1macvlan的单网络通信
//需要在docker01和docker02_上都进行操作。 [root@docker01~]#iplinkshowens33 //查看网卡模式
[root@docker01~]#iplinksetens33promiscon //创建网卡模式为混杂模式 [root@docker01~]#iplinkshowens33 //查看网卡模式
2)在docker01.上创建macvlan网络
[root@docker01~]#dockernetworkcreate-dmacvlan--subnet172.22.16.0/24--gateway172.22.16.1-oparent=ens33mac_net1 //创建一个macvlan模式的网络 -oparent=绑定在哪张网卡之上 [root@docker01~]#dockernetworkls //查看网卡信息
3)基于创建的macvlan网络运行一个容器
[root@docker01~]#dockerrun-itd--namebbox1--ip172.22.16.10--networkmac_net1busybox
4)在docker02.上创建macvlan网络(要和docker01的macvlan一模一样)
[root@docker02~]#dockernetworkcreate-dmacvlan--subnet172.22.16.0/24--gateway172.22.16.1-oparent=ens33mac_net1 [root@docker02~]#dockernetworkls
5)在docker02.上,基于创建的macvlan网络运行一个容器,验证与docker01.上容器的通信。
[root@docker02~]#dockerrun-itd--namebbox2--networkmac_net1--ip172.22.16.20busybox //基于busybox创建一个容器 [root@docker02~]#dockerexec-itbbox2/bin/sh //进入bbox2容器 /#ping172.22.16.10 //ping一下docker01的主机
4.2macvlan的多网络通信
1)docker01和docker02验证内核模块8021q封装
macvlan需要解决的问题:基于真实的ens33网卡,生产新的虚拟网卡。
[root@docker01~]#modinfo8021q //验证内核模块8021q封装
[root@docker01~]#modprobe8021q //如果内核模块没有开启,运行上边的命令导入一下
2)docker01基于ens33创建虚拟网卡
修改ens33网卡配置文件
[root@docker01~]#cd/etc/sysconfig/network-scripts/ [root@docker01network-scripts]#vimifcfg-ens33
[root@docker01~]#cd/etc/sysconfig/network-scripts/ [root@docker01network-scripts]#cp-pifcfg-ens33ifcfg-ens33.10 //-p保留源文件或目录的属性 [root@docker01network-scripts]#vimifcfg-ens33.10 //修改ens33.10网卡配置文件 BOOTPROTO=none NAME=ens33.10 DEVICE=ens33.10 ONBOOT=yes IPADDR=192.168.10.10 PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes
这里注意,IP要和ens33网段做一个区分,保证网关和网段IP的一致性,设备名称和配置文件的-致性,并且打开VLAN支持模式。
创建第二个虚拟网卡配置文件
[root@docker01network-scripts]#cp-pifcfg-ens33.10ifcfg-ens33.20 [root@docker01network-scripts]#vimifcfg-ens33.20 //修改ens33.20网卡配置文件 BOOTPROTO=none NAME=ens33.20 DEVICE=ens33.20 ONBOOT=yes IPADDR=192.168.20.20 PREFIX=24 GATEWAY=192.168.20.2 VLAN=yes
docker01上的操作,启用创建的虚拟网卡:
[root@docker01network-scripts]#ifupifcfg-ens33.10 [root@docker01network-scripts]#ifupifcfg-ens33.20 [root@docker01network-scripts]#ifconfig //查看IP
3)docker02基于ens33创建虚拟网卡
修改ens33网卡配置文件
[root@docker02~]#cd/etc/sysconfig/network-scripts/ [root@docker02network-scripts]#vimifcfg-ens33
[root@docker02~]#cd/etc/sysconfig/network-scripts/ [root@docker02network-scripts]#cp-pifcfg-ens33ifcfg-ens33.10 //-p保留源文件或目录的属性 [root@docker02network-scripts]#vimifcfg-ens33.10 //修改ens33.10网卡配置文件 BOOTPROTO=none NAME=ens33.10 DEVICE=ens33.10 ONBOOT=yes IPADDR=192.168.10.11 PREFIX=24 GATEWAY=192.168.10.2 VLAN=yes
这里注意,IP要和ens33网段做一个区分,保证网关和网段IP的一致性,设备名称和配置文件的-致性,并且打开VLAN支持模式。
创建第二个虚拟网卡配置文件
[root@docker02network-scripts]#cp-pifcfg-ens33.10ifcfg-ens33.20 [root@docker02network-scripts]#vimifcfg-ens33.20 //修改ens33.20网卡配置文件 BOOTPROTO=none NAME=ens33.20 DEVICE=ens33.20 ONBOOT=yes IPADDR=192.168.20.21 PREFIX=24 GATEWAY=192.168.20.2 VLAN=yes
docker02上的操作,启用创建的虚拟网卡:
[root@docker02network-scripts]#systemctlrestartnetwork [root@docker02network-scripts]#ifupifcfg-ens33.10 [root@docker02network-scripts]#ifupifcfg-ens33.20 [root@docker02network-scripts]#ifconfig //查看IP
[root@docker02network-scripts]#dockernetworkcreate-dmacvlan--subnet172.16.10.0/24--gateway172.16.10.1-oparent=ens33.10mac_net10 //创建一个新的网卡基于ens33.10 [root@docker02network-scripts]#dockernetworkcreate-dmacvlan--subnet172.16.20.0/24--gateway172.16.20.1-oparent=ens33.20mac_net20 //创建一个新的网卡基于ens33.20
5)Docker01部署一个私有仓库
Docker01
dockerpullregistry //下载registry镜像 dockerrun-itd--nameregistry-p5000:5000--restart=alwaysregistry:latest //基于registry镜像,启动一台容器 dockertagbusybox:latest192.168.1.11:5000/busybox:v1 //把容器重命名一个标签 dockerps
vim/usr/lib/systemd/system/docker.service#13行修改 ExecStart=/usr/bin/dockerd--insecure-registry192.168.1.11:5000 systemctldaemon-reload systemctlrestartdocker.service //重启docker dockerpush192.168.1.11:5000/busybox:v1 //上传容器到私有仓库 dockerimages
Docker02
vim/usr/lib/systemd/system/docker.service#13行修改 ExecStart=/usr/bin/dockerd--insecure-registry192.168.1.11:5000 systemctldaemon-reload systemctlrestartdocker.service //重启docker dockerpull192.168.1.11/busybox:v1 //下载刚刚上传的镜像
6)docker01和docker02基于busybox:v1镜像和网卡mac_net10,mac_net20,创建容器。
Docker01
[root@docker01~]#dockerrun-itd--namebbox10--networkmac_net10--ip172.16.10.10192.168.1.11:5000/busybox:v1 [root@docker01~]#dockerrun-itd--namebbox20--networkmac_net20--ip172.16.20.20192.168.1.11:5000/busybox:v1 **Docker02**
[root@docker02~]#dockerrun-itd--namebbox10--networkmac_net10--ip172.16.10.10192.168.1.11:5000/busybox:v1 [root@docker02~]#dockerrun-itd--namebbox20--networkmac_net20--ip172.16.20.20192.168.1.11:5000/busybox:v1
***这里只需注意,我们在这里的操作跟在docker01和上面的操作是一模一样的,操作顺序大致为:
验证8021q内核封装
基于ens33网卡创建新的虚拟网卡,ens33.10和ens33.20(注意和docker01.上的ens33.10和ens33.20必须是在同一-网段,且IP不能冲突)基于此网络运行容器。(注意和docker01上的容器,都是基于刚刚创建的macvlan网络,但IP地址不能冲突)
7)验证
在docker01.上进入容器bbox10和docker02.上的bbox11进行通信。
在docker01.上进入容器bbox20和docker02.上的bbox21进行通信。
注意:VMware的网络必须设置为Bridge模式。
现在把docker01和docker02的网络模式设置为桥接模式
[root@docker01~]#dockerexec-itbbox10/bin/sh /#ping172.16.20.20
[root@docker02~]#dockerexec-itbbox20/bin/sh /#ping172.16.20.20
5.Macvlan的局限性
Macvlan是将VM或容器通过二层连接到物理网络的近乎理想的方案,但它也有一些局限性:
1.Linux主机连接的交换机可能会限制同一个物理端口上的MAC地址数量。虽然你可以让网络管理员更改这些策略,但有时这种方法是无法实行的(比如你要去给客户做一个快速的PoC演示)。
2.许多NIC也会对该物理网卡上的MAC地址数量有限制。超过这个限制就会影响到系统的性能。
3.IEEE802.11不喜欢同一个客户端上有多个MAC地址,这意味着你的Macvlan子接口在无线网卡或AP中都无法通信。可以通过复杂的办法来突破这种限制,但还有一种更简单的办法,那就是使用Ipvlan,感兴趣可以自己查阅相关资料。
6.总结
macvlan是一种网卡虚拟化技术,能够将一张网卡虚拟出多张网卡。
macvlan的特定通信模式,常用模式是bridge。
在Docker中,macvlan只支持bridge模式。
相同的macvlan可以通信,不同的macvlan二层无法通信,可以通过三层路由完成通信。
思考一下:
macvlanbridge和bridge的异同点
还有一种类似的技术,多张虚拟网卡共享相同MAC地址,但有独立的IP地址,这是什么技术?
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。