Volcano的NUMA感知调度实现

2021-12-19
5 min read

接上篇文章,调研Volcano的NUMA感知调度实现。

因为kubelet没有将cpu/等资源的拓扑信息暴露,所以volcano的方式是通过CRD Numatopology来获取节点的NUMA信息。Numatopology的spec包含:

  • policies:包含cpuManager、topologyManager的策略配置。详细内容可见上篇文章。
  • resReserved:预留资源,上报kubelet预留的系统资源
  • numares:资源的NUMA感知信息,包含可分配量和资源总量
  • cpuDetail:cpu的NUMANodeID、SocketID、CoreID的信息,这部分内容也在上篇介绍过了。可以理解为把cpuManager的内部数据结构暴露出来。

如何上报资源

volcano通过workernode上的resourceExporter组件。resourceExporter以Daemonset的形式部署到每台worker node

上,收集并上报到CRD上。resourceExporter的主程周期性地 1) 检查节点上的kubelet配置,确认预留资源量、cpuManager、topologyManager的策略配置是否有更新;2) 检查/sys/devices/system下cpu设备的NUMA信息,并更新至CPUNumaInfo

  • NUMA2CpuCap:NUMA node id 与CPU数量的映射关系
  • cpu2NUMA:CPU id与NUMA node id映射关系
  • cpuDetail:单个cpu的NUMANodeID、SocketID、CoreID的恶信息
  • NUMA2FreeCpus:统计以NUMA node分组下空闲的CPU ids

当exporter发现更新后会将从 1)获取的配置信息被填充到spec的policiesresReserved,将 2)中的NUMA2FreeCpusNUMA2CpuCap:NUMA填充到spec的numarescpuDetail填充到同名spec.cpuDetail里。

源码在此:https://github.com/volcano-sh/resource-exporter/blob/a5b966f736c645bab7557fb0d6a60e9bf20ac4e1/pkg/numatopo/update.go#L63

调度算法

scheduling-process

volcano实现了自己的调度器,调度流程和默认调度器类似,不过增加了podGroup、queue之类的批量计算的概念。在volcanoJob CRD里可以给每个task设置了任务执行的拓扑策略topologyPolicy,和topologyManager的4种策略对齐:nonebest-effortrestrictedsingle-numa-node。volcano为了确保和kubelet的判断一致,通过admission webhook设置了非none的task的资源申请是Guaranteed的。

volcano controller会将拓扑策略信息填充到pod的annotation上:volcano.sh/numa-topology-policy。确保每个pod拥有拓扑信息。从这里可以看出,volcano不支持跨task(pod)、task(pod)间的拓扑亲和性。

volcano scheduler监听Numatopology,并更新schedulerCache.nodeInfo中的NumaInfo。之后在调度pod时将上述信息作为输入,执行预选和优选。预选和优选的逻辑和默认调度器类似。相关内容在我之前写的负载调度文章有过介绍。

预选算法

volcano scheduler基本上没有复用kubelet的代码,之后将bitmask、cpuset结构依据信息重新执行一部分manager的分配逻辑。依据pod的拓扑策略,调度器过滤候选节点:

策略预选行为
none无拓扑过滤
best-effort允许pod调度到任意节点,并依据bestHint分配node上的cpuset
restricted依据NUMA node信息判断bestHiint是否是首选的分配结果,只要满足条件才能成为候选节点
single-numa-node依据NUMA node信息判断bestHiint是否能分配到单个NUME node上,只要满足条件才能成为候选节点

优选算法

依据pod的拓扑策略,调度器实现BatchNodeOrder方法为候选节点打分,找到最适合当前作业执行的节点。数据源是预选阶段生产的node的资源分配结果。对于NUMA node资源,资源分配跨NUMA node越少的机器,优选分越高。计算公式如下:

score = weight * (100 - 100 * numaNodeNum / maxNumaNodeNum)

总结

可以看到volcano并不支持最新的memoryManager,虽然保留了硬件资源NUMA信息的扩展性,但是和upstream的同步还是有一定的开发成本。并且volcano极力保持和kubelet的分配算法逻辑一致,但是两者处理资源分配的时间点并不一致。在高并发的场景下,因为没有资源预留,两者的分配结果会出现不一致的情况。

参考:

https://github.com/volcano-sh/volcano/blob/master/docs/design/numa-aware.md

comments powered by Disqus