虚拟机资源控件

适用范围:Windows Server 2022、Windows Server 2016、Microsoft Hyper-V Server 2016、Windows Server 2019、Microsoft Hyper-V Server 2019

本文介绍虚拟机的 Hyper-V 资源和隔离控制。 这些功能(我们称其为虚拟机 CPU 组,或只是"CPU 组")是在 Windows Server 2016。 使用 CPU 组,Hyper-V 管理员可以更好地跨来宾虚拟机管理和分配主机的 CPU 资源。 使用 CPU 组,Hyper-V 管理员可以:

  • 创建虚拟机组,每个组对虚拟化主机的总 CPU 资源分配不同,在整个组中共享。 这允许主机管理员为不同类型的 VM 实现服务类。

  • 将 CPU 资源限制设置为特定组。 此"组上限"设置整个组可能使用的主机 CPU 资源的上限,从而有效地为该组强制实施所需的服务类。

  • 将 CPU 组约束为仅在主机系统处理器的特定集上运行。 这可用于将属于不同 CPU 组的 VM 彼此隔离。

管理 CPU 组

CPU 组通过 Hyper-V 主机计算服务或 HCS 进行管理。 Microsoft 虚拟化团队的博客文章引入主机计算服务 (HCS) 中提供了 HCS 及其 创建方法、HCS API 链接等的详细说明。

注意

只能使用 HCS 来创建和管理 CPU 组;Hyper-V 管理器小程序、WMI 和 PowerShell 管理接口不支持 CPU 组。

Microsoft 在 Microsoft 下载中心提供命令行实用工具 cpugroups.exe,该实用工具使用 HCS 接口来管理 CPU 组。 此实用工具还可以显示主机的 CPU 拓扑。

CPU 组工作

Hyper-V 虚拟机监控程序使用计算的 CPU 组上限在 CPU 组中分配主机计算资源。 CPU 组上限是 CPU 组的总 CPU 容量的一小部分。 组上限的值取决于分配的组类或优先级级别。 计算组上限可视为"大量 LP 的 CPU 时间"。 此组预算是共享的,因此,如果只有一个 VM 处于活动状态,则它可以将整个组的 CPU 分配用于自身。

CPU 组上限的计算方式为 G = n x C,其中:

  • G 是我们要分配给组的主机 LP 数量
  • n 是组中逻辑处理器 (IP) 总数
  • C 是最大 CPU 分配,即组所需的服务类,以系统总计算容量的百 分比表示

例如,假设一个 CPU 组配置有 4 个逻辑处理器 (4 个 PS) ,上限为 50%。

  • G = n * C
  • G = 4 * 50%
  • G = 整个组的 2 个 LP CPU 时间

此示例为 CPU 组 G 分配了 2 个 LP 的 CPU 时间。

