找回密码
 立即注册
首页 业界区 业界 刚入职的AIops菜鸡,应该知道gang-scheduling和binpack ...

刚入职的AIops菜鸡,应该知道gang-scheduling和binpack调度吗?

啖曼烟 昨天 12:35
如题,刚入职的AIOps菜鸡, 基于kubeflow做AI大模型训练和推理,本文记录了企业项目:[云原生AI算力平台] 在云原生的背景下,遇到了一些现实挑战和应对方式。
1. 可插拔的调度框架

k8s以可插拔的插件方式实现了调度能力,插件可以实现多个扩展点接口来执行更复杂或有状态的任务。
1.png

默认的调度插件 给出了他们实现的扩展点、默认的打分策略。
在AI工程中要重点关注默认调度器带来的副作用:
① 默认的调度器是以Pod为调度单元进行依次调度,不会考虑Pod之间的相互关系
② NodeResourcesFit插件默认启用的最少资源分配策略: 为避免单点故障,调度时打散了Pod。
2. AIops

在AI工程化中,我们要面对2个现实:
① 很多数据计算类的离线作业(包括ML训练)具有组合调度的特点,即要求所有的子任务都能够成功创建后,整个作业才能正常运行。如果只有部分子任务启动的话,启动的子任务将持续等待剩余的子任务被调度(甚至死锁), 这浪费了节点资源,这正是Gang Scheduling的场景。
② 在ML训练和推理时,节点上的GPU是最昂贵的算力资源,默认的LeastAllocated调度策略打散了Pod,很容易在节点上产生GPU碎片, 影响了资源的利用率,这时就要求binpack调度。
2.png

gang-scheduling 调度

gang-scheduling 是coschedule协同调度中的严格协同调度,(批处理作业完全不允许有“作业碎片”存在), 也就是“All or Nothing”。
binpack调度

顾名思义就是:装箱,在k8s调度中意味:避免资源碎片化,尽可能把节点空余出来, 最终最大化的利用节点资源。
原生NodeResourcesFit调度插件

官网所述,默认调度器的NodeResourcesFit有三个打分策略

  • LeastAllocated(默认),这种策略的目的是将工作量平均分配到各个节点,防止任何一个节点超负荷工作
  • MostAllocated
  • RequestedToCapacityRatio:根据节点资源与 pod 需求的匹配程度来决定哪个节点
3.png

同一个k8s集群,为了让在线任务和离线任务的不同调度需求能优雅落地,项目引入了koordinator 调度器。
Koordinator 是一个基于 QoS 的 Kubernetes 混合工作负载调度系统。它旨在提高对延迟敏感的工作负载和批处理作业的运行时效率和可靠性,简化与资源相关的配置调整的复杂性,并增加 Pod 部署密度以提高资源利用率。
3.koordinator一把梭

3.1 准备环境/背景

① 本次使用minikube:minikube start --cni=auto --nodes=3 --addons=metrics-server
binpack依赖metrics-server插件判断节点资源利用情况,每个节点默认2核心cpu/2200MB内存。
对control-plane添加污点kubectl taint nodes minikube node-role.kubernetes.io/control-plane=true:NoSchedule, 只关注两个worker节点的调度。
② 本次环境无gpu硬件, 本次在k8s上安装虚拟资源:example.com/dongle
下面对2台worker分别构造了8卡虚拟资源
  1. kubectl proxy
  2. # 每个节点申请过8卡机器
  3. curl --header "Content-Type: application/json-patch+json" \
  4.   --request PATCH \
  5.   --data '[{"op": "add", "path": "/status/capacity/example.com~1dongle", "value": "8"}]' \
  6.   http://127.00.1:8001/api/v1/nodes/minikube-m02/status
  7.   curl --header "Content-Type: application/json-patch+json" \
  8.   --request PATCH \
  9.   --data '[{"op": "add", "path": "/status/capacity/example.com~1dongle", "value": "8"}]' \
  10.   http://127.0.0.1:8001/api/v1/nodes/minikube-m03/status
