最小的自动化。 第1.1部分。 虚拟化基础

上一篇文章介绍了虚拟化网络的体系结构,底层覆盖,VM之间的软件包路径等。
Roman Gorge受到她的启发,因此决定撰写有关虚拟化的评论文章。

在本文中,我们将涉及(或尝试涉及)以下问题:网络功能的虚拟化实际上是如何发生的,用于启动和管理VM的主要产品的后端是如何实现的,以及虚拟交换的工作方式(OVS和Linux桥接器)。

虚拟化的主题是广泛而深入的,不可能解释虚拟机管理程序的所有工作细节(并且没有必要)。 我们将把自己的知识限制在理解任何虚拟化解决方案(不一定是电信公司)的操作所必需的最少知识上。



目录内容


  • 虚拟化简介和简要历史
  • 虚拟资源的类型-计算,存储,网络
  • 虚拟切换
  • 虚拟化工具-libvirt,virsh等
  • 结论






虚拟化简介和简要历史



现代虚拟化技术的历史可以追溯到1999年,当时年轻的VMware公司发布了一款名为VMware Workstation的产品。 这是用于桌面/客户端应用程序的虚拟化产品。 服务器端虚拟化后来以ESX Server产品的形式出现,该产品后来演变为ESXi(我的意思是集成的)-这是与IT和Telco共同用作服务器应用程序管理程序的同一产品。

在开源方面,有两个主要项目将虚拟化引入了Linux:
  • KVM(基于内核的虚拟机)是一个Linux内核模块,它允许内核充当管理程序(创建启动和管理VM的必要基础结构)。 它是在2007年的内核版本2.6.20中添加的。
  • QEMU(快速仿真器)-直接仿真虚拟机的硬件(CPU,磁盘,RAM,包括USB端口在内的任何东西),并与KVM结合使用以实现几乎“本机”的性能。


实际上,目前,KE的所有功能都可以在QEMU中使用,但这并不重要,因为大多数Linux虚拟化用户并不直接使用KVM / QEMU,而是通过至少一个抽象级别来访问它们,但以后会更多。


如今,VMware ESXi和Linux QEMU / KVM是主导市场的两个主要管理程序。 它们还是两种不同类型的管理程序的代表:
  • 类型1-虚拟机管理程序直接在硬件(裸机)上运行。 这是VMware ESXi,Linux KVM,Hyper-V
  • 类型2-系统管理程序在主机OS(操作系统)内部启动。 这是VMware Workstation或Oracle VirtualBox。


关于什么更好和什么不好的讨论不在本文的讨论范围之内。



钢铁生产商还必须尽自己的一份努力,以确保表现令人满意。

