Controles de recursos de máquina virtual

Aplica-se a: Windows Server 2022, Windows Server 2016, Microsoft Hyper-V Server 2016, Windows Server 2019 e Microsoft Hyper-V Server 2019

Este artigo descreve os controles de recurso e isolamento do Hyper-V para máquinas virtuais. Esses recursos, que nos referiremos como Grupos de CPU de Máquina Virtual ou apenas "grupos de CPU", foram introduzidos Windows Server 2016. Os grupos de CPU permitem que os administradores do Hyper-V gerenciem e alocem melhor os recursos de CPU do host em máquinas virtuais convidadas. Usando grupos de CPU, os administradores do Hyper-V podem:

  • Crie grupos de máquinas virtuais, com cada grupo com alocações diferentes do total de recursos de CPU do host de virtualização, compartilhados em todo o grupo. Isso permite que o administrador do host implemente classes de serviço para diferentes tipos de VMs.

  • Definir limites de recursos de CPU para grupos específicos. Esse "limite de grupo" define o limite superior para recursos de CPU do host que todo o grupo pode consumir, impondo efetivamente a classe de serviço desejada para esse grupo.

  • Restringir um grupo de CPU para ser executado somente em um conjunto específico dos processadores do sistema host. Isso pode ser usado para isolar VMs que pertencem a diferentes grupos de CPU uns dos outros.

Gerenciando grupos de CPU

Os grupos de CPU são gerenciados por meio do Serviço de Computação do Host Hyper-V ou HCS. Uma ótima descrição do HCS, seus gêneses, links para as APIs do HCS e muito mais está disponível no blog da equipe de Virtualização da Microsoft na postagem Introdução ao HCS (Serviço de Computação de Host).

Observação

Somente o HCS pode ser usado para criar e gerenciar grupos de CPU; as interfaces de gerenciamento do Hyper-V Manager, WMI e PowerShell não são suportadas por grupos de CPU.

A Microsoft fornece um utilitário de linha de comando, cpugroups.exe, no Centro de Download da Microsoft que usa a interface HCS para gerenciar grupos de CPU. Esse utilitário também pode exibir a topologia de CPU de um host.

Como funcionam os grupos de CPU

A alocação de recursos de computação do host em grupos de CPU é imposta pelo hipervisor hyper-V, usando um limite de grupo de CPU computado. O limite do grupo de CPU é uma fração da capacidade total da CPU para um grupo de CPU. O valor do limite de grupo depende da classe de grupo ou do nível de prioridade atribuído. O limite do grupo computado pode ser pensado como "um número de lps de tempo de CPU". Esse orçamento de grupo é compartilhado, portanto, se apenas uma única VM estivesse ativa, ela poderia usar a alocação de CPU de todo o grupo para si mesma.

O limite do grupo de CPU é calculado como G = n x C, em que:

  • G é a quantidade de LP de host que queremos atribuir ao grupo
  • n é o número total de LPs (processadores lógicos) no grupo
  • C é a alocação máxima de CPU , ou seja, a classe de serviço desejada para o grupo, expressa como um percentual da capacidade de computação total do sistema

Por exemplo, considere um grupo de CPU configurado com 4 LPs (processadores lógicos) e um limite de 50%.

  • G = n * C
  • G = 4 * 50%
  • G = 2 LP de tempo de CPU para todo o grupo

Neste exemplo, o grupo de CPU G é alocado com 2 LPs de tempo de CPU.

Observe que o limite do grupo se aplica independentemente do número de máquinas virtuais ou processadores virtuais vinculados ao grupo e independentemente do estado (por exemplo, desligamento ou iniciado) das máquinas virtuais atribuídas ao grupo de CPU. Portanto, cada VM vinculada ao mesmo grupo de CPU receberá uma fração da alocação total de CPU do grupo, e isso mudará com o número de VMs vinculadas ao grupo de CPU. Portanto, como as VMs são vinculadas ou não vinculadas de um grupo de CPU, o limite geral do grupo de CPU deve ser reajustado e definido para manter o limite por VM resultante desejado. O administrador de host da VM ou a camada de software de gerenciamento de virtualização é responsável por gerenciar os limites de grupo conforme necessário para obter a alocação de recursos de CPU por VM desejada.

Classes de serviço de exemplo

