配置 NUMA 感知型虚拟机调度

本文档介绍了如何配置集群和虚拟机,以支持具有非统一内存访问 (NUMA) 的计算效率的高性能和低延迟工作负载。以下是有关调整集群节点的 Kubernetes 设置的说明。本文档还介绍了如何配置具有 NUMA 亲和性的虚拟机 (VM),以使它们调度到虚拟机上并利用 NUMA 节点

使用 NUMA 感知型虚拟机时,该虚拟机中的所有通信都在 NUMA 节点的本地。NUMA 感知型虚拟机可以避免进出远程资源的数据事务,此类事务可能会降低虚拟机性能。

将节点配置为使用 NUMA

以下部分介绍了如何配置关键的 Kubernetes 组件来调整节点并确保其可以调度 NUMA 感知型容器。这些 NUMA 节点经过调整,可优化 CPU 和内存性能。请按照您要运行 NUMA 感知型虚拟机的每个节点的相关说明执行操作。

更新 kubelet 配置

作为支持 NUMA 节点亲和性的节点配置的一部分,您需要在 kubelet 配置中进行以下更改:

  • 启用使用 static 政策的 CPU 管理器
  • 启用使用 Static 政策的内存管理器
  • 启用使用 restricted 拓扑的拓扑管理器

如需在工作器节点上配置 kubelet,请执行以下操作:

  1. 在工作器节点上找到 kubelet 文件,然后将其打开以进行修改:

    edit /etc/default/kubelet
    

    如果您没有看到 kubelet 文件,请使用以下命令创建它:

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

    此命令会创建包含空的 KUBELET_EXTRA_ARGS="" 部分的 kubelet 文件。

  2. 如需启用使用 static 政策的 CPU 管理器,请将 --cpu-manager-policy=static 标志添加到文件的 KUBELET_EXTRA_ARGS="" 部分:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static"
    
  3. 如需启用使用 Static 政策的内存管理器,请将 --memory-manager-policy=Static 标志添加到文件的 KUBELET_EXTRA_ARGS="" 部分:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static"
    
  4. 如需启用使用 restricted 政策的拓扑管理器,请将 --topology-manager-policy=restricted 标志添加到文件的 KUBELET_EXTRA_ARGS="" 部分:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted"
    
  5. 检查 GKE on Bare Metal 当前预留的内存量:

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

    输出应如下所示:

    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"

    --kube-reserved=cpu=100m,memory=3470Mi 设置表示 GKE on Bare Metal 在节点上预留 3470 MiB 的内存。

  6. kubelet 文件的 KUBELET_EXTRA_ARGS 部分中的 --reserved-memory 标志设置为比当前预留的内存多 100 MiB,以考虑逐出阈值。如果没有预留的内存,则可以跳过此步骤。

    例如,通过上一步示例中 3470Mi 的预留内存,您需要在 kubelet 文件中预留 3570Mi 的内存:

    KUBELET_EXTRA_ARGS="--cpu-manager-policy=static --memory-manager-policy=Static --topology-manager-policy=restricted --reserved-memory=0:memory=3570Mi"
    
  7. /var/lib 目录中移除 CPU 和内存状态文件:

    rm /var/lib/cpu_manager_state
    rm /var/lib/memory_manager_state
    
  8. 重启 kubelet:

    systemctl start kubelet
    

如需详细了解这些政策设置,请参阅以下 Kubernetes 文档:

将节点配置为使用巨型页面

启用使用 Static 政策的内存管理器后,您可以添加巨型页面以进一步提高 NUMA 节点上的容器工作负载性能。顾名思义,巨型页面可让您指定大于标准的 4 千字节 (KiB) 的内存页面。VM Runtime on Google Distributed Cloud 支持 2 兆比字节 (MiB) 和 1 吉比字节 (GiB) 的巨型页面。您可以在运行时为节点设置巨型页面,也可以在节点机器启动时设置。我们建议您在要运行 NUMA 感知型虚拟机的每个节点上配置巨型页面。

  1. 如需在运行时在 NUMA 节点上配置特定大小的巨型页面数量,请使用以下命令:

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

    替换以下内容:

    • HUGEPAGE_QTY:要分配的指定大小的巨型页面数量。

    • NUMA_NODE:要为其分配巨型页面的 NUMA 节点(例如 node0)。

    • HUGEPAGE_SIZE:巨型页面的大小(以千字节为单位),即 2048 (2 MiB) 或 1048576 (1 GiB)。

将虚拟机配置为使用 NUMA 节点

针对 NUMA 调整集群节点后,您可以创建 NUMA 感知型虚拟机。NUMA 感知虚拟机会调度到 NUMA 节点上。

如需创建 NUMA 感知型虚拟机,请执行以下操作:

  1. 按照相关说明通过清单创建虚拟机

    使用以下 compute 设置将虚拟机配置为支持 NUMA 感知型:

    • spec.compute.guaranteed:将 guaranteed 设置为 true。使用此设置后,virt-launcher Pod 会配置为放入 Kubernetes 保证的服务质量 (QoS) 类

    • spec.compute.advancedCompute:

      • dedicatedCPUPlacement:将 dedicatedCPUPlacement 设置为 true。此设置会将虚拟 CPU 固定到节点的物理 CPU。
      • hugePageSize:将 hugePageSize 设置为 2Mi1Gi 以指定虚拟机要使用的巨型页面大小,即 2 MiB 或 1 GiB。
      • numaGuestMappingPassthrough:为此设置添加空结构 ({})。此设置会建立 NUMA 亲和性,以便虚拟机仅调度到 NUMA 节点上。

    下面的 VirtualMachine 清单示例展示了 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