也许最重要和使用最广泛的是Intel VT(虚拟化技术),这是Intel为x86处理器开发的一组扩展,用于虚拟机管理程序的有效运行(在某些情况下是必需的,例如,如果不打开VT,则KVM将无法工作-x,如果没有它,系统管理程序将被迫从事纯软件仿真,而无需硬件加速。
其中最著名的两个扩展是VT-x和VT-d。 第一个对提高虚拟化期间的CPU性能非常重要,因为它为某些功能提供了硬件支持(VT-x 99.9%Guest OS代码直接在物理处理器上执行,仅在最必要的情况下才输出输出),第二个是直接连接物理设备到虚拟机(对于前向虚拟功能(VF)SRIOV,例如, 必须启用 VT-d)。

下一个重要概念是完全虚拟化和半虚拟化之间的区别。
完全虚拟化是好的,它允许您在任何处理器上运行任何操作系统,但是效率极低,绝对不适合高负载系统。
简而言之,准虚拟化是指Guest OS知道其在虚拟环境中运行并与虚拟机管理程序合作以实现更高的效率。 即,出现来宾管理程序界面。
当今使用的绝大多数操作系统都支持半虚拟化-在Linux内核中,这是从2.6.20版内核开始出现的。

为了使虚拟机正常工作,不仅需要虚拟处理器(vCPU)和虚拟内存(RAM);还需要仿真PCI设备。 也就是说,实际上,需要一组驱动程序来管理虚拟网络接口,磁盘等。
在Linux KVM虚拟机管理程序中,该任务是通过实现virtio (解决方案)解决的, virtio是用于开发和使用虚拟化I / O设备的框架。
Virtio是附加的抽象级别,它使您可以在半虚拟化的虚拟机管理程序中模拟各种I / O设备,从而为虚拟机一侧提供统一的标准化接口。 这使您可以将virtio驱动程序代码重用于各种固有设备。 Virtio包括:
  • 前端驱动程序-虚拟机中的内容
  • 后端驱动程序-虚拟机管理程序中的功能
  • 传输驱动程序-连接后端和前端的内容

通过这种模块化,您可以在不影响虚拟机驱动程序的情况下更改虚拟机管理程序中使用的技术(此刻对于网络加速技术和整个Cloud解决方案非常重要,但稍后会介绍更多信息)。
也就是说,当来宾操作系统“知道”它在虚拟环境中运行时,存在来宾-管理程序连接。
如果您曾经在RFP中写过一个问题或在RFP中回答过一个问题,“您的产品是否支持virtio?” 它只是要支持前端virtio驱动程序。


虚拟资源的类型-计算,存储,网络


虚拟机由什么组成?
虚拟资源有三种主要类型:

  • 计算-处理器和RAM
  • 存储-虚拟机系统磁盘和块存储
  • 网络-网卡和输入/输出设备





计算



中央处理器


从理论上讲,QEMU能够模拟任何类型的处理器及其相应的标志和功能;在实践中,它们可以使用主机模型并在将标志传输到Guest OS之前先关闭它们的标志,或者使用命名模型并按点打开/关闭标志。

默认情况下,QEMU将模拟来宾OS识别为QEMU虚拟CPU的处理器。 这不是最佳处理器类型,尤其是在虚拟机中运行的应用程序使用CPU标志进行工作时。 了解有关QEMU中不同CPU型号的更多信息

QEMU / KVM还允许您控制处理器拓扑,线程数,缓存大小,将vCPU绑定到物理核心等等。

对于虚拟机是否需要此操作取决于在Guest OS上运行的应用程序的类型。 例如,众所周知的事实是,对于处理具有高PPS的数据包的应用程序,重要的是进行CPU固定 ,即,不允许将物理处理器转移到其他虚拟机。

记忆体


接下来的是RAM。 从主机操作系统的角度来看,使用QEMU / KVM启动的虚拟机与在操作系统用户空间中运行的任何其他进程没有什么不同。 相应地,将虚拟机分配内存的过程由内核Host OS中的相同调用执行,就像您启动了例如Chrome浏览器一样。

在继续介绍虚拟机中RAM的故事之前,您需要讲解并解释术语NUMA-非统一内存访问。
现代物理服务器的体系结构涉及两个或多个处理器(CPU)的存在,并且与之相关联的是随机存取存储器(RAM)。 这样一堆处理器+内存称为一个节点或节点。 各种NUMA节点之间的通信通过特殊的总线-QPI (QuickPath互连)进行

本地NUMA节点被分配-当操作系统中运行的进程使用位于同一NUMA节点中的处理器和RAM时,远程NUMA节点-当操作系统中运行的进程使用位于不同NUMA节点中的处理器和RAM时,也就是说,对于处理器和内存的交互,需要通过QPI总线进行数据传输。




从虚拟机的角度来看,在启动虚拟机时已经为它分配了内存,但实际上并非如此,并且内核Host OS会为Guest OS中的应用程序请求额外的内存向QEMU / KVM进程分配新的内存部分(尽管可能还会有如果您直接指定QEMU / KVM在启动时直接将所有内存分配给虚拟机,则为例外。

内存不是按字节分配的,而是按一定大小的页面分配的。 页面大小是可配置的,理论上可以是任何大小,但实际上大小为4kB(默认),2MB和1GB。 最后两个大小称为HugePages ,通常用于为内存密集型虚拟机分配内存。 在转换后备缓冲区TLB )中查找页面的虚拟地址与物理内存之间匹配的过程中使用HugePages的原因,而后者又受到限制,并且仅存储有关最后使用的页面的信息。 如果在TLB中没有有关所需页面的信息,则会发生称为未命中TLB的过程,您需要使用主机操作系统处理器来查找与所需页面相对应的物理存储单元。

该过程效率低下且速度慢,因此使用了较少的较大尺寸的页面。
QEMU / KVM还允许您模拟来宾操作系统的各种NUMA拓扑,仅从特定的NUMA节点主机操作系统获取虚拟机的内存,等等。 最常见的做法是从分配给虚拟机的处理器本地的NUMA节点获取虚拟机的内存。 原因是希望避免在连接物理服务器CPU插槽的QPI总线上造成不必要的负载(当然,如果您的服务器有2个或更多插槽,这是合乎逻辑的)。




贮藏


如您所知,RAM被称为操作内存,因为它的内容在关闭电源或重新引导操作系统时就会消失。 要存储信息,您需要持久性存储设备(ROM)或持久性存储
持久性存储主要有两种类型:
  • 块存储-一块磁盘空间,可用于安装文件系统和创建分区。 如果不客气,那么您可以将其当作普通磁盘使用。
  • 对象存储-信息只能保存为对象(文件),可通过HTTP / HTTPS访问。 对象存储的典型示例是AWS S3或Dropbox。


虚拟机需要持久性存储 ,但是,如果虚拟机“驻留”在主机OS RAM中,该怎么做? 简而言之,对虚拟磁盘控制器的任何来宾OS调用都会被QEMU / KVM拦截,并转换为主机OS物理磁盘上的记录。 该方法效率低下,因此,在此以及网络设备中,使用virtio驱动程序来代替完全模拟IDE或iSCSI设备。 在此处阅读有关此内容的更多信息。 因此,虚拟机通过virtio驱动程序访问其虚拟磁盘,然后QEMU / KVM将传输的信息写入物理磁盘。 重要的是要了解,在主机操作系统中,可以将磁盘后端实现为CEPH,NFS或iSCSI架子。

模拟持久性存储的最简单方法是将Host OS某个目录中的文件用作虚拟机的磁盘空间。 QEMU / KVM支持这种文件的许多不同格式-raw,vdi,vmdk等。 但是,使用最广泛的格式是qcow2 (QEMU写入时复制版本2)。 通常,以某种方式,qcow2是一个结构化文件,没有任何操作系统。 大量虚拟机以qcow2-映像(映像)的形式分发,并且是虚拟机系统磁盘的副本,以qcow2格式打包。 这有几个优点-qcow2编码比字节到字节磁盘的原始副本占用的空间少得多,QEMU / KVM可以调整qcow2文件的大小,这意味着可以更改虚拟机磁盘的大小,还支持AES qcow2加密(这很有意义,因为虚拟机的映像可能包含知识产权)。

此外,当虚拟机启动时,QEMU / KVM使用qcow2文件作为系统磁盘(尽管这也是一项有趣的任务,但这里省略了加载虚拟机的过程),并且虚拟机具有通过virtio读取数据/将数据写入qcow2文件的能力。司机。 因此,获取虚拟机映像的过程是可行的,因为在任何时候qcow2文件都包含虚拟机系统磁盘的完整副本,并且该映像可用于备份,传输到其他主机等。

通常,此qcow2文件将在来宾操作系统中定义为/ dev / vda设备 ,并且来宾操作系统会将磁盘空间划分为多个分区并安装文件系统。 同样,由QEMU / KVM作为/ dev / vdX设备连接的以下qcow2文件可以用作虚拟机中的块存储来存储信息(这正是Openstack Cinder组件的工作方式)。



联播网


在我们的虚拟资源列表上,最后一个是网卡和I / O设备。 虚拟机像物理主机一样,需要PCI / PCIe总线来连接I / O设备。 QEMU / KVM能够仿真不同类型的芯片组-q35或i440fx(第一个支持PCIe,第二个支持传统PCI),以及各种PCI拓扑,例如,为NUMA节点来宾OS创建单独的PCI总线(PCI扩展器总线)。

创建PCI / PCIe总线后,必须将I / O设备连接到它。 通常,它可以是从网卡到物理GPU的任何东西。 当然,还有完全虚拟化的网卡(例如,完全e1000虚拟化的接口)和半虚拟化的网卡(例如,virtio)或物理NIC。 最后一个选项用于需要获得线速数据包速率的数据平面虚拟机-路由器,防火墙等。

这里有两种主要方法-PCI直通SR-IOV 。 它们之间的主要区别在于,对于PCI-PT,该驱动程序仅在Guest OS内部使用,而对于SRIOV,则使用Host OS驱动程序(用于创建VF-虚拟功能 )和Guest OS驱动程序来控制SR-IOV VF。 瞻博网络撰写了有关PCI-PT和SRIOV的出色细节。



为了澄清起见,值得注意的是PCI直通和SR-IOV是互补技术。 SR-IOV正在将物理功能划分为虚拟功能。 这是在主机OS级别完成的。 同时,主机操作系统将虚拟功能视为另一个PCI / PCIe设备。 他接下来对他们做什么并不重要。

PCI-PT是一种用于在来宾操作系统中转发任何主机操作系统PCI设备的机制,包括由SR-IOV设备创建的虚拟功能


因此,我们检查了虚拟资源的主要类型,下一步是了解虚拟机如何通过网络与外界通信。



虚拟切换



如果有一个虚拟机,并且它具有一个虚拟接口,那么显然会出现将数据包从一个VM传输到另一个VM的问题。 在基于Linux的虚拟机管理程序(例如KVM)中,可以使用Linux桥接器解决此问题,但是Open vSwitch (OVS)项目已获得广泛接受。
有几种核心功能使OVS能够广泛传播,并成为许多云计算平台(例如Openstack)和虚拟化解决方案使用的事实上的核心数据包交换方法。
  • 网络状态传输-在虚拟机管理程序之间迁移VM时,任务是传输ACL,QoS,L2 / L3转发表等。 OVS可以做到。
  • 内核和用户空间中数据包传输机制(数据路径)的实现
  • CUPS(控制/用户平面分离)架构-允许您将数据包处理功能转移到专用芯片组(例如,Broadcom和Marvell芯片组可以做到),并通过控制平面OVS对其进行控制。
  • 支持远程流量控制方法-OpenFlow协议(hi,SDN)。


乍一看,OVS架构看上去很吓人,但是乍一看。


要使用OVS,您需要了解以下内容:
  • 数据路径 -包在这里处理。 类比是铁开关的开关结构。 数据路径包括已在数据路径中编程的接收数据包,处理报头,流表中的匹配项。 如果OVS在内核中运行,它将作为内核模块实现。 如果OVS在用户空间中运行,则这是用户空间Linux中的一个过程。
  • vswitchdovsdb是用户空间中的守护程序,它直接实现交换机的功能,存储配置,设置流向数据路径并对其进行编程。
  • OVS设置和故障排除工具包-ovs-vsctl,ovs-dpctl,ovs-ofctl,ovs-appctl 。 在ovsdb中注册端口配置,注册应切换到哪个流,收集统计信息等等所需的全部操作。 好人为此写了一篇文章


虚拟机的网络设备如何以OVS结尾?

为了解决此问题,我们需要以某种方式将位于操作系统用户空间中的虚拟接口与位于内核中的数据路径OVS互连起来。

在Linux操作系统中,数据包通过两个特殊接口在内核和用户空间进程之间传输。 两个接口都使用向/从特殊文件写入/读取数据包来将数据包从用户空间进程传输到内核,反之亦然-文件描述符(FD)(如果数据路径OVS位于内核中,这是虚拟交换性能较差的原因之一-每个数据包)需要通过FD进行写入/读取)

  • TUN(隧道)-在L3模式下工作的设备,允许您将IP数据包写入FD或从FD读取。
  • TAP(网络分接头)-与tun接口相同+可以对以太网帧执行操作,即 在L2模式下工作。




