Docker- 7.1、跨主机网络-macvlan

一、macvlan介绍

macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址而实现虚拟多块网卡,即多个 interface,每个 interface 可以配置自己的IP。macvlan 本质上是一种网卡虚拟化技术
macvlan 的最大优点是性能极好,相比其他实现,macvlan不需要创建Linux bridge,而是直接通过以太interface连接到物理网络。

二、准备实验环境

使用hosts1 和 hosts2上单独的网卡ens33 创建macvlan。
1、为保证多个 MAC 地址的网络包都可以从 ens33 通过,我们需要打开物理网卡的混杂模式:
ip link set ens33 promisc on
或者
ens33 开启混杂模式ifconfig ens33 promisc
ens33 关闭混杂模式ifconfig ens33 -promisc
2、macvlan 是 Linux 内核提供的一种网络驱动类型。如果内核没有加载 macvlan,可以通过命令加载:
   modprobe macvlan # 加载macvlan;可用于判断系统是否支持macvlan;若要卸载 macvlan:modprobe -r macvlan
   lsmod | grep macvlan # 确认是否已加载
如果第一个命令报错,或者第二个命令没有返回,说明当前系统不支持 macvlan,需要升级内核。

三、相同 macvlan 网络之间的通信

1、首先使用 docker network create 分别在两台主机上创建两个 macvlan 网络:
sudo docker network create --driver macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33  macvlan_10  # 为了简单设置的网络与宿主机的网络为同一网段
  • --driver:指定 Docker 网络 driver;
  • --subnet:macvlan网络是local网络,为了保证跨主机能够通信,用户需要自己管理 IP subnet;
  • --gateway 与其他网络不同,docker不会为macvlan 创建网关,这里的网关应该是真实存在的,否则容器无法路由
  • -o parent 指定用来分配 macvlan 网络的物理网卡
docker network ls查看创建的macvlan网络:
2、在两台宿主机上分别增加一个容器
由于node1中的macvlan_10与node2中的macvlan_10本质上是独立的,为了避免自动分配造成 IP 冲突,最好通过 --ip 指定地址。
node1上运行容器,指定IP为172.16.10.2:
node2上运行容器,指定IP为172.16.10.3:
1、macvlan是不依赖Linux bridge的,创建好macvlan网络之后,通过brctl show可以确认没有创建新的网桥。
2、docker 没有为 macvlan 提供 DNS 服务,这点与 overlay 网络是不同的。
3、容器内的eth0是由macvlan所在物理接口ens33创建的一个逻辑网口,解释如下:
容器内,除了lo,容器只有一个eth0,eth0后面有个if2,这说明该接口有个对应的interface,全局编号为2,而在主机上执行ip link可以看到,ens33的编号也是2:
4、容器直接使用宿主机的网卡,性能较好,这种方案使得容器无需通过NAT和端口映射就能与外网相通(只要有网关),在网络上与其他独立主机没有区别。
5、需要注意的是,通过MacVLAN创建的网络,docker容器内的IP是不能与parent的网卡互通的因为 macvlan 网络会独占物理网卡,即一张物理网卡只能创建一个 macvlan 网络,如果想创建多个 macvlan 网络就得用多张网卡,但主机的物理网卡是有限的,这个时候需要用到VLAN子接口的功能实现。

四、不同 macvlan 网络之间的通信

由于 macvlan 网络会独占物理网卡,也就是说 一张物理网卡只能创建一个 macvlan 网络,如果我们想创建多个 macvlan 网络就得用多张网卡,但主机的物理网卡是有限的,怎么办呢?
可以 通过 VLAN 技术将一个网口划分出多个子网口,这样就可以基于子网口来创建 macvlan 网络了。

下面是具体的创建过程
1、首先分别在两台主机上将物理网口 ens33创建出两个 VLAN 子接口。
# 使用 vconfig 命令在 ens33配置两个 VLAN
sudo vconfig add ens33 100  # 使用vconfig需要执行sudo apt install vlan
sudo vconfig add ens33 200
# 设置 VLAN REORDER_HDR 参数,默认就行了
sudo vconfig set_flag ens33.100 1 1    
sudo vconfig set_flag ens33.200 1 1
  