复制代码
③ 启动2副本pod,查看默认调度结果
  1. # deploy.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5.   name: vgpu-job # 本次deploy的资源名称
  6. spec:
  7.   replicas: 2 # 启动3副本
  8.   selector:
  9.     matchLabels:
  10.       app: vgpu-job
  11.   template:
  12.     metadata:
  13.       labels:
  14.         app: vgpu-job
  15.     spec:
  16.       containers:
  17.       - image: busybox
  18.         imagePullPolicy: IfNotPresent
  19.         name: curlimage
  20.         command:
  21.         - sleep
  22.         - 365d
  23.         resources:
  24.           limits:
  25.             cpu: 40m
  26.             memory: 40Mi
  27.             example.com/dongle: 2
  28.           requests:
  29.             cpu: 40m
  30.             memory: 40Mi
  31.             example.com/dongle: 2
复制代码
每个pod申请2卡example.com/dongle资源,默认调度器的输出:启动的2pod均匀分布到2个worker节点
4.png

按照上面的理论,再申请8卡资源会受限。
为不影响原生调度器的能力,本次将koordinator作为第二套调度器。
3.2 gang scheduling

koordinator支持gang scheduling 可使用crd或者注解的方式,这里我们使用crd:
该任务要求3pod,形成组调度:
  1. # pg.deploy.yaml
  2. apiVersion: scheduling.sigs.k8s.io/v1alpha1
  3. kind: PodGroup
  4. metadata:
  5.   name: gang-example
  6.   namespace: default
  7. spec:
  8.   scheduleTimeoutSeconds: 10
  9.   minMember: 3
复制代码
修改业务manifest文件,指定koord-scheduler调度器和gang scheduling规格对象标签。
5.png

3.3 binpack

koordinator有NodeResourcesFitPlus插件 来做binpack调度。
本例模拟节点上GPU的分配,希望将应用都binpack到一个节点上,而不是均分到多个节点,那么对于资源example.com/dongle的权重要设高。
修改koordinator的NodeResourcesFitPlus插件配置:
!!! 以helm方式安装的Koordinator的,对外没有修改插件配置的入口。
本次拉取helm chart到本地,对template/koord-scheduler-config.yaml新增了插件配置,切记不要红框内容完全替换文件,而是拿下面的配置patch到文件。
helm upgrade koordinator ./
kubectl  rollout restart deploy/koord-scheduler -n koordinator-system
6.png

插件NodeResourcesFitPlus两种策略的评分计算方法和效果如下:
7.png

最终的节点评分可以按如下方式计算:
finalScoreNode = [(weight1 * resource1) + (weight2 * resource2) + … + (weightN* resourceN)] /(weight1+weight2+ … +weightN)
那么节点的打分:
nodeScore =  (20* MostAllocatedAlg + 2* LeastAllocatedAlg + 1* LeastAllocatedAlg  )/(20+2+1),
粗略想象在第一个Pod被调度到节点A之后, 调度第二个Pod时, 节点A的MostAllocatedAlg = 2/6, 而节点B的MostAllocatedAlg = 2/8,  20的权重值在分子端占据更大因素,故第二个Pod也会更倾向于调度到节点A, 这样算法就做到了binpack。
到这里条件就都就绪了:
2台节点(均有8卡资源),每个Pod占用2卡资源,要求3 Pod形成组调度,且是binpack调度。
8.png

验证有效,目前3Pod占用了minikube-m03节点上6卡资源,继续扩容到5 Pod,理论上会有一个Pod调度到另外一个worker节点。
9.png

总结

本文回顾了在云原生背景下AIops 与原生k8s调度器的格格不入。
演示了开源的koordinator调度器是如何支持AIOps场景下的gang-scheduling 和binpack调度。
gang-scheduling 聚焦于k8s集群中上层批处理作业要求的Pod协作能力。
binpack 聚焦于k8s集群中作为基础设施节点的资源利用率,binpack避免打散,会尽量留出空闲节点。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册