这就是为什么当虚拟机在Host OS中运行时,您可以使用ip链接ifconfig命令查看创建的TAP接口的原因-这是virtio的“响应”部分,在内核Host OS中是“可见”的。还值得注意的是,TAP接口与虚拟机中的virtio接口具有相同的MAC地址。

可以使用ovs-vsctl命令将TAP接口添加到OVS-然后,由OVS切换到TAP接口的任何程序包都将通过文件描述符传输到虚拟机。

创建虚拟机的实际过程可能有所不同,即 首先,您可以创建一个OVS桥,然后告诉虚拟机创建连接到该OVS的接口,反之亦然。


现在,如果我们需要能够在同一虚拟机管理程序上运行的两个或多个虚拟机之间传输数据包,我们只需要创建一个OVS桥并使用ovs-vsctl命令向其添加TAP接口。可以轻松地搜索需要哪些团队。

虚拟机管理程序上可能有多个OVS桥接器,例如,这就是Openstack Neutron的工作方式,或者虚拟机可以位于不同的命名空间中以实现多租户。

如果虚拟机位于不同的OVS桥接器中?

为了解决这个问题,还有另一种工具-veth对Veth对可以表示为通过电缆连接的一对网络接口-一切“飞”入一个接口,从另一个“飞”入。Veth对用于将多个OVS桥接器或Linux桥接器彼此连接。另一个重要的一点是,veth对的一部分可以位于不同的命名空间Linux OS中,也就是说,veth对还可以用于在网络级别上相互通信命名空间。

