0%

【网络虚拟化】MacVLAN

Macvlan 允许你在主机的一个网络接口上配置多个虚拟的网络接口,这些网络 interface 有自己独立的 MAC 地址,也可以配置上 IP 地址进行通信。Macvlan 下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。Macvlan 和 Bridge 比较相似,但因为它省去了 Bridge 的存在,所以配置和调试起来比较简单,而且效率也相对高。除此之外,Macvlan 自身也完美支持 VLAN

macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。macvlan 本质上是一种网卡虚拟化技术(最大优点是性能极好)

可以在linux命令行执行lsmod | grep macvlan 查看当前内核是否加载了该driver;如果没有查看到,可以通过modprobe macvlan来载入,然后重新查看。内核代码路径 /drivers/net/macvlan.c

Bridge VS MACVlan

Bridge Mode

  • Bridge 是二层设备,仅用来处理二层的通讯。
  • Bridge 使用 MAC 地址表来决定怎么转发帧(Frame)。
  • Bridge 会从 host 之间的通讯数据包中学习 MAC 地址。
  • 可以是硬件设备,也可以是纯软件实现(例如:Linux Bridge)。

提示:

Bridge 有可能会遇到二层环路,如有需要,可以开启 STP 来防止出现环路。

MACVlan Mode

  • 可让使用者在同一张实体网卡上设定多个 MAC 地址。
  • 上述设定的 MAC 地址的网卡称为子接口(sub interface);而实体网卡则称为父接口(parent interface)。
  • parent interface 可以是一个物理接口(eth0),可以是一个 802.1q 的子接口(eth0.10),也可以是 bonding 接口。
  • 可在 parent/sub interface 上设定的不只是 MAC 地址,IP 地址同样也可以被设定。
  • sub interface 无法直接与 parent interface 通讯 (带有 sub interface 的 VM 或容器无法与 host 直接通讯)。
  • 若 VM 或容器需要与 host 通讯,那就必须额外建立一个 sub interface 给 host 用。
  • sub interface 通常以 mac0@eth0 的形式来命名以方便区別。

工作模式

Bridge Mode

属于同一个parent接口的macvlan接口之间挂到同一个bridge上,可以二层互通(macvlan接口都无法与parent 接口互通)

VPEA Mode

Virtual Ethernet Port Aggregator,所有接口的流量都需要到外部switch才能够到达其他接口

Private Mode

接口只接受发送给自己MAC地址的报文。

Passthru Mode

父接口和相应的MacVLAN接口捆绑在一起,这种模式每个父接口只能和一个 Macvlan 虚拟网卡接口进行捆绑,并且 Macvlan 虚拟网卡接口继承父接口的 MAC 地址。

实战体验

下面的实验创建了两个macvlan接口,分别放到两个netns中;然后验证这两个macvlan口之间客户互通。

先使用bridge mode创建两个macvlan接口,其parent接口都是 eth0。

1
2
$ sudo ip link add link eth0 name macv1 type macvlan mode bridge
$ sudo ip link add link eth0 name macv2 type macvlan mode bridge

查看创建的结果,注意每个接口都有自己的 mac 地址

1
2
3
4
5
6
7
$ sudo ip link
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:f4:3e:1d brd ff:ff:ff:ff:ff:ff
3763: macv1@eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 52:76:5f:92:85:8d brd ff:ff:ff:ff:ff:ff
3764: macv2@eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 66:90:ba:08:bd:81 brd ff:ff:ff:ff:ff:ff

创建namespace

1
2
$ sudo ip netns add net1
$ sudo ip netns add net2

将macvlan接口插入到namespace

1
2
$ sudo ip link set macv1 netns net1
$ sudo ip link set macv2 netns net2

设置网卡IP,设置网卡UP状态

1
2
3
4
5
$ sudo ip netns exec net1 ip addr add 52.1.1.151/24 dev macv1
$ sudo ip netns exec net2 ip addr add 52.1.1.152/24 dev macv2

$ sudo ip netns exec net1 ip link set macv1 up
$ sudo ip netns exec net2 ip link set macv2 up

查看网卡状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo ip netns exec net1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3763: macv1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:76:5f:92:85:8d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 52.1.1.151/24 scope global macv1
valid_lft forever preferred_lft forever
$ sudo ip netns exec net2 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3764: macv2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 66:90:ba:08:bd:81 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 52.1.1.152/24 scope global macv2
valid_lft forever preferred_lft forever

net1和net2无法ping通宿主机,ping自己也不通.2个容器互相ping没有问题

发现macv1 ping不通宿主机接口 eth0 的地址:

1
2
3
4
5
$ sudo ip net exec net1 ping 10.0.1.3
PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.
^C
--- 10.0.1.3 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3008ms

但是可以ping通macv2的地址:

1
2
3
4
5
$ sudo ip net exec net1 ping 52.1.1.152
PING 52.1.1.152 (52.1.1.152) 56(84) bytes of data.
64 bytes from 52.1.1.152: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 52.1.1.152: icmp_seq=2 ttl=64 time=0.041 ms
64 bytes from 52.1.1.152: icmp_seq=3 ttl=64 time=0.047 ms