Otimizando o desempenho do KVM em sistemas NUMA

Virtualização, atualmente, significa mais do que apenas consolidar servidores subutilizados. Ultrapassamos a época em que a virtualização em x86 era apenas utilizada para cargas de trabalho pequenas, dada as limitações de escalabilidade e o impacto no desempenho causado pelo hypervisor.

Parece que chegou a vez dos grandes servidores terem o seu lugar ao sol, ou melhor, na nuvem.

E até onde o KVM pode chegar?

Vejamos alguns limites do KVM no Red Hat Enteprise Linux 6:

Número máximo de vCPUs para uma máquina virtual 160
Quantidade máxima de memória para uma máquina virtual 2 TB

São números suficientemente grandes para a maioria das cargas de trabalho existentes.

O fato do KVM estar integrado ao kernel do Linux dá-lhe a possibilidade de aproveitar seus recursos bastante estáveis e eficientes, como o escalonamento de processos, gerenciamento de memória e I/O. Todas estas tecnologias colaboram com sua escalabilidade e, sobretudo, com seu desempenho.

Entretanto, devemos observar algumas características e configurações para conseguirmos extrair o máximo de desempenho das máquinas virtuais com configurações altas. A topologia do NUMA é uma delas.

O que é NUMA?

Historicamente, toda memória em um sistema x86 era igualmente acessada por todas as CPUs. Conhecido como Uniform Memory Access (UMA), o tempo de acesso era exatamente o mesmo, não importando qual CPU executava o processo.

Este comportamento foi alterado nos sistemas x86 mais recentes. No Non-Uniform Memory Access (NUMA), toda memória do sistema é dividida em zonas, chamados de nodes, que são alocados para um determinado CPU ou socket. Sendo assim, um processo consegue acessar sua memória local mais rapidamente que a memória remota (memória local de outro processador ou memória compartilhada entre os processadores).


Sistema NUMA típico com dois nodes

Na figura acima, o CPU2 é um core que pertence ao NUMA Node A e, portanto, um processo executado por ele irá acessar a memória local mais rapidamente do que a memória do Node B, já que para chegar nesta memória é necessário utilizar outro barramento, representado na figura pelo Cross-Node Link.

O problema

Em um servidor bare-metal típico, as versões mais recentes dos principais sistemas operacionais sabem como lidar com o NUMA, otimizando o acesso à memória de acordo com o processador e o seu respectivo node.

Mas quando adicionamos virtualização, tratando-se especificamente do KVM, o sistema operacional virtualizado não tem conhecimento da topologia do NUMA, afetando sua capacidade de otimizar a alocação de memória ao escalonar os processos.

Este cenário fica mais evidente quando executamos máquinas virtuais com configurações altas (maior quantidade de vCPUs e memória), pois aumenta-se o risco de seus respectivos vCPUs e memória não estarem nos mesmos nodes.

E não é apenas a localização dos dados na memória que importa. O número de nodes dentro de uma máquina virtual afeta diretamente o desempenho do sistema, pois é necessário gerenciar os locks para acessá-los, ou seja, quanto maior o número de nodes, maior a divisão destes locks e, consequentemente, menor é a contenção.

A solução

Uma saída para otimizarmos o desempenho em relação a topologia do NUMA é através das configurações de tuning de CPU do KVM, onde é possível fixar os CPUs físicos para uma determinada máquina virtual.

No exemplo de configuração a seguir, especificamos que os 8 vCPUs da nossa máquina virtual executará seus processos nos CPUs físicos de 0 a 7. Também associamos cada vCPU a um determinado CPU físico. Por exemplo, o vCPU0 estará preso ao CPU físico 0, vCPU1 ao CPU físico 1, e assim por diante.

<vcpu cpuset=’0-7′>8 </vcpu>
<cputune>
<vcpupin vcpu=’0′ cpuset=’0’/>
<vcpupin vcpu=’1′ cpuset=’1’/>
<vcpupin vcpu=’2′ cpuset=’2’/>
<vcpupin vcpu=’3′ cpuset=’3’/>
<vcpupin vcpu=’4′ cpuset=’4’/>
<vcpupin vcpu=’5′ cpuset=’5’/>
<vcpupin vcpu=’6′ cpuset=’6’/>
<vcpupin vcpu=’7′ cpuset=’7’/>
</cputune>

E supondo que estes 8 vCPUs estejam divididos em dois NUMA nodes, podemos usar a configuração a seguir para definirmos a topologia do NUMA em nossa máquina virtual.

<cpu>
<numa>
<cell cpus=’0-3′ memory=’512000’/>
<cell cpus=’4-7′ memory=’512000’/>
</numa>
</cpu>

Com o conhecimento da topologia do NUMA no servidor físico, podemos trabalhar com estas configurações para fixarmos os vCPUs e definirmos a topologia da máquina virtual, maximizando a alocação de memória em nodes específicos.

Automatizando

Como vimos, é relativamente fácil fixarmos os CPUs e configurarmos a topologia do NUMA manualmente para uma máquina virtual no KVM. Entretanto, mesmo essas configurações podem não ser as melhores em determinados momentos, tendo em vista o dinamismo das cargas de trabalho.

Adicionalmente, ajustes manuais devem ser evitados para não comprometer outras vantagens do sistema de virtualização, como a alta disponibilidade, migração a quente e a própria capacidade de consolidação.

Considerando este cenário, as versões mais recentes do kernel do Linux implementa o recurso AutoNUMA, cujo objetivo é estabelecer as ligações dos processos (incluindo as máquinas virtuais do KVM) com os CPUs físicos dinamicamente, buscando extrair o máximo de desempenho em relação a topologia do NUMA.

Este recurso não existe no kernel do Red Hat Enterprise Linux 6, porém, ele é habilitado por padrão no Red Hat Enterprise Linux 7.

Para verificar o status do AutoNUMA no Red Hat Enterprise Linux 7, utilize o comando:

# cat /sys/kernel/debug/sched_features

Para desabilitá-lo:

# echo NONUMA > /sys/kernel/debug/sched_features

E para habilitá-lo:

# echo 1 > /sys/kernel/mm/autonuma/enabled

O AutoNUMA traz ganhos significativos de desempenho. Desabilitá-lo faz sentido apenas quando o overhead gerado pelos seus cálculos e processo de realocação de memória seja perceptível em cargas de trabalho mais críticas. Neste caso, recomenda-se fazer a configuração manualmente.

Referências

Red Hat. Virtualization limits for Red Hat Enterprise Linux hypervisors. Red Hat Resource Library. Acessado em 04-02-2014.
Red Hat. Domain XML format.Libvirt documentation. Acessado em 04-02-2014.
Arcangeli,Andrea (08-2012). Automatic NUMA CPU Scheduling and Memory Migration .Linux Plumbers Conference. Acessado em 05-02-2014.
Theurer, Andrew (05-2012). KVM and Big VMs. KVM Forum 2012. Acessado em 05-02-2014.

2 comentários sobre “Otimizando o desempenho do KVM em sistemas NUMA

Deixe um comentário para Thiago Girolamo Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *