窃取:谁从虚拟机中窃取处理器时间



你好 我想用通俗易懂的语言讲述虚拟机内部窃取现象的发生机理,以及我们在他的研究期间设法发现的一些非显而易见的工件,我必须作为云平台Mail.ru Cloud Solutions的技术人员投入其中。 该平台在KVM上运行。

CPU窃取时间是指虚拟机在执行过程中没有收到处理器资源的时间。 仅在虚拟化环境中的来宾操作系统中考虑此时间。 这些非常分配的资源在生活中使用的原因非常模糊。 但是我们决定弄清楚,甚至进行了一系列的实验。 并不是说我们现在对盗窃一无所知,但现在我们会告诉您一些有趣的事情。

1.什么是偷


因此,窃取是一个指标,表明虚拟机内部的进程缺少处理器时间。 如KVM内核补丁中所述 ,窃取是系统管理程序在主机OS上执行其他进程的时间,尽管它已将虚拟机进程排队等待执行。 即,窃取被认为是进程准备执行的时间与处理器分配给进程的时间之间的差。

内核内核从管理程序接收度量窃取。 同时,系统管理程序并没有确切指定其执行的其他进程,只是“我忙着,我不能给你时间”。 在KVM上, 补丁程序中已添加了窃取计数支持。 这里有两个关键点:

  • 虚拟机从虚拟机管理程序了解有关盗窃的信息。 也就是说,从损失的角度来看,对于虚拟机本身上的进程,它是一种间接测量,可能会遭受各种失真。
  • 系统管理程序不会与虚拟机共享有关他与他人进行的操作的信息-主要是他不花时间在虚拟机上。 因此,虚拟机本身无法检测到窃取索引中的失真,这可以通过竞争进程的性质来估计。

2.什么会影响抢断


2.1。 计算偷


实际上,窃取被认为与正常的CPU使用时间大致相同。 关于如何考虑处置的信息不多。 可能是因为大多数人认为这个问题显而易见。 但是这里也有陷阱。 要熟悉此过程,您可以阅读Brendann Gregg文章 :您将了解到处置计算中的一些细微差别以及由于以下原因该计算将是错误的情况:

  • 处理器过热,在此期间时钟周期被跳过。
  • 打开/关闭turbo boost,其结果是处理器时钟频率改变。
  • 使用处理器节能技术(例如SpeedStep)时发生的时间量变化。
  • 计算平均值的问题:一分钟内80%的利用率估计值可能会使100%的短期突发事件蒙上阴影。
  • 循环锁(自旋锁)导致处理器被丢弃,但用户进程看不到其执行进度。 结果,尽管该进程实际上不会消耗处理器时间,但该进程的估计处理器利用率将为100%。

我没有找到描述类似的偷窃计算方法的文章(如果您知道,请在评论中分享)。 但是,从来源来看,计算机制与处置方式相同。 只是在内核中直接添加了另一个计数器,用于KVM进程(虚拟机进程),该计数器计算KVM进程处于处理器时间待机状态的时间长度。 计数器从其规格中获取有关处理器的信息,并查看虚拟进程是否已利用其所有的滴答声。 如果仅此而已,那么我们认为处理器仅参与虚拟机的处理。 否则,我们通知处理器正在做其他事情,出现了盗窃现象。

窃取计数过程遇到与常规回收计数相同的问题。 并不是说这类问题经常出现,但看起来却令人沮丧。

2.2。 KVM上的虚拟化类型


一般来说,虚拟化有三种类型,并且所有这些都受KVM支持。 虚拟化的类型可以确定发生盗窃的机制。

广播节目 在这种情况下,虚拟机操作系统与虚拟机管理程序的物理设备的运行大致如下所示:

  1. 来宾操作系统将命令发送到其来宾设备。
  2. 来宾设备驱动程序接受该命令,生成对设备BIOS的请求,然后将其发送到管理程序。
  3. 系统管理程序进程将命令转换为物理设备的命令,从而使其更加安全。
  4. 物理设备驱动程序接受修改后的命令,并将其发送到物理设备本身。
  5. 命令执行的结果沿同一路径返回。

