virtio-networking

669 阅读6分钟

内容个人理解,仅供参考,菜狗一个,主要目的用作笔记用

虚拟化组内会议 21-12-24

First, What is Virtio ?

Virtio是一套被用于VM访问块设备或者网络适配器的标准化API接口。大体可以理解为用来做虚拟化的一套方案,即从内部VM如何通过外部的物理机kernel访问外部实现通信。
下文将会提到多种名词:host(外部宿主机), guest/vm(内部云主机), virtio-net(虚拟以太网卡),vhost protocol(vhost协议)

So, What is Virtualization ?

简而言之,虚拟化就是将物理资源进行分配后在外部宿主机上构建出一套或多套设备环境。本文将简单介绍利用qemu与kvm虚拟化构建环境的操作过程。

What can virtio-networking do ?

Linux操作系统分为内核态与用户态(二者将在后续Blog中描述,本文不做赘述),我们将虚拟化的环境置于用户态中方便软件操作与用户使用,而由于是虚拟化出来的设备,所以最后真正的处理还是要交由host的内核处理。所以需要面临的问题就是,如何实现guest的内核态与host内核态的通信。本文采取libvirt, qemu, kvm 作为例子进行讲述。

  1. KVM(kernel based virtual machine)作为一种Linux的内核,提供了对宿主机的操作,比如内存管理,调度,网络栈等都包含在了Linux kernel里,所以运行在内核态;
  2. 而其余二者libvirt, qemu则为用户态的进程,其中qemu是提供与模拟guest环境的进程,由他提供guest虚拟的块设备等,与host内核进行通信,实现虚拟化中用户态操作的真正落地,对外暴露cli(command line interface)进行调用;
  3. 而libvirt只是作为外部更为便捷的使用qemu-cli的一种外部封装(like JDBC pool与JDBC connection),他可以翻译xml格式配置到qemu CLI调用的接口,它提供了一个admin状态下的守护进程来配置子进程,比如开启一个qemu的子进程,因此qemu才可以进行无需root权限即可对KVM发起指令,多台VM则开启多个qemu进程。

三者的组合作用如下:

img_1.png

大体构造了解了,那么就要讨论最核心的问题了:如何实现guest kernel与host kernel的通信

当讨论virtio-networking架构时需要分为两部分讨论:即数据面与控制面

  1. 控制平面 - 用于host和guest之间能力的协商,用于建立和终止数据平面
  2. 数据平面 - 用于host和guest之间传输实际的数据(packets)

So Why divided into two parts?

从目标上来讲,并无需要进行所谓的数据面控制面分离,之所以要进行分离,实际上是为了性能的提升。其实最初的virtio-networking并不是现在这样,有一套演化过程,而不变的目标就是性能,即追求从guest kernel到KVM的响应速度。其实从最简单的想法开始,要做的事就是guest kernel-->Qemu process-->KVM,然后由KVM实际完成操作后再切换到guest kernel,但由于频繁切换上下文等操作实际上会比较慢,所以在设计上进行了数据面与控制面的分离操作; 为了数据面的性能,此处引入vhost-protocol, 这个协议与virtio spec隔离开,与控制面的实现不同,无需通过qemu进程进行实现,简单来说就是数据面做出映射,将数据面的实现下放到host kernel中,直接将二者进行数据通信,跳过qemu进程的操控(数据面本身也可不需要操控)

The vhost-net/virtio-net architecture

当我们谈论关于virtio接口的时候我们有一个后端组件和一个前端组件

后端组件是host侧的virtio接口
前端组件是guest侧的virtio接口

在vhost-net/virtio-net架构的组件里是这样的

vhost-net是运行在host内核空间
virtio-net运行在guest的内核空间

下面的图展示了宏观上virtio的前端和后端是如何对应的:

img_2.png 🤖attention:因为vhost-net和virtio-net都运行在host和guest的内核空间,我们也叫他们驱动(drivers)所以如果有人“vhost-net-driver”不太要感觉奇怪指的是同一个东西
实际上数据面的通讯是通过VCPU的专用队列进行通信,提供了receive(RX)与transmit(TX)两种通道,而这些通道最后都会由vhost-net进行管理。
img_3.png

Virtio-networking and OVS

现在我们已经知道guest是如何实现调度host内核完成工作的了,但是还有重要的一点是,对于多台guest或者是guest与host的外部网络是如何通信的呢,这里我们选择将OVS(Open vSwitch)作为示例,作为一个交换机,其在用户态提供了一个可以用于记录转发记录的db-server,一个来管理和控制交换机的ovs-deamon,而在内核态提供了一个ovs内核模块以供数据通路和转发平面。
img_4.png 上图中为简化后的结构图,我们使用物理网卡的端口连接到ovs的内核转发平面并由其连接到vhost的后端,这样guest中的数据包将从vcpu的队列中发送到v-host后端并由ovs进行转发(ovs的控制面同时与db-server以及转发面通讯,即由控制面读取db决定发包往何处(host内部的其他guest或者host外部)后调用转发面进行转发。

Summary

在这篇文章中,我们已经触及了 virtio-networking 生态系统的表面,向您介绍了 virtio-networking 使用的虚拟化和网络的基本构建组件。我们简短的涵盖了virtio spec和vhost protocol,回顾了用于实现 virtio 接口的前端和后端架构,并带您了解了 vhost-net(host内核)与 virtio-net(guest内核)通信的 vhost-net/virtio-net 架构。

我们在尝试解释事物时遇到的一个基本挑战是术语历史问题。例如,virtio-net既指virtio规范中的virtio网络设备实现,也指vhost-net/virtio-net架构中描述的guest内核前端。我们试图通过在上下文解释术语并使用virtio-net仅描述guest内核前端来解决这个问题。

正如将在后面的文章中解释的那样,基于使用DPDK和不同硬件offload技术的virtio规范网络设备还有其他实现,这些都在virtio-networking的保护伞下。

原文链接: 原文链接