slurm on k8s IB网络调度优化

调度需求

k8s的默认调度器在调度pod时,分两个阶段,第一个阶段:根据请求资源和pod、node的亲和性等配置筛选出符合要求的node列表。第二阶段:对筛选出来的node资源情况进行打分排序,最终选择打分最高的node作为pod的调度节点。在一些场景,我们想要自定义筛选节点的算法,该如何做呢?下面以slurm on k8s的需求举例,通过两种方式对k8s的调度器进行扩展

需求

  1. 部署slurm集群时需要根据物理架构选择性能最优的节点进行部署
  2. 在节点资源不足时,希望所有的pod都不要调度

物理架构

image.png

在slurm worker节点调度时,希望slurm cluster最好运行在一个leaf Pod网络内,且尽可能占用最少的leaf Pod数,对leaf Pod网络拓扑碎片化的影响最小

测试用例(如下su即是一个leaf Pod):

假设:su中空闲的服务器从大到小排序后依次是su(m) 、su(m-1)、... su(m-7),申请的计算服务器数量为n.
用例一:n > sum(su(m) + su(m-1)+ ... + su(m-7))时,调度失败
用例二:n < su(m-7)时,服务器全部从su(m-7)进行调度
用例三:n < su(m-k) & n > su(m-k+1)时,服务器全部从su(m-k)进行调度, k的范围 (0, 1, 2, 3, 4, 5, 6, 7)
用例四:n < sum(su(m) + su(m-1)+ ... + su(m-7)) & n > su(m-7)时,服务器根据su(m)、sum(m-1)... 顺序进行优先调度,直到满足数量要求

通过k8s 调度器框架进行扩展

对PreScore、Score扩展点进行扩展, 不支持pod group调度。同一个集群的部分pod调度完成后实际的leafpod拓扑结构已经发生变化

func (n *leafPodPlugin) PreScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
    // 1. 获取pod group的实例个数
    podAnnotations := pod.GetAnnotations()
    podGroupReplicas, _ := strconv.Atoi(podAnnotations["replicas"])
    // 2. 遍历nodes, 计算node所属leafpod node的个数
    nodeLeafPodCount := make(map[string]int)
    for _, node := range nodes {
        nodeAnnotations := node.GetAnnotations()
        if v, ok := nodeAnnotations["leafpod"]; ok {
            nodeLeafPodCount[v]++
        }
    }
    klog.Infof("nodeLeafPodCount: %v", nodeLeafPodCount)
    // 3. 遍历node, 计算k值
    for _, node := range nodes {
        nodeAnnotations := node.GetAnnotations()
        if v, ok := nodeAnnotations["leafpod"]; ok {
            klog.Infof("node %s leafpod count: %d, k: %d", node.GetName(), nodeLeafPodCount[v], podGroupReplicas-nodeLeafPodCount[v])
            podAnnotations[node.GetName()] = fmt.Sprintf("%d", nodeLeafPodCount[v]-podGroupReplicas)
        }
    }
    // PreScore的时候,判断pod group实例的个数m,nodeInfo所属POD组的node的个数n,k = n -m, k越小则约倾向于调度到该node,k < 0, 则万不得已不要调度到该节点
    // 将node对应k值记录到pod的annotation中
    pod.SetAnnotations(podAnnotations)
    return nil
}

func (n *NetworkSpeedPlugin) Score(ctx context.Context, state *framework.CycleState, p *v1.Pod, nodeName string) (int64, *framework.Status) {
      // 当k < 0时,即该node所属的leafpod不满足足够pod实例数的调度。当k > 0时,k值越小,调度到该node对整个集群的碎片化影响最小,优先调度
      podAnnotations := pod.GetAnnotations()
      k := podAnnotations[nodeName]
      if k > 0 {
         return 100 -k
      }
      return 0
}

引入volvano对调度器进行扩展

  1. 配置了volcano podgroup后可以支持按组调度。对于资源的利用率更高效。


    image.png
  2. 通过extendor 对volcano prioritize扩展点进行扩展从而实现同一leaf POD优先调度


    image.png

参考:
1. https://blog.csdn.net/lin2ur/article/details/136400365
2. https://blog.csdn.net/Forever_wj/article/details/124849567
3. volcano/pkg/scheduler/plugins/extender/extender.go at master · volcano-sh/volcano (github.com)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容