转换的优点是它允许您模拟任何设备,并且不需要特殊准备操作系统内核。 但是首先,您必须付出代价。

硬件虚拟化 。 在这种情况下,硬件级别的设备可以理解来自操作系统的命令。 这是最快,最好的方法。 但是,不幸的是,并非所有物理设备,系统管理程序和来宾OS都支持它。 当前,支持硬件虚拟化的主要设备是处理器。

准虚拟化(paravirtualization) 。 KVM上最常见的设备虚拟化版本,通常是来宾操作系统的最常见虚拟化模式。 它的特点是可以与虚拟机管理程序的某些子系统一起使用(例如,与网络或磁盘堆栈一起使用),或者使用虚拟机管理程序API进行内存页面分配,而无需转换低级命令。 这种虚拟化方法的缺点是需要修改来宾操作系统的内核,以便它可以使用此API与管理程序进行交互。 但是通常这可以通过在来宾操作系统上安装特殊驱动程序来解决。 在KVM中,此API称为virtio API

与转换相比,使用半虚拟化可以通过直接从虚拟机向主机管理程序进程发送命令来显着减少物理设备的路径。 这使您可以加快虚拟机内部所有指令的执行。 在KVM中,virtio API对此负责,它仅适用于某些设备,例如网络或磁盘适配器。 这就是为什么在虚拟机中放置virtio驱动程序的原因。

这种加速的不利方面是,并非虚拟机内部运行的所有进程都保留在其中。 这会产生一些特殊效果,可能导致偷窃现象的出现。 我建议使用用于虚拟I / O的API开始详细研究此问题:virtio

2.3。 公平的舍灵


实际上,虚拟机管理程序上的虚拟化是一个普通的过程,遵循Linux内核中的调度规则(进程之间的资源分配),因此我们将对其进行更详细的考虑。

Linux使用所谓的CFS(完全公平调度程序),自内核2.6.23起它已成为默认调度程序。 要了解此算法,您可以阅读Linux Kernel Architecture或源代码。 CFS的本质是进程之间的处理器时间分配,具体取决于它们的执行持续时间。 该过程所需的处理器时间越长,则收到的时间就越少。 这保证了所有进程的“诚实”执行-从而一个进程不会始终占据所有处理器,其他进程也可以执行。

有时,这种范例会导致有趣的伪像。 长期使用Linux的用户可能会记得运行要求苛刻的类似于编译器的应用程序时常规桌面文本编辑器的消失。 发生这种情况是因为桌面应用程序的非资源密集型任务与积极消耗资源的任务(例如编译器)竞争。 CFS认为这是不诚实的,因此它会定期停止文本编辑器并允许处理器处理编译器任务。 使用sched_autogroup机制已对此进行了纠正,但是任务之间CPU时间分配的许多其他功能仍然保留。 实际上,这个故事不是关于CFS的糟糕情况,而是试图引起人们注意处理器时间的“诚实”分配并不是最琐碎的任务。

舍杜勒的另一个重要观点是抢占。 这是从处理器驱动窃听过程并使其他人正常工作所必需的。 流放过程称为上下文切换,处理器上下文切换。 在这种情况下,将保存任务的整个上下文:堆栈的状态,寄存器等,然后进程等待,然后由另一个进程代替。 对于OS而言,这是一项昂贵的操作,并且很少使用,但实际上没有错。 频繁切换上下文可能表明OS中存在问题,但是通常情况下它会连续发生并且没有特别说明。

需要用一个很长的故事来解释一个事实:诚实的Linux sheduler尝试消耗的处理器资源越多,停止它的速度就越快,以便其他进程也可以工作。 这是否正确是一个复杂的问题,在不同的负载下将以不同的方式解决。 在Windows中,直到最近,sheduler一直专注于桌面应用程序的优先处理,因为后台程序可能会挂起。 Sun Solaris具有五种不同的卸载程序。 在开始虚拟化时,他们添加了第六个“ 公平共享调度程序” ,因为前五个未充分利用Solaris Zones虚拟化。 我建议使用诸如《 Solaris Internals:Solaris 10和OpenSolaris内核体系结构》或《 了解Linux内核》之类的书开始对此问题进行详细研究。