Vamos dar uma olhada em alguns exemplos simples. Para começar, suponha que o administrador do host Hyper-V gostaria de dar suporte a duas camadas de serviço para VMs convidadas:

  1. Uma camada "C" de baixo nível. Vamos dar a essa camada 10% dos recursos de computação de todo o host.

  2. Uma camada "B" de intervalo médio. Essa camada é alocada a 50% dos recursos de computação do host inteiro.

Neste ponto em nosso exemplo, declararemos que nenhum outro controle de recurso de CPU está em uso, como limites de VM individuais, pesos e reservas. No entanto, os limites de VM individuais são importantes, pois veremos um pouco mais tarde.

Para simplificar, vamos supor que cada VM tenha 1 VP e que nosso host tenha 8 LPs. Vamos começar com um host vazio.

Para criar a camada "B", o administrador de host define o limite do grupo como 50%:

  • G = n * C
  • G = 8 * 50%
  • G = 4 LP's de tempo de CPU para todo o grupo

O administrador do host adiciona uma única VM da camada "B". Neste ponto, nossa VM da camada "B" pode usar no máximo 50% da CPU do host ou o equivalente a 4 LPs em nosso sistema de exemplo.

Agora, o administrador adiciona uma segunda VM "Camada B". A alocação do grupo de CPU é dividida igualmente entre todas as VMs. Temos um total de 2 VMs no Grupo B, portanto, cada VM agora obtém metade do total do Grupo B de 50%, 25% cada ou o equivalente a 2 LPs de tempo de computação.

Definindo limites de CPU em VMs individuais

Além do limite do grupo, cada VM também pode ter um "limite de VM" individual. Controles de recursos de CPU por VM, incluindo um limite de CPU, peso e reserva, fazem parte do Hyper-V desde sua introdução. Quando combinado com um limite de grupo, um limite de VM especifica a quantidade máxima de CPU que cada VP pode obter, mesmo que o grupo tenha recursos de CPU disponíveis.

Por exemplo, o administrador do host pode querer colocar um limite de 10% da VM em VMs "C". Dessa forma, mesmo que a maioria dos VPs "C" fique ociosa, cada VP nunca poderá obter mais de 10%. Sem um limite de VM, as VMs "C" podem atingir o desempenho de forma oportunista além dos níveis permitidos por sua camada.

Isolando grupos de VMs para processadores de host específicos

Os administradores de host do Hyper-V também podem querer a capacidade de dedicar recursos de computação a uma VM. Por exemplo, imagine que o administrador quisesse oferecer uma VM "A" premium com um limite de classe de 100%. Essas VMs Premium também exigem a menor latência e tremência de agendamento possíveis; ou seja, eles podem não ser des agendados por nenhuma outra VM. Para obter essa separação, um grupo de CPU também pode ser configurado com um mapeamento de afinidade lp específico.

Por exemplo, para ajustar uma VM "A" no host em nosso exemplo, o administrador criaria um novo grupo de CPU e definiria a afinidade de processador do grupo para um subconjunto dos LPs do host. Os grupos B e C seriam afiliados aos LPs restantes. O administrador poderia criar uma única VM no Grupo A, que teria acesso exclusivo a todos os LPs no Grupo A, enquanto os grupos de camada inferior B e C iam compartilhar os LPs restantes.

Segregando VPs raiz de VPs convidados

Por padrão, o Hyper-V criará um VP raiz em cada LP físico subjacente. Esses VPs raiz são estritamente mapeados 1:1 com os LPs do sistema e não migram – ou seja, cada VP raiz sempre será executado no mesmo LP físico. Os VPs convidados podem ser executados em qualquer LP disponível e compartilharão a execução com VPs raiz.

No entanto, pode ser desejável separar completamente a atividade de VP raiz de VPs convidados. Considere nosso exemplo acima em que implementamos uma VM de camada "A" premium. Para garantir que as VPs da VM "A" tenham a menor latência e "tremidade" ou variação de agendamento, queremos executar em um conjunto dedicado de LPs e garantir que a raiz não seja executado nesses LPs.

Isso pode ser feito usando uma combinação da configuração "minroot", que limita a partição do sistema operacional host à execução em um subconjunto do total de processadores lógicos do sistema, juntamente com um ou mais grupos de CPU afiliados.