# 启用接口
sudo ifconfig ens33.100 up
sudo ifconfig ens33.200 up
ifconfig查看:
2、分别在 node1 和 node2 上基于两个 VLAN 子接口创建 2 个 macvlan 网络,mac100 和 mac200。
docker network create -d macvlan --subnet=172.16.100.0/24 --gateway=172.16.100.1 -o parent=ens33.100  mac100
docker network create -d macvlan --subnet=172.16.200.0/24 --gateway=172.16.200.1 -o parent=ens33.200  mac200
3、分别在 node1 和 node2 上运行容器,并指定不同的 macvlan 网络
node1
root@node1:~$ docker run -itd --name d1 --ip=172.16.100.10 --network mac100 busybox
root@node1:~$ docker run -itd --name d2 --ip=172.16.200.10 --network mac200 busybox
  
# node2
zhang@node2:~$ docker run -itd --name d3 --ip=172.16.100.11 --network mac100 busybox
zhang@node2:~$ docker run -itd --name d4 --ip=172.16.200.11 --network mac200 busybox
通过验证,d1 和 d3,d2 和 d4 在同一 macvlan 网络下,互相可以 ping 通,d1 和 d2,d1 和 d4 在不同的 macvlan 网络下,互相 ping 不通。
  
初始测试,d1与d3不通,d2和d4不通。
后将测试机器改为桥接模式:
d1可以ping通d3,但ping不通d2:
d2可以ping通d4:
这个原因也很明确,不同 macvlan 网络处于不同的网络,而且通过 VLAN 隔离,自然 ping 不了。
但这也只是在二层上通不了,通过三层的路由是可以通的,我们这就来验证下。
  
  
重新找一台主机node3,通过打开 ip_forward 把它改造成一台虚拟路由器,用来打通两个 macvlan 网络,大概的图示如下所示:
1 首先对 node3 执行 vi /etc/sysctl.d/99-sysctl.conf  net.ipv4.ip_forward=1   sysctl -p开路由开关。
2 然后创建两个 VLAN 子接口,一个作为 macvlan 网络 mac10 的网关,一个作为 mac20 的网关。
# 使用 vconfig 命令在 ens33配置两个 VLAN
[root@node3~]~$ vconfig add ens33 100
[root@node3 ~]~$ vconfig add ens33 200
# 设置 VLAN REORDER_HDR 参数,默认就行了
[root@node3 ~]~$ vconfig set_flag ens33.100 1 1  
[root@node3 ~]~$ vconfig set_flag ens33.200 1 1
  
# vlan 子接口配置网关 IP 并启用
[root@node3 ~]~$ ifconfig ens33.100 172.16.100.1 netmask 255.255.255.0 up
[root@node3 ~]~$ ifconfig ens33.200 172.16.200.1 netmask 255.255.255.0 up
3、此时,d1还是ping不通d4
4、node3上添加iptable规则,转发不同VLAN的数据。
iptables-save查看规则:
添加规则:
iptables -t nat -A POSTROUTING -o ens33.100 -j MASQUERADE
iptables -t nat -A POSTROUTING -o ens33.200 -j MASQUERADE
  
iptables -A FORWARD -i ens33.100 -o ens33.200 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i ens33.200 -o ens33.100 -m state --state RELATED,ESTABLISHED -j ACCEPT
  
iptables -A FORWARD -i ens33.100 -o ens33.200 -j ACCEPT
iptables -A FORWARD -i ens33.200 -o ens33.100 -j ACCEPT
再查看ipatbles规则:
5、此时,d1可以ping通d4,也可以ping通d2。
6、分析数据包是如何从d1(172.16.100.10)到达d4(172.16.200.11)
    1、因为d1与d4在不同的IP网段,根据d1的路由表:
    
    数据包将发往网关172.16.100.1.
    2、路由器从ens33.100收到数据包,发现目的地址是172.16.200.11,查看自己的路由表:
    
    于是将数据包从ens33.200转发出去。
    3、通过ARP记录的信息,路由器能够得知172.16.200.11在host2上,于是将数据包发往hosts2.
    
    4、hosts3根据目的地址和VLAN信息将数据包发往d4。
  

五、总结

macvlan 是一种网卡虚拟化技术,能够将一张网卡虚拟出多张网卡。
macvlan网络的连通与隔离完依赖VLAN、IP subnet和路由,docker本身不做任何限制,用户可以像管理传统VLAN网络那样管理macvlan。
macvlan 的四种通信模式,常用模式是 bridge。
在 Docker 中,macvlan 只支持 bridge 模式。
相同 macvlan 可以通信,不同 macvlan 二层无法通信,可以借助三层路由完成通信。

六、参考

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值