赞
踩
Virtio是一种标准化的开放接口,用于使虚拟机(VM)能够访问简化的设备,如块设备和网络适配器
。Virtio-net是一张虚拟以太网卡,到目前为止是virtio支持的最复杂的设备。
在本文中,我们将提供virtio-networking架构的高级解决方案概述,基于在主机内核和VM客户内核之间建立接口。我们将介绍基本的构建模块,包括KVM、qemu和libvirt。我们将查看virtio规范和vhost协议,以及用于连接不同VM和外部世界的Open vSwitch(OVS)。本文中描述的基于vhost-net/virtio-net的架构是一系列不同性能、应用易用性和实际部署的virtio-networking架构中的第一个。
阅读完本文后,您应该清楚所提到的术语以及运行在VM中的应用程序如何将数据包传输到运行在其他VM和外部世界的应用程序。这些术语将成为接下来文章的基础。
Guest VM或guest是安装、执行和托管在物理机器上的虚拟机(VM)。托管guest VM的机器称为主机,它为guest提供资源。guest在主机操作系统之上通过虚拟机监视器运行一个独立的操作系统。例如,主机将为guest提供一个虚拟网卡,使guest机器感觉自己正在使用真实的网卡,而实际上它正在使用虚拟网卡。
以下构建块创建了virtio连接的环境:
1、KVM - 基于内核的虚拟机,允许Linux充当虚拟机监视器,以便主机机器可以运行多个隔离的虚拟环境,称为guests。KVM基本上为Linux提供了虚拟机监视器的功能
。这意味着虚拟机监视器组件,如内存管理器、调度程序、网络堆栈等,作为Linux内核的一部分提供。虚拟机是由标准Linux调度程序安排的常规Linux进程,具有专用的虚拟硬件,如网络适配器。
2、QEMU - 通过模拟提供一组不同的硬件和设备模型供guest机器使用的托管虚拟机监视器
。QEMU可以与KVM一起使用,以接近本地速度运行虚拟机,利用硬件扩展功能。通过qemu命令行界面(CLI)执行guest。CLI提供了为QEMU指定所有必要配置选项的功能。
3、Libvirt - 一个接口,将XML格式的配置转换为qemu CLI调用
。它还提供了一个管理守护程序来配置诸如qemu之类的子进程,因此qemu不需要root权限。例如,当Openstack Nova想要启动VM时,它使用libvirt来为每个VM调用qemu进程,通过为每个VM调用一个qemu进程来启动VM。
以下图表显示了这三个构建块是如何结合在一起的:
主机和guest都包含内核空间和用户空间。如图所示,KVM在主机内核空间中运行,而libvirt在主机用户空间中运行。
guest VM在qemu进程内运行,这只是在主机用户空间运行的进程,与libvirt(用户空间应用程序)和KVM(主机内核)进行通信。
为每个guest VM创建一个qemu进程,因此如果创建N个VM,将有N个qemu进程,libvirt将与每个进程通信。
在讨论virtio-networking时,我们可以将讨论分为两个层面:
控制平面 - 用于主机和guest之间的能力交换协商,用于建立和终止数据平面。
数据平面 - 用于在主机和guest之间传输实际数据(数据包)。
重要的是要区分这些层,因为它们具有不同的要求(如性能)和不同的实现,正如将在这篇文章和接下来的文章中看到的那样。
从根本上说,数据平面需要尽可能高效,以便快速传输数据包,而控制平面需要尽可能灵活,以支持未来架构中的不同设备和供应商
。
如介绍中所提到的,virtio是作为让guest访问主机上的设备的接口而开发的。我们可以将virtio分为两部分:
virtio规范 - 由OASIS维护的virtio规范定义了如何在guest和host之间创建控制平面和数据平面。例如,数据平面由在规范中详细
描述的缓冲区和环形布局组成。
vhost协议 - 一种允许将virtio数据平面实现卸载到另一个元素(用户进程或内核模块)以增强性能的协议。
virtio的控制平面是基于virtio规范在qemu进程中实现的,但数据平面不是。那么问题是为什么不根据virtio规范在qemu进程中以类似的方式实现数据平面?
答案是性能。
如果我们简单地在qemu中实现virtio规范的数据平面,每个从内核到guest的数据包以及反之都会导致一次上下文切换。这是一个昂贵的操作,会增加延迟并需要更多的处理时间(请记住,qemu只是另一个Linux进程),因此如果可能的话,我们希望避免这种情况。
这就是vhost协议
发挥作用的地方,它使我们能够实现一个从内核(主机)直接到guest的数据平面,绕过qemu进程
。
vhost协议本身只描述了如何建立数据平面
。实施它的人还应该实施描述数据缓冲区(主机和guest)和实际发送/接收数据包的环形布局。
如后面的部分所述,vhost协议可以在内核中(vhost-net)或用户空间中(vhost-user)实现。本文描述的vhost-net/virtio-net架构侧重于内核实现,也称为vhost-net。
当我们谈论virtio接口时,有一个后端组件和一个前端组件:
后端组件是virtio接口的主机端
前端组件是virtio接口的guest端
在vhost-net/virtio-net架构中,这些组件如下:
vhost-net是在主机内核空间运行的后端
virtio-net是在guest内核空间运行的前端
以下图表显示了virtio后端和前端如何映射到整个架构:
需要澄清的几个要点:
由于vhost-net和virtio-net都在主机和guest内核空间运行,因此我们也称它们为驱动程序,所以如果有人写“vhost-net驱动程序”(同样的东西),不要感到困惑。
在后端和前端之间,我们有一个单独的控制平面和数据平面。正如前面解释的,控制平面只是为vhost-
net内核模块和qemu进程实现virtio规范,然后传输到guest,最终到virtio-net。vhost-net使用vhost协议
来建立框架,然后用于数据平面,直接通过共享内存区域在主机和guest内核之间转发数据包。
实际上,数据平面通信,接收(RX)和传输(TX),是通过专用队列完成的。
对于每个guest,我们可以关联多个虚拟CPU(vCPU),并为每个CPU创建RX/TX队列,因此具有4个vCPU的更详细的示例如下(为简单起见删除了控制平面):
到目前为止,我们已经描述了如何使用virtio-networking接口将数据包传递给主机内核。为了将这些数据包转发到在同一主机上运行的其他guest或主机外(例如互联网),我们使用了OVS。
OVS是一个软件交换机,可在内核中启用数据包转发。它由用户空间部分和内核空间部分组成:
用户空间 - 包括一个数据库(ovsdb-server)和用于管理和控制交换机的OVS守护程序(ovs-vswitchd)。
OVS控制器既与数据库服务器通信,也与内核转发平面通信。为了将数据包推入和推出OVS,我们使用Linux端口。在我们的情况下,有一个端口将OVS内核转发平面连接到物理NIC,而另一个端口连接到vhost-net后端。
请注意,我们正在尝试简化事物,因为实际上会有多个NIC通过多个端口连接到OVS,并且会运行多个VM,因此有多个端口连接到多个vhost-net后端。
回到virtio-networking,这个图表显示了OVS如何连接到virtio:
请注意,上面提到的端口用于将OVS连接到主机外部,以及连接到vhost-net,从那里连接到virtio-net,再连接到在VM中运行的应用程序。
这就结束了基于主机内核、客户内核和在内核中运行的OVS的vhost-net/virtio-net架构概述。
在本篇文章中,我们初步介绍了virtio-networking生态系统的基本构建块,为您介绍了virtio-networking使用的虚拟化和网络的基本构建块。我们简要介绍了virtio规范和vhost协议,回顾了用于实现virtio接口的前端和后端架构,并带您了解了vhost-net/virtio-net架构,其中vhost-net(主机内核)与virtio-net(客户内核)通信。
在试图解释事物时,我们遇到的一个根本性挑战是术语的历史负担。例如,virtio-net既指virtio规范中的virtio网络设备实现,也指vhost-net/virtio-net架构中描述的客户内核前端。我们试图通过解释术语的上下文并仅使用virtio-net来描述客户内核前端来解决这个问题。
正如稍后的帖子中将要解释的,根据使用DPDK和不同的硬件卸载技术,还有其他的virtio规范网络设备的实现,这些都属于virtio-networking的范畴。
接下来的两篇帖子旨在更深入地了解vhost-net/virtio-net架构。其中一篇帖子面向架构师,提供了对vhost-net/virtio-net的技术深入分析,并解释了在实践中如何实现数据平面和控制平面。另一篇面向开发人员,包括Ansible脚本,以便实验vhost-net/virtio-net架构。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。