O host de virtualização pode ser configurado para restringir a partição do host a LPs específicos, com um ou mais grupos de CPU afiliados aos LPs restantes. Dessa maneira, as partições raiz e convidado podem ser executados em recursos de CPU dedicados e completamente isolados, sem compartilhamento de CPU.

Para obter mais informações sobre a configuração "minroot", consulte Gerenciamento de recursos de CPU do host Hyper-V.

Usando a ferramenta CpuGroups

Vamos ver alguns exemplos de como usar a ferramenta CpuGroups.

Observação

Os parâmetros de linha de comando para a ferramenta CpuGroups são passados usando apenas espaços como delimitadores. Nenhum caractere '/' ou '-' deve continuar a opção de linha de comando desejada.

Descobrindo a topologia da CPU

A execução de CpuGroups com o GetCpuTopology retorna informações sobre o sistema atual, conforme mostrado abaixo, incluindo o índice LP, o nó NUMA ao qual o LP pertence, as IDs de Pacote e Núcleo e o índice VP RAIZ.

O exemplo a seguir mostra um sistema com dois soquetes de CPU e nós NUMA, um total de 32 LPs e vários threadings habilitados e configurados para habilitar o Minroot com 8 VPs raiz, 4 de cada nó NUMA. Os LPs que têm VPs raiz têm um RootVpIndex >= 0; LPs com um RootVpIndex de -1 não estão disponíveis para a partição raiz, mas ainda são gerenciados pelo hipervisor e executarão VPs convidados conforme permitido por outras definições de configuração.

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

Exemplo 2 – Imprimir todos os grupos de CPU no host

Aqui, listamos todos os grupos de CPU no host atual, sua GroupId, o limite de CPU do grupo e os indicies de LPs atribuídos a esse grupo.

Observe que os valores válidos de limite de CPU estão no intervalo [0, 65536], e esses valores expressam o limite do grupo em porcentagem (por exemplo, 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

Exemplo 3 – Imprimir um único grupo de CPU

Neste exemplo, consultaremos um único grupo de CPU usando GroupId como um filtro.

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

Exemplo 4 – Criar um novo grupo de CPU

Aqui, criaremos um novo grupo de CPU, especificando a ID do Grupo e o conjunto de LPs a atribuir ao grupo.

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

Agora, exibe nosso grupo recém-adicionado.

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

Exemplo 5 – Definir o limite do grupo de CPU como 50%

Aqui, definiremos o limite do grupo de CPU como 50%.

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

Agora, vamos confirmar nossa configuração exibindo o grupo que atualizamos.

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

Exemplo 6 – Imprimir IDs de grupo de CPU para todas as VMs no host

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

Exemplo 7 – Desavincular uma VM do grupo de CPU

Para remover uma VM de um grupo de CPU, de definido como CpuGroupId da VM como o GUID NULL. Isso desvincula a VM do grupo de 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

Exemplo 8 – Vincular uma VM a um grupo de CPU existente

Aqui, adicionaremos uma VM a um grupo de CPU existente. Observe que a VM não deve ser vinculada a nenhum grupo de CPU existente ou a configuração da ID do grupo de CPU falhará.

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

Agora, confirme se a VM G1 está no grupo de CPU desejado.

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

Exemplo 9 – Imprimir todas as VMs agrupadas por ID do grupo de CPU

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

Exemplo 10 – Imprimir todas as VMs para um único grupo de CPU

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

Exemplo 11 – Tentativa de excluir um grupo de CPU não vazio

Somente grupos de CPU vazios, ou seja, grupos de CPU sem VMs vinculadas, podem ser excluídos. A tentativa de excluir um grupo de CPU não vazio falhará.

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

Exemplo 12 – Desavincular a única VM de um grupo de CPU e excluir o grupo

Neste exemplo, vamos usar vários comandos para examinar um grupo de CPU, remover a única VM que pertence a esse grupo e, em seguida, excluir o grupo.

Primeiro, vamos enumerar as VMs em nosso grupo.

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

Vemos que apenas uma única VM, chamada G1, pertence a esse grupo. Vamos remover a VM G1 do nosso grupo definindo a ID do grupo da VM como NULL.

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

E verifique nossa alteração...

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

Agora que o grupo está vazio, podemos excluí-lo com segurança.

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

E confirme se nosso grupo foi embora.

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

Exemplo 13 – Vincular uma VM de volta ao grupo de CPU original

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