虚拟化KVM中的tun/tap和bridge+vnet以及macvtap之间有什么区别?

我刚刚发现了很多不同的方法来进行KVM网络设置。但是我困惑于哪种方法才是正确的。我发现OpenStack使用macvtap来进行neutron网络设置,看起来不错。
但是每种方法有什么区别,为什么要使用每种方法呢?
方法1 [旧的?TUN/TAP]

http://www.shakthimaan.com/installs/debian-tun-tap-setup.html

/--------\   /----\   /----\   /----\   /--------\
|Internet|---|eth0|---|br0 |---|tap0|---|Guest NIC
\--------/   \----/   \----/   \----/   \--------/

废弃了,对吧?
方式2 [桥接+虚拟网络] <- 这就是virt-manager所做的。

http://www.linux-kvm.com/content/using-bridged-networking-virt-manager

基本上,您可以在您的物理接口内创建一个桥接接口。
auto br0
#iface br0 inet dhcp
iface br0 inet static
address 172.16.0.100
network 172.16.0.0
netmask 255.255.0.0
broadcast 172.16.255.255
gateway 172.16.0.1
   bridge_ports eth2
   bridge_stp off
    bridge_fd 0
    bridge_maxwait 0

当您从virt-manager启动虚拟机时,会创建一个vnet接口并添加到桥接器中。至少根据我所知的情况是如此。不需要tun/tap接口。

这个方法在很长一段时间内都运行得很好,但是现在在saucy版本中我发现了一些问题。

https://bugs.launchpad.net/ubuntu/+source/core-network/+bug/1255516

为什么可以在桥接器上添加新的虚拟网络接口而不需要TAP接口?
第三种方式是MACVTAP。
最后是macvtap接口。

http://virt.kernelnewbies.org/MacVTap

它复制了TUN/TAP软件接口,但以更好的方式实现。虽然不知道具体是什么方式,但似乎更好。
macvtap相比第二种方式有什么优势?
哪个更好?
对此有何帮助?

你应该考虑标记一个答案。只是个建议而已。 - IMTheNachoMan
3个回答

这些方法在根本上做着不同的事情。要理解其中的原因,您需要了解网络的分层模型。对于我们在这里的目的,第1、2和3层是重要的:
- 第1层是物理层 - 它指定了可以使用的电缆类型,以及在该电缆上表示1和0的电压/电流模式,以及每个电缆末端的设备如何协商操作速率等。 - 第2层是链路层 - 它指定了电缆两端的设备之间交流的语言。在这一层上,以太网设备具有帧和MAC地址等特性。 - 第3层是网络层 - 它指定了设备如何使用直接的第2层链路来到达无法直接在第2层到达的第三个设备。在这一层上,设备具有IP地址和路由表。
MACVLAN / MACVTAP
MACVLAN创建了一个虚拟的第二层或链路层设备,具有自己的MAC地址,与现有设备共享第一层或物理层。最明显易懂的情况是,当您将以太网设备插入网络并基于该以太网设备创建MACVLAN设备时;现在您有两个以太网“设备”,它们具有不同的MAC地址,但都在同一根电缆上传输帧。稍后我会详细介绍MACVTAP。
MACVLAN接口可以以几种不同的方式与现有以太网接口进行交互,特别是当一个帧出现在其中一个接口上,并且被寻址到另一个接口时:
私有模式下,框架被丢弃;两个接口之间无法进行通信,只能与外部设备进行通信。
vepa模式下,框架像其他框架一样通过物理层发送。如果您将设备插入一个足够聪明的交换机中,该交换机会识别到该框架需要通过相同端口返回,然后由发送它的物理层接收,并且第二层将使用MAC地址将其发送到目标网络接口。
桥接模式下,当一个框架出现在一个设备上时,会检查是否是为另一个设备而设计的,如果是,则直接发送到那里,不经过第一层。
还有一些更为晦涩的模式。
请注意,MACVLAN接口有一个重要限制:它们不能进行地址学习。因此,您不能将MACVLAN接口桥接到第二个物理设备,并期望能够通过第一个设备访问第二个设备。这对于原始以太网接口有效,但对附加到其上的MACVLAN接口无效。 TUN/TAP TAP接口也是一个新的虚拟第二层设备,但它没有连接到第一层。相反,程序可以获得表示物理层的文件描述符。然后,它可以将原始以太网帧数据写入该文件描述符,内核将像对待真实物理接口上接收到的任何其他以太网数据包一样处理它。
TAP接口的重要之处在于物理层位于用户模式;具有适当权限的任何软件都可以以任何方式生成以太网帧,并将其推送到内核将其视为真实物理接口的东西中。这使得它们非常适用于VPN和隧道等应用;您可以在用户空间中编写任何类型的隧道软件,而无需干预内核空间以将帧写入网络堆栈,只需创建一个TAP设备并将帧写入其文件描述符即可。
TUN设备与TAP设备类似,只是它们在第三层操作而不是第二层,并且用户模式软件必须将原始IP数据包写入文件描述符,而不是原始以太网帧。
回到MACVTAP设备,这些是MACVLAN和TAP接口之间的混合体。像TAP接口一样,用户模式程序可以获得文件描述符并将原始以太网帧写入其中。像MACVLAN接口一样,这些帧然后通过真实以太网设备的物理层发送。这使您可以轻松地调整使用TAP设备编写的软件以使用MACVLAN设备。
VNet
这在概念上类似于TUN/TAP网络,但具有更完善的控制平面(因此使用它的用户模式软件可以更灵活地配置接口)和更优化的数据平面(因此可以更高效地通过虚拟网络设备传输数据)。
所有这些都可以做类似的事情,但具有略微不同的功能。所有这些都可以用于将虚拟机连接到以太网网络:
一个虚拟化产品可以接收来自客户机的以太网帧,并将其写入TAP设备的文件描述符中。该TAP设备可以由主机分配独立的IP地址,或者可以与以太网接口一起作为桥接设备使用,共享主机的IP地址,也可以通过配置iptables使用NAT来转发流量。
一个虚拟化产品可以接收来自客户机的以太网帧,并将其写入MACVTAP设备的文件描述符中;然后这些帧会直接传输到以太网设备的物理层,从而有效地为虚拟机提供了一个“真实”的以太网设备(需要注意的是,也可以为其他类型的网络接口(如桥接设备)创建MACVLAN / MACVTAP设备)。
一个虚拟化产品可以将客户机中的virtio驱动程序连接到主机中的virtio驱动程序,以实现非常高效的网络通信。

