网卡也能虚拟化?网卡虚拟化技术 macvlan 详解

本文首发于个人公众号 cloud_dev,专一于干货分享,号内有大量书籍和视频资源,后台回复 「1024」便可领取,欢迎你们关注,二维码文末能够扫。

01 macvlan 简介

前面的文章讲过了几种 Linux 虚拟网络设备:tap/tun、veth-pair、bridge,它们本质上是 Linux 系统 提供的网络虚拟化解决方案,今天要讲的 macvlan 也是其中的一种,准确说这是一种网卡虚拟化的解决方案。由于 macvlan 这种技术能将 一块物理网卡虚拟成多块虚拟网卡 ,至关于物理网卡施展了 多重影分身之术 ,由一个变多个。docker

02 macvlan 的工做原理

macvlan 是 Linux kernel 支持的新特性,支持的版本有 v3.9-3.19 和 4.0+,比较稳定的版本推荐 4.0+。它通常是之内核模块的形式存在,咱们能够经过如下方法判断当前系统是否支持:编程

# modprobe macvlan
# lsmod | grep macvlan
macvlan                24576  0

若是第一个命令报错,或者第二个命令没有返回,说明当前系统不支持 macvlan,须要升级内核。ubuntu

macvlan 这种技术听起来有点像 VLAN,但它们的实现机制是彻底不同的。macvlan 子接口和原来的主接口是彻底独立的,能够单独配置 MAC 地址和 IP 地址,而 VLAN 子接口和主接口共用相同的 MAC 地址。VLAN 用来划分广播域,而 macvlan 共享同一个广播域。网络

经过不一样的子接口,macvlan 也能作到流量的隔离。macvlan 会根据收到包的目的 MAC 地址判断这个包须要交给哪一个虚拟网卡,虚拟网卡再把包交给上层的协议栈处理。工具

03 四种模式

根据 macvlan 子接口之间的通讯模式,macvlan 有四种网络模式:学习

  • private 模式
  • vepa(virtual ethernet port aggregator) 模式
  • bridge 模式
  • passthru 模式

默认使用的是 vepa 模式。测试

3.1 private

这种模式下,同一主接口下的子接口之间彼此隔离,不能通讯。即便从外部的物理交换机导流,也会被无情地丢掉。云计算

3.2 vepa

这种模式下,子接口之间的通讯流量须要导到外部支持 802.1Qbg/VPEA 功能的交换机上(能够是物理的或者虚拟的),经由外部交换机转发,再绕回来。spa

注:802.1Qbg/VPEA 功能简单说就是交换机要支持 发夹(hairpin) 功能,也就是数据包从一个接口上收上来以后还能再扔回去。code

3.3 bridge

这种模式下,模拟的是 Linux bridge 的功能,但比 bridge 要好的一点是每一个接口的 MAC 地址是已知的,不用学习。因此,这种模式下,子接口之间就是直接能够通讯的。

3.4 passthru

这种模式,只容许单个子接口链接主接口,且必须设置成混杂模式,通常用于子接口桥接和建立 VLAN 子接口的场景。

3.5 mactap

和 macvlan 类似的技术还有一种是 mactap。和 macvlan 不一样的是,mactap 收到包以后不是交给协议栈,而是交给一个 tapX 文件,而后经过这个文件,完成和用户态的直接通讯。

04 实践

在 Linux 系统下,建立 macvlan 的命令形式以下:

ip link add link DEVICE name NAME type { macvlan | macvtap } mode { private | vepa | bridge |
              passthru  [ nopromisc ] }

一般,单独使用 macvlan 毫无心义,通常都是结合 VM 和容器来构建网络。下面咱们就简单使用 namespace 来看看 Linux 是怎么使用 macvlan 的。

实验拓扑以下:

在个人系统中,以接口 enp0s8 为例建立两个 macvlan 子接口(使用 bridge 模式),配置 IP 并将其挂到两个 namespace 中,测试连通性。

# 建立两个 macvlan 子接口
ip link add link enp0s8 dev mac1 type macvlan mode bridge
ip link add link enp0s8 dev mac2 type macvlan mode bridge

# 建立两个 namespace
ip netns add ns1
ip netns add ns2

# 将两个子接口分别挂到两个 namespace 中
ip link set mac1 netns ns1
ip link set mac2 netns ns2

# 配置 IP 并启用
ip netns exec ns1 ip a a 192.168.56.122/24 dev mac1
ip netns exec ns1 ip l s mac1 up

ip netns exec ns1 ip a a 192.168.56.123/24 dev mac2
ip netns exec ns2 ip l s mac2 up

注:enp0s8 的 IP 是 192.168.56.110/24,配置的子接口 IP 也必须是同一网段的。

完了两个子接口 ping 一下:

root@ubuntu:~# ip netns exec ns1 ip a show mac1
9: mac1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1
    link/ether 2e:6e:d9:08:c5:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.56.122/24 scope global mac1
       valid_lft forever preferred_lft forever
    inet6 fe80::2c6e:d9ff:fe08:c505/64 scope link 
       valid_lft forever preferred_lft forever
root@ubuntu:~# ip netns exec ns1 ping 192.168.56.123
PING 192.168.56.123 (192.168.56.123) 56(84) bytes of data.
64 bytes from 192.168.56.123: icmp_seq=1 ttl=64 time=0.052 ms
64 bytes from 192.168.56.123: icmp_seq=2 ttl=64 time=0.028 ms
^C
--- 192.168.56.123 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.028/0.040/0.052/0.012 ms

能够看到,可以 ping 通,若是把上面的 mode 换成其余模式就行不通了,这个就留给你们去实验了(默认是 vepa 模式)。

另外,在 docker 中,macvlan 是一种较为重要的跨主机网络模型,这块的内容就留做下篇文章再作讲解了。

05 总结

macvlan 是一种网卡虚拟化技术,可以将一张网卡虚拟出多张网卡。

macvlan 的四种通讯模式,经常使用模式是 bridge。

思考一下:

  1. macvlan bridge 和 bridge 的异同点
  2. 还有一种相似的技术,多张虚拟网卡共享相同 MAC 地址,但有独立的 IP 地址,这是什么技术?

这两个问题你们能够留言互动一下。


个人公众号 cloud_dev,号内有大量书籍和视频资源,后台回复 「1024」便可领取,分享的内容包括但不限于云计算虚拟化、容器、OpenStack、K8S、雾计算、网络、工具、SDN、OVS、DPDK、Linux、Go、Python、C/C++编程技术等内容,欢迎你们关注。

相关文章
相关标签/搜索