虚拟化工具-libvirt,virsh等



在前面的章节中,我们研究了虚拟化的理论基础,在这一章中,我们将讨论可直接用于用户的工具,这些工具可用于在KVM虚拟机管理程序上启动和更改虚拟机。
让我们详细介绍三个主要组件,它们涵盖了虚拟机所有类型操作的90%:

  • libvirt
  • virsh CLI
  • virt-install


, CLI-, , , qemu_system_x86_64 virt manager, . Cloud-, Openstack, , libvirt.


libvirt


libvirt是一个大型开源项目,它开发了用于管理虚拟机管理程序的一组工具和驱动程序。它不仅支持QEMU / KVM,还支持ESXi,LXC等。
其流行的主要原因是用于通过一组XML文件进行交互的结构化且直观的界面,以及能够通过API进行自动化的功能。应当注意,libvirt并未描述虚拟机监控程序的所有可能功能,它只是从项目参与者的角度提供了一个方便的界面,用于使用有用的虚拟机监控程序功能

是的,libvirt是当今虚拟化世界中的事实上的标准。只需查看使用libvirt 的应用程序列表即可



关于libvirt的好消息是,所有必需的软件包都已预先安装在所有最常用的主机操作系统(Ubuntu,CentOS和RHEL)中,因此您很有可能不必编译必需的软件包并编译libvirt。在最坏的情况下,您将必须使用适当的批处理安装程序(apt,yum等)。