这真是太有帮助了。你介意详细解释一下MACVLAN中的“地址学习”方面吗?我对你的例子还不是完全理解。无法将MACVLAN接口桥接到第二个物理设备??? - IMTheNachoMan
@IMTheNachoMan - 当你桥接两个以太网接口时,桥接会维护桥转发表。当它在其中一个以太网接口上收到一个未知的MAC地址的帧时,它会记录该MAC地址可以通过该端口访问。因此,下次当另一个桥接端口上到达一个寻址给该MAC的帧时,它就知道要将其发送到该以太网接口上。然而,由于某些原因,MACVLAN接口不支持这一功能,所以如果你将其从属于一个桥接,流量将无法正确地穿越桥接。 - Tom

这真的取决于你想要实现什么。

  • TAP/TUN

无论是虚拟机还是物理机都没关系。TUN提供了一个隧道网络,而TAP则是一种设备。简单来说,你通过一个隧道网络连接到另一个网络。

例如,在配置OpenVPN网络时,你的客户端会被分配到10.8.0.6的IP地址。VPN服务器10.8.0.1会将你的请求路由到另一个网络(例如192.168.x.x)后面。当使用TAP时,你会直接从目标网络(192.168.10.x/24)获得一个IP地址(192.168.10.10/24)。很简单。

  • 桥接

"Linux桥接"将VNET(来自虚拟机)与物理以太网桥接起来。如果你想要一个基于KVM的虚拟机,那么在主机上必须要有一个桥接连接vnet和以太网。


1嗯,谢谢你的答案,但它并没有解决我的疑虑。如果你查看链接,你会发现有更多的原因来使用其中之一。事实上,在当前 Linux 栈对于虚拟机来说,桥接方式并不好用了。所以我不得不使用 MACVTAP。 - Gonzalo Aguilar Delgado

我会说这取决于你的使用情况。
自动添加/删除虚拟主机?
试试macvtap。应该比macvlan更高效(macvlan大致上就像给物理设备添加另一个MAC地址,到达那里的信息由网络堆栈处理),或者使用额外的桥接器,因为macvtap绕过了网络堆栈并直接导出tap字符设备。但是不要完全相信我。此外,macvlan和macvtap都共享相同的可用模式(VEPA/hairpin、桥接、私有),只有在交换机支持反射中继模式时,hairpinning才能正常工作。(到达物理交换机端口x的数据包必须被允许再次从同一端口x离开。)
因为使用桥接时eth0(或其他你使用的接口)会进入混杂模式,所以macvXXX模式被认为具有更高的吞吐量。
这些模式还定义了“隔离”的程度(虚拟主机是否可以看到彼此的流量?hv如何?)。关于底层原理,我还不清楚。
veth(虚拟以太网对)在隔离方面有些相似,您定义了两个虚拟接口,一个连接到桥接器,另一个连接到您的虚拟机。在这里,通过将虚拟机接口放入自己的命名空间中来进行隔离,从而使设备有一定程度的隔离。所有流量都汇集在桥接器上,但一个虚拟主机无法看到另一个虚拟主机的虚拟网络接口。
如果您使用桥接器,还需要进行其他配置,当桥接器关闭时,所有连接也会断开。重新启动桥接器时,您可能需要重新连接所有虚拟接口到桥接器(或者只需重新启动整个 hv...)。
底线是: 如果您的拓扑结构不经常更改,那就选择桥接模式吧,因为在线上可以找到大量关于桥接模式的信息,这比阅读内核代码要好。哪怕是 iproute2-doc 包本身也缺乏大部分实际存在于 iproute2 中的信息,即使您运行最新版本。尝试从可用的 manpages 或 ip-crefs.ps 中了解有关 man ip-tcp_metrics 的信息...

我甚至都不记得写过这个,更别提我是在哪里找到那么多的信息了。:( - sjas