请注意,无论绑定到组的虚拟机或虚拟处理器数量如何,以及状态如何(例如 (分配给 CPU 组的虚拟机的虚拟机的关闭或启动) ,组上限均适用。 因此,绑定到同一 CPU 组的每个 VM 将接收组总 CPU 分配的一小部分,这将会随绑定到 CPU 组的 VM 数而更改。 因此,由于 VM 是绑定 VM 还是从 CPU 组取消绑定 VM,因此必须重新调整和设置总体 CPU 组上限,以保持所需的每个 VM 的上限。 VM 主机管理员或虚拟化管理软件层负责在必要时管理组上限,以实现所需的每 VM CPU 资源分配。

服务的示例类

让我们看一些简单的示例。 首先,假设 Hyper-V 主机管理员希望为来宾 VM 支持两层服务:

  1. 低端"C"层。 我们将为此层提供整个主机计算资源的 10%。

  2. 中等范围的"B"层。 此层分配有整个主机计算资源的 50%。

此时,在我们的示例中,我们将断言没有使用任何其他 CPU 资源控制,例如单个 VM 上限、权重和预留。 但是,单个 VM 上限非常重要,因为稍后我们将看到。

为简单起见,假设每个 VM 都有 1 个 VP,并且主机有 8 个 LPS。 我们将从空主机开始。

若要创建"B"层,主机管理员启动程序将组上限设置为 50% :

  • G = n * C
  • G = 8 * 50%
  • G = 整个组的 4 个 LP 的 CPU 时间

主机管理员添加单个"B"层 VM。 此时,我们的"B"层 VM 最多可以使用主机 CPU 的 50%,或者相当于示例系统中 4 个 IP。

现在,管理员添加了第二个"B 层"VM。 CPU 组的分配在所有 — VM 之间均匀分配。 我们在组 B 中总共有 2 个 VM,因此每个 VM 现在获取组 B 总数 50%、每个 VM 25% 的一半,或相当于 2 个 LPS 的计算时间。

在单个 VM 上设置 CPU 上限

除了组上限外,每个 VM 还可以有单独的"VM 上限"。 自引入 Hyper-V 以来,每个 VM 的 CPU 资源控制(包括 CPU 上限、权重和预留)一直是 Hyper-V 的一部分。 与组上限结合使用时,VM 上限指定每个 VP 可以获取的最大 CPU 量,即使该组具有可用的 CPU 资源。

例如,主机管理员可能想要在"C"VM 上设置 10% 的 VM 上限。 这样,即使大多数"C"IP 处于空闲状态,每个 VP 也永远不会超过 10%。 如果没有 VM 上限,"C"VM 可能会获得超出其层所允许级别的性能。

将 VM 组隔离到特定主机处理器

Hyper-V 主机管理员可能还希望能够将计算资源专用于 VM。 例如,假设管理员想要提供一个类上限为 100% 的高级"A"VM。 这些高级 VM 还需要尽可能低的计划延迟和抖动;也就是说,它们可能不会由任何其他 VM 取消计划。 若要实现这种分离,还可使用特定的 LP 关联映射配置 CPU 组。

例如,为了在主机上适应示例中的"A"VM,管理员将创建新的 CPU 组,将组的处理器关联设置为主机 IP 的子集。 组 B 和 C 将与剩余的 LPS 进行联系。 管理员可以在组 A 中创建单个 VM,然后,该组 A 中所有 LPS 将具有独占访问权限,而可能较低的层组 B 和 C 将共享剩余的 LPS。

将根 IP 与来宾 IP 隔离

默认情况下,Hyper-V 将在每个基础物理 LP 上创建根 VP。 这些根 IP 与系统 LPS 严格映射为 1:1,不会迁移,也就是说,每个根 VP 将始终在同一物理 — LP 上执行。 来宾 IP 可以在任何可用的 LP 上运行,并与根 IP 共享执行。

但是,可能需要将根 VP 活动与来宾 IP 完全分离。 请考虑上述示例,其中我们实现了高级"A"层 VM。 为了确保"A"VM 的 IP 具有尽可能低的延迟和"抖动"或计划变体,我们希望在一组专用的 LPS 上运行它们,并确保根不会在这些 LPS 上运行。

这可以使用"minroot"配置的组合实现,该配置将主机 OS 分区限制为在系统逻辑处理器的子集上运行,以及一个或多个已联合的 CPU 组。

可以将虚拟化主机配置为将主机分区限制为特定的 LPS,其中一个或多个 CPU 组与剩余的 LPS 相连接。 这样,根分区和来宾分区就可以在专用 CPU 资源上运行,并且完全隔离,无需 CPU 共享。

有关"minroot"配置详细信息,请参阅 Hyper-V 主机 CPU 资源管理

使用 CpuGroups 工具

让我们看看如何使用 CpuGroups 工具的一些示例。

注意

CpuGroups 工具的命令行参数仅使用空格作为分隔符传递。 "/"或"-"字符不应继续所需的命令行开关。

发现 CPU 拓扑

使用 GetCpuTopology 执行 CpuGroups 将返回有关当前系统的信息,如下所示,包括 LP 索引、LP 所属的 NUMA 节点、包和核心 ID 以及 ROOT VP 索引。

以下示例演示一个系统,该系统具有 2 个 CPU 套接字和 NUMA 节点,总共启用了 32 个 PS,并启用了多线程,并且配置为启用具有 8 个根 IP 的 Minroot,每个 NUMA 节点 4 个。 具有根 IP 的 IP 的 RootVpIndex > = 0;RootVpIndex 为 -1 的 LPS 不可用于根分区,但仍由虚拟机监控程序管理,并按其他配置设置允许运行来宾 IP。

C:\vm\tools>CpuGroups.exe GetCpuTopology

LpIndex NodeNumber PackageId CoreId RootVpIndex
------- ---------- --------- ------ -----------
      0          0         0      0           0
      1          0         0      0           1
      2          0         0      1           2
      3          0         0      1           3
      4          0         0      2          -1
      5          0         0      2          -1
      6          0         0      3          -1
      7          0         0      3          -1
      8          0         0      4          -1
      9          0         0      4          -1
     10          0         0      5          -1
     11          0         0      5          -1
     12          0         0      6          -1
     13          0         0      6          -1
     14          0         0      7          -1
     15          0         0      7          -1
     16          1         1     16           4
     17          1         1     16           5
     18          1         1     17           6
     19          1         1     17           7
     20          1         1     18          -1
     21          1         1     18          -1
     22          1         1     19          -1
     23          1         1     19          -1
     24          1         1     20          -1
     25          1         1     20          -1
     26          1         1     21          -1
     27          1         1     21          -1
     28          1         1     22          -1
     29          1         1     22          -1
     30          1         1     23          -1
     31          1         1     23          -1

示例 2 – 打印主机上的所有 CPU 组

在这里,我们将列出当前主机上的所有 CPU 组、其 GroupId、组的 CPU 上限,以及分配给该组的 IP 的指令。

请注意,有效的 CPU 上限值在 [0, 65536] 范围内,这些值以百分比表示组上限 (例如 32768 = 50%) 。

C:\vm\tools>CpuGroups.exe GetGroups

CpuGroupId                          CpuCap  LpIndexes
------------------------------------ ------ --------
36AB08CB-3A76-4B38-992E-000000000002 32768  4,5,6,7,8,9,10,11,20,21,22,23
36AB08CB-3A76-4B38-992E-000000000003 65536  12,13,14,15
36AB08CB-3A76-4B38-992E-000000000004 65536  24,25,26,27,28,29,30,31

示例 3 – 打印单个 CPU 组

本示例使用 GroupId 作为筛选器来查询单个 CPU 组。

C:\vm\tools>CpuGroups.exe GetGroups /GroupId:36AB08CB-3A76-4B38-992E-000000000003
CpuGroupId                          CpuCap   LpIndexes
------------------------------------ ------ ----------
36AB08CB-3A76-4B38-992E-000000000003 65536  12,13,14,15

示例 4 – 创建新的 CPU 组

在这里,我们将创建一个新的 CPU 组,并指定组 ID 以及要分配给该组的 LPs 集。

C:\vm\tools>CpuGroups.exe CreateGroup /GroupId:36AB08CB-3A76-4B38-992E-000000000001 /GroupAffinity:0,1,16,17

现在会显示新添加的组。

C:\vm\tools>CpuGroups.exe GetGroups
CpuGroupId                          CpuCap LpIndexes
------------------------------------ ------ ---------
36AB08CB-3A76-4B38-992E-000000000001 65536 0,1,16,17
36AB08CB-3A76-4B38-992E-000000000002 32768 4,5,6,7,8,9,10,11,20,21,22,23
36AB08CB-3A76-4B38-992E-000000000003 65536 12,13,14,15
36AB08CB-3A76-4B38-992E-000000000004 65536 24,25,26,27,28,29,30,31

示例 5 – 将 CPU 组上限设置为50%

在这里,我们将 CPU 组上限设置为50%。

C:\vm\tools>CpuGroups.exe SetGroupProperty /GroupId:36AB08CB-3A76-4B38-992E-000000000001 /CpuCap:32768

现在,让我们通过显示刚刚更新的组来确认设置。

C:\vm\tools>CpuGroups.exe GetGroups /GroupId:36AB08CB-3A76-4B38-992E-000000000001

CpuGroupId                          CpuCap LpIndexes
------------------------------------ ------ ---------
36AB08CB-3A76-4B38-992E-000000000001 32768 0,1,16,17

示例 6 – 为主机上的所有 vm 打印 CPU 组 id

C:\vm\tools>CpuGroups.exe GetVmGroup

VmName                                 VmId                           CpuGroupId
------ ------------------------------------ ------------------------------------
    G2 4ABCFC2F-6C22-498C-BB38-7151CE678758 36ab08cb-3a76-4b38-992e-000000000002
    P1 973B9426-0711-4742-AD3B-D8C39D6A0DEC 36ab08cb-3a76-4b38-992e-000000000003
    P2 A593D93A-3A5F-48AB-8862-A4350E3459E8 36ab08cb-3a76-4b38-992e-000000000004
    G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200 36ab08cb-3a76-4b38-992e-000000000002
    G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC 36ab08cb-3a76-4b38-992e-000000000002

示例 7 – 从 CPU 组取消绑定 VM

若要从 CPU 组中删除 VM,请将设置为 VM 的 CpuGroupId 为 NULL GUID。 这会将 VM 从 CPU 组中解除绑定。

C:\vm\tools>CpuGroups.exe SetVmGroup /VmName:g1 /GroupId:00000000-0000-0000-0000-000000000000

C:\vm\tools>CpuGroups.exe GetVmGroup
VmName                                 VmId                           CpuGroupId
------ ------------------------------------ ------------------------------------
    G2 4ABCFC2F-6C22-498C-BB38-7151CE678758 36ab08cb-3a76-4b38-992e-000000000002
    P1 973B9426-0711-4742-AD3B-D8C39D6A0DEC 36ab08cb-3a76-4b38-992e-000000000003
    P2 A593D93A-3A5F-48AB-8862-A4350E3459E8 36ab08cb-3a76-4b38-992e-000000000004
    G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200 36ab08cb-3a76-4b38-992e-000000000002
    G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC 00000000-0000-0000-0000-000000000000

示例8将 – VM 绑定到现有 CPU 组

此处,我们将 VM 添加到现有 CPU 组。 请注意,VM 不能绑定到任何现有 CPU 组,或设置 CPU 组 id 会失败。

C:\vm\tools>CpuGroups.exe SetVmGroup /VmName:g1 /GroupId:36AB08CB-3A76-4B38-992E-000000000001

现在,确认 VM G1 是否处于所需的 CPU 组中。

C:\vm\tools>CpuGroups.exe GetVmGroup
VmName                                 VmId                           CpuGroupId
------ ------------------------------------ ------------------------------------
    G2 4ABCFC2F-6C22-498C-BB38-7151CE678758 36ab08cb-3a76-4b38-992e-000000000002
    P1 973B9426-0711-4742-AD3B-D8C39D6A0DEC 36ab08cb-3a76-4b38-992e-000000000003
    P2 A593D93A-3A5F-48AB-8862-A4350E3459E8 36ab08cb-3a76-4b38-992e-000000000004
    G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200 36ab08cb-3a76-4b38-992e-000000000002
    G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC 36AB08CB-3A76-4B38-992E-000000000001

示例 9 – 打印按 CPU 组 id 分组的所有 vm

C:\vm\tools>CpuGroups.exe GetGroupVms
CpuGroupId                           VmName                                 VmId
------------------------------------ ------ ------------------------------------
36AB08CB-3A76-4B38-992E-000000000001     G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC
36ab08cb-3a76-4b38-992e-000000000002     G2 4ABCFC2F-6C22-498C-BB38-7151CE678758
36ab08cb-3a76-4b38-992e-000000000002     G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200
36ab08cb-3a76-4b38-992e-000000000003     P1 973B9426-0711-4742-AD3B-D8C39D6A0DEC
36ab08cb-3a76-4b38-992e-000000000004     P2 A593D93A-3A5F-48AB-8862-A4350E3459E8

示例 10 – 打印单个 CPU 组的所有 vm

C:\vm\tools>CpuGroups.exe GetGroupVms /GroupId:36ab08cb-3a76-4b38-992e-000000000002

CpuGroupId                           VmName                                VmId
------------------------------------ ------ ------------------------------------
36ab08cb-3a76-4b38-992e-000000000002     G2 4ABCFC2F-6C22-498C-BB38-7151CE678758
36ab08cb-3a76-4b38-992e-000000000002     G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200

示例 11 – 尝试删除非空的 CPU 组

只有空 CPU 组 — ,即没有绑定 vm 的 cpu 组 — 可以被删除。 尝试删除非空的 CPU 组将失败。

C:\vm\tools>CpuGroups.exe DeleteGroup /GroupId:36ab08cb-3a76-4b38-992e-000000000001
(null)
Failed with error 0xc0350070

示例 12 – 从 CPU 组中取消绑定唯一 VM,并删除组

在此示例中,我们将使用几个命令来检查 CPU 组,删除属于该组的单个 VM,然后删除该组。

首先,让我们来枚举组中的 Vm。

C:\vm\tools>CpuGroups.exe GetGroupVms /GroupId:36AB08CB-3A76-4B38-992E-000000000001
CpuGroupId                           VmName                                VmId
------------------------------------ ------ ------------------------------------
36AB08CB-3A76-4B38-992E-000000000001     G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC

我们发现只有单个 VM (名为 G1)属于此组。 让我们从组中删除 G1 VM,方法是将 VM 的组 ID 设置为 NULL。

C:\vm\tools>CpuGroups.exe SetVmGroup /VmName:g1 /GroupId:00000000-0000-0000-0000-000000000000

并验证我们的更改 .。。

C:\vm\tools>CpuGroups.exe GetVmGroup /VmName:g1
VmName                                 VmId                           CpuGroupId
------ ------------------------------------ ------------------------------------
    G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC 00000000-0000-0000-0000-000000000000

现在,组为空,可以安全地将其删除。

C:\vm\tools>CpuGroups.exe DeleteGroup /GroupId:36ab08cb-3a76-4b38-992e-000000000001

并确认我们的组已消失。

C:\vm\tools>CpuGroups.exe GetGroups
CpuGroupId                          CpuCap                     LpIndexes
------------------------------------ ------ -----------------------------
36AB08CB-3A76-4B38-992E-000000000002 32768  4,5,6,7,8,9,10,11,20,21,22,23
36AB08CB-3A76-4B38-992E-000000000003 65536  12,13,14,15
36AB08CB-3A76-4B38-992E-000000000004 65536 24,25,26,27,28,29,30,31

示例13将 – VM 重新绑定回其原始 CPU 组

C:\vm\tools>CpuGroups.exe SetVmGroup /VmName:g1 /GroupId:36AB08CB-3A76-4B38-992E-000000000002

C:\vm\tools>CpuGroups.exe GetGroupVms
CpuGroupId VmName VmId
------------------------------------ -------------------------------- ------------------------------------
36ab08cb-3a76-4b38-992e-000000000002 G2 4ABCFC2F-6C22-498C-BB38-7151CE678758
36ab08cb-3a76-4b38-992e-000000000002 G3 B0F3FCD5-FECF-4A21-A4A2-DE4102787200
36AB08CB-3A76-4B38-992E-000000000002 G1 F699B50F-86F2-4E48-8BA5-EB06883C1FDC
36ab08cb-3a76-4b38-992e-000000000003 P1 973B9426-0711-4742-AD3B-D8C39D6A0DEC
36ab08cb-3a76-4b38-992e-000000000004 P2 A593D93A-3A5F-48AB-8862-A4350E3459E8