介绍:

MacVLAN是一种linux虚拟化网卡技术。MacVLAN允许用户在主机的一个物理网卡上配置多个虚拟网卡,每个MacVLAN接口都有自己的区别于父接口的mac地址,并且可以像普通网络接口一样分配IP地址。这些虚拟网卡逻辑上和物理网卡对等的。

补充:网卡别名方式也可以实现一块网卡配置多个ip,但其mac地址都是相同的,无法做到不同。

模式:

bridge、VEPA、Private、Passthru和Source 5种模式。

bridge模式

类似linux bridge。bridge模式下,拥有相同父接口的MacVLAN虚拟网卡可直接通信,流量不需要发往外部网络,广播帧将会被泛洪到子接口和物理接口。

不同的是,MacVLAN的bridge模式不需要学习mac地址,也不需要STP协议。

VEPA模式,Virtual Ethernet Port Aggregator,虚拟以太网端口聚合

默认模式。所有从MacVLAN子接口发出的流量,不管目的地址是什么,全都发送给父接口,即使流量的目的地是共享同一个父接口的其他MacVLAN子接口。

在二层网络下,由于生成树协议的原因,两个MacVLAN接口之间的通信会被阻塞,这时就需要接入的外部交换机支持hairpin,把源和目的地址都是本地MacVLAN子接口地址的流量,发给相应的接口。在VEPA模式下,从父接口收到的广播包会洪泛给所有的子接口。

目前大多数交换机都不支持hairpin模式,但Linux网桥支持开启,可让VEPA模式下的MacVLAN接口能直接通信。配置如下:

# 配置Linux网桥br0开启hairpin,使得从eth0收到包后再从eth0发回去
brctl hairpin br0 eth0 on

配置hairpin后,源、目地址都是本地Macvlan接口地址的流量,会被Linux网桥发回给相应的接口。

补充:hairpin主要是将数据包从一个接口上收上来之后再扔回去,多用于网关设备。

Private模式

类似VEPA模式,但增强了VEPA模式的隔离能力。其完全阻止共享同一父接口的MacVLAN子接口之间的通信。即使配置了hairpin,相应的流量仍会被丢弃。

Private模式的具体实现方式是丢弃广播/多播数据,这就意味着以太网地址解析ARP将无法工作。

Passthru模式

直通模式。这种模式下,每个父接口只能和一个MacVLAN子接口绑定,并且MacVLAN网卡继承父接口的mac地址。

在VEPA和Passthru模式下,两个MacVLAN网卡之间的通信会经过父接口两次,第一次是发出的时候,第二次是返回的时候。除了会影响MacVLAN接口之间的通信性能,还影响物理接口的宽带。

Source模式

这种模式下,寄生在物理设备上,MacVLAN设备只接收指定源mac地址的数据包,其他数据包一概丢弃。

配置使用:

# 创建
ip link add eth0.1 link eth0 type macvlan mode bridge
# 查看
ip -d link show eth0.1
________________________________________________________________________
16: eth0.1@eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 06:d0:84:ab:8e:c4 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 16110
    macvlan mode bridge bcqueuelen 1000 usedbcqueuelen 1000 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
# up网卡
ip link set eth0.1 up
# 配置ip
ifconfig eth0.1 192.168.209.200/24
# 删除网卡
ip link del eth0.1

实验:

宿主机:192.168.209.129/24,网关192.168.209.2

容器:192.168.209.209/24,网关192.168.209.2

# 创建虚拟网卡eth0.1
ip link add eth0.1 link eth0 type macvlan mode bridge

# 启动容器
docker run -id -d --net=none --name=busybox busybox /bin/sh

# 另开启一个ssh连接到宿主机
# 查看容器ns,pid为17223,961d为容器id前缀
 docker inspect --format '{{ .State.Pid }}' 961d
 # 将虚拟网卡eth0.1放到容器
 ip link set netns 17223 eth0.1
 # 进入netns 17223,为虚拟网卡配置ip以及为容器配置route。192.168.209.2为网关
 nsenter --target=17223 --net
 ifconfig eth0.1 192.168.209.209/24
 ip link set eth0.1 up
 ip route add default via 192.168.209.2 dev eth0.1
 
 # 测试
 # 容器ping外网
 通
 
 # 其它主机ping容器
 通
 
 # 宿主机ping容器
 不通
 
 # 容器ping宿主机
 不通

实验总结:MacVLAN只为虚拟机或容器提供访问外部物理网络的连接。

小结:

MacVLAN是将虚拟机或容器通过二层连接到物理网络的一个不错的方案,但它也有局限性,如:

因为每个虚拟网卡都要有自己的mac地址,所以MacVLAN需要大量的mac地址,而Linux主机连接的交换机可能会限制一个物理端口的mac地址数量上限,而且许多物理网卡的mac地址数量也有限制,超过这个限制就会影响到系统的性能;

IEEE 802.11标准(即无线网络)不喜欢同一个客户端上有多个mac地址,这意味着MacVLAN子接口没法在无线网卡上通信。