Configurar VMs com reconhecimento de NUMA

Neste documento, descrevemos como configurar clusters e VMs para oferecer suporte a cargas de trabalho de alto desempenho e baixa latência com a eficiência de computação do acesso à memória não uniforme (NUMA, na sigla em inglês). Há instruções sobre como ajustar as configurações do Kubernetes para nós de cluster. Este documento também inclui instruções para configurar máquinas virtuais (VMs) com afinidade de NUMA para que elas sejam programadas e usem os nós NUMA.

Com uma VM compatível com NUMA, toda a comunicação dentro da VM é local para o nó NUMA. A VM com reconhecimento de NUMA evita transações de dados de e para recursos remotos que podem prejudicar o desempenho da VM.

Configurar nós para usar NUMA

As seções a seguir descrevem como configurar os componentes essenciais do Kubernetes para ajustar o nó e garantir que ele possa programar contêineres compatíveis NUMA. Esses nós NUMA são ajustados para otimizar o desempenho da CPU e da memória. Siga as instruções para cada nó em que você quer executar VMs compatíveis NUMA.

Atualizar a configuração do Kubelet

Como parte da configuração do nó para aceitar a afinidade de nó NUMA, é necessário fazer as seguintes alterações na configuração do kubelet:

  • Ativar o gerenciador de CPU com uma política static
  • Ativar o gerenciador de memória com uma política Static
  • Ativar o gerenciador de topologia com uma topologia restricted

Para configurar o kubelet no nó de trabalho, faça o seguinte:

  1. Localize o arquivo kubelet no nó de trabalho e abra-o para edição:

    edit /etc/default/kubelet
    

    Se você não vir o arquivo kubelet, crie-o com o seguinte comando:

    echo "KUBELET_EXTRA_ARGS=\"\"" >> /etc/default/kubelet
    

    Esse comando cria o arquivo kubelet com uma seção KUBELET_EXTRA_ARGS="" vazia.

  2. Para ativar o Gerenciador de CPU com uma política static, adicione a sinalização --cpu-manager-policy=static à seção KUBELET_EXTRA_ARGS="" do arquivo:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static"
    
  3. Para ativar o Gerenciador de memória com uma política Static, adicione a sinalização --memory-manager-policy=Static à seção KUBELET_EXTRA_ARGS="" do arquivo:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static"
    
  4. Para ativar o Gerenciador de topologia com uma política restricted, adicione a sinalização --topology-manager-policy=restricted à seção KUBELET_EXTRA_ARGS="" do arquivo:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted"
    
  5. Verifique a quantidade atual de memória reservada pelo GKE em Bare Metal:

    cat /var/lib/kubelet/kubeadm-flags.env
    

    A saída será semelhante a esta:

    KUBELET_KUBEADM_ARGS="--anonymous-auth=false --authentication-token-webhook=true --authorization-mode=Webhook --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --feature-gates=SeccompDefault=true --kube-reserved=cpu=100m,memory=3470Mi --max-pods=110 --node-ip=192.168.1.190 --node-labels=baremetal.cluster.gke.io/k8s-ip=192.168.1.190,baremetal.cluster.gke.io/namespace=cluster-user001,baremetal.cluster.gke.io/node-pool=node-pool-1,cloud.google.com/gke-nodepool=node-pool-1 --pod-infra-container-image=gcr.io/anthos-baremetal-release/pause-amd64:3.1-gke.5 --provider-id=baremetal://192.168.1.190 --read-only-port=10255 --rotate-server-certificates=true --seccomp-default=true"

    A configuração --kube-reserved=cpu=100m,memory=3470Mi indica que o GKE em Bare Metal reservou 3.470 mebibytes de memória no nó.

  6. Defina a sinalização --reserved-memory na seção KUBELET_EXTRA_ARGS do arquivo kubelet como 100 mebibytes a mais da memória reservada atual para considerar o limite de remoção. Se não houver memória reservada, pule esta etapa.

    Por exemplo, com a memória reservada de 3470Mi do exemplo na etapa anterior, você reserva 3570Mi de memória no arquivo kubelet:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted --reserved-memory=0:memory=3570Mi"
    
  7. Remova arquivos de estado de CPU e memória do diretório /var/lib:

    rm /var/lib/cpu_manager_state
    rm /var/lib/memory_manager_state
    
  8. Reinicie o kubelet:

    systemctl start kubelet
    