2.4。 如何监控盗窃?


与其他任何处理器指标一样,监视虚拟机内部的窃取也很简单:您可以使用任何方法删除处理器指标。 最主要的是,虚拟机在Linux上。 由于某些原因,Windows不会向其用户提供此类信息。 :(


top命令的输出:处理器负载详细信息,在最右边的列中-窃取

尝试从管理程序获取此信息时会遇到困难。 您可以尝试通过例如平均负载(LA)参数(在队列中等待执行的进程数的平均值)来预测主机上的窃取。 计算此参数的方法并不简单,但是通常,如果按处理器线程数标准化的LA大于1,则表明Linux服务器有些过载。

这些过程还在等待什么? 显而易见的答案是处理器。 但是答案并不完全正确,因为有时处理器是空闲的,并且LA会翻转。 记住NFS如何下降以及LA如何增长 。 它与磁盘以及其他输入/输出设备大致相同。 但是实际上,进程可以期待与I / O设备相关联的任何物理锁定和逻辑锁定(例如互斥锁)的结束。 这还包括硬件级别的锁(磁盘上的相同答案)或逻辑(所谓的锁原语,其中包括一堆实体,互斥量自适应和自旋,信号量,条件变量,rw锁,ipc锁...)。

LA的另一个功能是将其视为操作系统的平均值。 例如,100个进程争用一个文件,然后LA = 50。 如此巨大的价值似乎表明该操作系统很糟糕。 但是对于其他歪曲的代码来说,这可能是一种正常状态,尽管事实上这仅对他不利,并且操作系统中的其他进程也不会受到影响。

由于这种平均(不少于一分钟),用LA指示器确定某件事情并不是最感激的,在特定情况下结果非常不确定。 如果尝试解决问题,您会发现Wikipedia文章和其他可用资源中仅描述了最简单的情况,而没有对该过程进行深入的说明。 在此,我再次将所有感兴趣的内容发送给Brendann Gregg-继续提供链接。 英文的懒惰对他来说他关于洛杉矶的热门文章翻译

3.特效


现在,让我们来谈谈我们遇到的主要盗窃案件。 我将告诉您它们如何遵循前述内容,以及它们与虚拟机监控程序上的指标的关系。

回收利用 。 最简单,最频繁:重新使用管理程序。 确实,有许多正在运行的虚拟机,其中有大量的处理器消耗,竞争激烈,LA的利用率超过1(由处理器线程标准化)。 在所有virtualoks内部,一切都会变慢。 从虚拟机管理程序传输的窃取也在增长,有必要重新分配负载或关闭某人。 通常,一切都是合乎逻辑且易于理解的。

准虚拟化与单个实例 。 虚拟机管理程序上只有一个虚拟机,它只消耗一小部分,但是却给输入/输出(例如磁盘)带来了很大的负担。 从其中的某个地方出现小偷窃,最高可达10%(如几次实验所示)。

这个案子很有趣。 由于半虚拟化驱动程序级别的锁定,在这里出现偷窃。 中断在虚拟机内部创建,由驱动程序处理,然后转到管理程序。 由于虚拟机的虚拟机管理程序上的中断处理,它看起来像一个已发送的请求,可以执行并等待处理器,但是它们没有给处理器时间。 Virtualka认为这次被偷了。

这种情况发生在发送缓冲区时,缓冲区进入虚拟机管理程序的内核空间,我们开始等待它。 尽管从virtualka的角度来看,他应该立即返回。 因此,根据窃取计算算法,这次被认为是被盗的。 最有可能的是,在这种情况下,可能存在其他机制(例如,处理其他一些sys调用),但是它们应该没有太大不同。

Sheduler反对沉重的virtualoks 。 当一台虚拟机遭受的盗窃比其他虚拟机更多时,它将与Sheduler精确连接。 该过程对处理器的负载越强,则sheduler越快将其排出,以便其他处理器也可以工作。 如果虚拟机消耗了一点,她几乎看不到偷窃行为:老实说,她的进程坐着等着,有必要给他更多的时间。 如果虚拟机在其所有内核上产生最大负载,则通常会将其从处理器中驱逐出去,并尽量不浪费大量时间。

更糟的是,当虚拟机内部的进程试图获得更多的处理器时,因为它们无法应对数据处理。 然后,由于诚实的优化,系统管理程序上的操作系统将提供越来越少的处理器时间。 此过程像雪崩一样发生,并且窃取跃升至天堂,尽管其他虚拟机可能几乎没有注意到它。 内核越多,分配给该计算机的性能就越差。 简而言之,具有多个内核的高负载虚拟机受害最大。

洛杉矶低,但是有抢断 。 如果LA约为0.7(即虚拟机管理程序似乎负载不足),但是在各个虚拟机中观察到盗窃:

  • 上面描述的带有半虚拟化的选项。 尽管虚拟机管理程序一切正常,但虚拟机可以接收指向窃取的指标。 根据我们的实验结果,这种窃取选项不会超过10%,并且不会对虚拟机内部的应用程序性能产生重大影响。
  • 错误地考虑了参数LA。 更准确地说,在每个特定时刻它被认为是正确的,但是平均一分钟,结果却被低估了。 例如,如果一个虚拟机在虚拟机管理程序的三分之一时间内消耗了所有处理器的时间恰好是半分钟,那么在虚拟机管理程序上每分钟的LA将为0.15; 四个同时工作的虚拟机将得出0.6。 而且每人半分钟在洛杉矶的抢断率高达25%,这一事实再也无法解决。
  • 同样,由于sheduler决定某人吃得太多,所以让这个等待。 同时,我正在切换上下文,处理中断并进行其他重要的系统操作。 结果,某些虚拟机看不到任何问题,而其他虚拟机则出现严重的性能下降。

4.其他变形


还有百万个原因会扭曲虚拟机上处理器时间的真实回报。 例如,超跑步和NUMA会增加计算的复杂性。 他们完全混淆了内核的选择,以执行该过程,因为sheduler使用系数-权重,这在切换上下文时使计算更加困难。

由于诸如turbo boost或相反的节能模式之类的技术而导致失真,当计算利用率时,该失真会人为地增加或减少服务器上的频率甚至时间片。 由于另一线程性能的提高,打开涡轮增压会降低一个处理器线程的性能。 此时,有关当前处理器频率的信息不会传输到虚拟机,并且她认为有人正在占用她的时间(例如,她请求2 GHz,但收到了一半)。

通常,可能有很多导致失真的原因。 在特定的系统中,您可能会找到其他东西。 最好从我上面链接的书开始,并使用诸如perf,sysdig,systemtap之类的实用程序从管理程序中获取统计信息,其中有数十种

5.结论


  1. 由于半虚拟化,可能会发生一定程度的窃取,并且可以认为这是正常的。 在Internet上,他们写道该值可以为5-10%。 它取决于虚拟机内部的应用程序以及它对物理设备造成的负载。 重要的是要注意虚拟机内部应用程序的感觉。
  2. 虚拟机管理程序和虚拟机上的窃取之间的负载比率并非始终是明确互连的,在特定情况下,不同的负载下,两种窃取估计值都可能是错误的。
  3. 调度程序不喜欢要求很多的进程。 他试图减少那些要求更多的人。 大型虚拟机是邪恶的。
  4. 在没有半虚拟化的情况下,小偷可能是很正常的做法(考虑到虚拟机内部的负载,邻居负载的特征,线程之间的负载分配以及其他因素)。
  5. 如果要查找特定系统中的窃取,则必须研究各种选择,收集指标,仔细分析它们并考虑如何均匀分配负载。 任何情况下都有可能出现偏差,必须通过实验确认或在内核调试器中查看。

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


All Articles