初始安装和启动后,libvirt默认会创建Linux桥virbr0及其最小配置。

例如,这就是为什么在安装Ubuntu Server时,会在ifconfig Linux bridge virbr0命令的输出中看到的原因-这是运行libvirtd守护程序的结果


该Linux桥接器不会连接到任何物理接口,但是,它可用于在单个虚拟机管理程序内通信虚拟机。Libvirt当然可以与OVS一起使用,但是,为此,用户必须使用适当的OVS命令独立创建OVS桥。

创建虚拟机所需的任何虚拟资源(计算,网络,存储)在libvirt中均表示为对象。一组不同的XML文件负责描述和创建这些对象的过程。

详细描述创建虚拟网络和虚拟存储的过程没有多大意义,因为libvirt文档中对该应用程序进行了很好的描述:



在libvirt术语中,具有所有连接的PCI设备的虚拟机本身称为域。这也是libvirt内部的一个对象,由一个单独的XML文件描述。

严格来说,此XML文件是具有所有虚拟资源(RAM,处理器,网络设备,磁盘等)的虚拟机。通常,此XML文件称为libvirt XML或转储XML。
不太可能会有人了解libvirt XML的所有参数,但是,有文档时就不需要这样做。

通常,用于Ubuntu Desktop Guest OS的libvirt XML将非常简单-40至50行。由于在libvirt XML(NUMA拓扑,CPU拓扑,CPU固定等)中还描述了所有性能优化,因此对于网络功能,libvirt XML可能非常复杂并且包含数百行。任何将其软件作为虚拟机发布的网络设备制造商都推荐了libvirt XML的示例。

virsh CLI



virsh实用程序是用于管理libvirt的“本地”命令行。它的主要目的是管理描述为XML文件的libvirt对象。典型示例是开始,停止,定义,销毁等。也就是说,对象的生命周期-生命周期管理。libvirt

文档中也提供了所有virsh命令和标志的描述

安装virt



用于与libvirt进行交互的另一个实用程序。主要优点之一是您不必处理XML格式,而可以使用virsh-install中可用的标志。第二个重点是网络上的大量示例和信息。

因此,无论使用哪种实用程序,最终都是由libvirt控制虚拟机管理程序,因此了解其操作的架构和原理很重要。



结论



在本文中,我们研究了使用虚拟机所需的最少理论知识。我故意不给出命令的实际示例和结论,因为可以在Web上找到尽可能多的示例,并且我没有设定编写“循序渐进指南”的任务。如果您对特定主题或技术感兴趣,请留下您的评论并提出问题。



有用的链接






谢谢啦


  • 我的同事,虚拟网络开发专家Alexander Shalimov用于评论和编辑。
  • 我的同事,虚拟化领域专家Yevgeny Yakovlev提出了意见和更正。

Source: https://habr.com/ru/post/zh-CN467801/


All Articles