Para mais informações sobre essas configurações de política, consulte a seguinte documentação do Kubernetes:

Configurar o nó para usar páginas grandes

Depois de ativar o gerenciador de memória com a política Static, você pode adicionar páginas grandes para melhorar ainda mais o desempenho da carga de trabalho do contêiner nos nós NUMA. As páginas grandes, como o nome sugere, permitem especificar páginas de memória maiores que o padrão de 4 kibibyte (KiB). O ambiente de execução de VM no GDC oferece suporte a páginas de 2 mebibyte (MiB) e 1 gibibyte (GiB). É possível definir páginas grandes para um nó no momento da execução ou para quando a máquina do nó for inicializada. Recomendamos que você configure grandes páginas em cada nó em que quiser executar VMs compatíveis com NUMA.

  1. Para configurar o número de páginas grandes de um tamanho específico no nó NUMA no ambiente de execução, use o seguinte comando:

    echo HUGEPAGE_QTY > \
        /sys/devices/system/node/NUMA_NODE/hugepages/hugepages-HUGEPAGE_SIZEkB/nr_hugepages
    

    Substitua:

    • HUGEPAGE_QTY: o número de páginas a serem alocadas para o tamanho especificado.

    • NUMA_NODE: o nó NUMA, como node0, ao qual você está alocando páginas grandes.

    • HUGEPAGE_SIZE: o tamanho das páginas grandes em kibibytes, 2048 (2 MiB) ou 1048576 (1 GiB).

Configurar uma VM para usar o nó NUMA

Depois que os nós do cluster forem ajustados para NUMA, será possível criar VMs com reconhecimento de NUMA. As VMs com reconhecimento de NUMA são programadas em nós NUMA.

Para criar uma VM compatível com NUMA:

  1. Siga as instruções para criar uma VM usando um manifesto.

    Use as seguintes configurações de compute para configurar a VM compatível com NUMA:

    • spec.compute.guaranteed: defina guaranteed como true. Com essa configuração, o virt-launcher pod está configurado para ser colocado na classe de qualidade de serviço (QoS) do Kubernetes.

    • spec.compute.advancedCompute:

      • dedicatedCPUPlacement: defina dedicatedCPUPlacement como true. Essa configuração fixa as CPUs virtuais nas CPUs físicas do nó.
      • hugePageSize: defina hugePageSize como 2Mi ou 1Gi para especificar o tamanho das páginas grandes para a VM usar, 2 mebibytes ou 1 gibibyte.
      • numaGuestMappingPassthrough: inclua uma estrutura vazia ({}) para essa configuração. Essa configuração estabelece a afinidade de NUMA para que a VM seja programada apenas em nós NUMA.

    O exemplo de manifesto VirtualMachine a seguir mostra como pode ser uma configuração de VM compatível com NUMA:

    apiVersion: vm.cluster.gke.io/v1
    kind: VirtualMachine
    metadata:
      name: vm1
    spec:
      compute:
        cpu:
          vcpus: 2
        guaranteed: true
        advancedCompute:
          dedicatedCPUPlacement: true
          hugePageSize: 2Mi
          numaGuestMappingPassthrough: {}
        memory:
          capacity: 256Mi
      interfaces:
      - name: eth0
        networkName: pod-network
        default: true
      disks:
      - virtualMachineDiskName: disk-from-gcs
        boot: true
        readOnly: true