任务队列ack-kube-queue旨在管理Kubernetes中的AI/ML工作负载和批处理工作负载。它允许系统管理员使用自定义队列的作业队列管理,以提高队列的灵活性。结合Quota系统,ack-kube-queue自动优化了工作负载和资源配额管理,以便最大化利用集群资源。本文介绍如何安装及使用任务队列ack-kube-queue。
前提条件
已开通云原生AI套件。
使用限制
仅支持ACK Pro托管版集群,且集群版本为1.18.aliyun.1及以上。
安装ack-kube-queue
分为以下两个场景讲解如何安装ack-kube-queue。
场景一:未部署云原生AI套件
-
登录容器服务管理控制台,在左侧导航栏单击集群。
-
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > 云原生AI套件。
-
在云原生AI套件页面下方,单击一键部署。
-
在调度区域,选中Kube Queue,在交互方式区域,选中Arena,然后在页面下方单击部署云原生AI套件。
场景二:已部署云原生AI套件
-
登录容器服务管理控制台,在左侧导航栏单击集群。
-
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > 云原生AI套件。
-
安装ack-arena和ack-kube-queue。
-
在云原生AI套件页面的操作列,单击组件ack-arena对应的部署。在参数配置页面,单击确定。
-
在云原生AI套件页面的操作列,单击组件ack-kube-queue对应的部署。在弹出页面,单击确定。
ack-arena和ack-kube-queue安装完成后,组件列表区域的组件状态为已部署。
-
支持排队功能的任务类型
ack-kube-queue支持TfJob、PytorchJob、MpiJob、Argo Workflow以及原生Job的排队功能。
使用限制
-
TfJob、PytorchJob需要使用ack-arena组件中提供的Operator。
-
使用原生Job类型排队功能需要集群版本不低于1.22。
-
MpiJob当前仅支持通过Arena提交MpiJob,且MpiJob的Operator仅支持ack-arena安装的Operator。
-
Argo Workflow当前仅支持对整体进行排队,可以通过在Annotation中申明如下内容,申明Workflow需要的资源。
``` kube-queue/min-resources: | cpu: 5 memory: 5G ```
切换Quota资源类型
当集群中有多个用户时,为了保障用户有足够的资源使用,管理员会将集群的资源固定分配给不同的用户。传统的方法是通过Kubernetes原生的ResourceQuota方式进行固定资源的分配。但由于小组之间资源忙闲不一,为了提升资源整体利用率,ack-kube-queue默认使用ElasticQuota。如果您想切换Quota资源类型为Kubernetes原生的ResourceQuota,可以按照如下步骤操作。关于ElasticQuota的更多信息,请参见ElasticQuota。
-
执行如下命令,切换ElasticQuota为Kubernetes的ResourceQuota。
kubectl edit deploy kube-queue-controller -nkube-queue
-
修改环境变量
elasticquota
为resourcequota
。env: - name: QueueGroupPlugin value: resourcequota
-
切换完成后,保存文件。等待新的kube-queue-controller启动,资源分配方式即可切换为ResourceQuota模式。
开启阻塞队列
默认情况下,ack-kube-queue处理任务时采用与kube-scheduler相同的任务轮转机制,所有任务会在队列中依次请求资源,请求失败后进入Unschedulable队列进行退避,直到下次调度。当集群中存在大量资源需求量小的任务时,由于小任务会占用大量队列轮转时间,资源需求量大的任务将难以获得资源执行,存在长时间Pending的风险。为了避免大量小任务轮转导致大任务无法执行,ack-kube-queue提供阻塞队列功能,开启后队列将只调度队列最前端的任务,从而使得大任务能够有机会执行。
开启方法
-
登录容器服务管理控制台,在左侧导航栏选择集群。
-
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 无状态。
-
选择命名空间为kube-queue,在kube-queue-controller所在行,单击操作列的编辑。
-
单击环境变量后面的新增,增加如下记录。
配置项
取值
类型
自定义
变量名称
StrictPriority
变量/变量引用
true
-
单击页面右侧更新。在确认弹出框中单击确定。
开启严格优先级调度
默认情况下,请求失败的任务进入Unschedulable队列进行退避,直到下次调度。当集群资源由于任务结束空闲时,高优先级任务由于仍处于退避阶段,不会被任务队列调度,可能会导致集群资源被低优先级任务占用。为了使得高优先级任务在集群获得空闲资源时能够被优先尝试调度,ack-kube-queue提供严格优先级调度功能。开启后队列将在正在运行的任务结束后从高优先级的最早提交的任务开始尝试执行,从而使得高优先级任务能够在集群获得空闲资源时优先调度。
说明
当高优先级任务未获得充足资源时,低优先级任务仍然可以获得资源执行。
开启方法
-
登录容器服务管理控制台,在左侧导航栏选择集群。
-
在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 无状态。
-
选择命名空间为kube-queue,在kube-queue-controller所在行,单击操作列的编辑。
-
单击环境变量后面的新增,增加如下记录。
配置项
取值
类型
自定义
变量名称
StrictConsistency
变量/变量引用
true
-
单击页面右侧更新。在确认弹出框中单击确定。
Quota资源使用示例
ElasticQuota
-
使用如下YAML,创建一个ElasticQuotaTree。
展开查看YAML文件
apiVersion: v1 kind: List metadata: resourceVersion: "" selfLink: "" items: - apiVersion: scheduling.sigs.k8s.io/v1beta1 kind: ElasticQuotaTree metadata: name: elasticquotatree namespace: kube-system spec: root: # root节点为总的资源数量,max的值不能小于Children的max之和。 name: root namespaces: [] max: cpu: "4" memory: 4Gi nvidia.com/gpu: "64" aliyun.com/gpu-mem: "32" min: cpu: "0" memory: 0M nvidia.com/gpu: "0" aliyun.com/gpu-mem: "0" children: # 可以有多个Child,一般每个Child对应一个Namespace。 - name: root.defaultQuotaGroup namespaces: - default max: cpu: "4" memory: 4Gi nvidia.com/gpu: "64" aliyun.com/gpu-mem: "16" min: cpu: "0" memory: 0M nvidia.com/gpu: "0" aliyun.com/gpu-mem: "0" children: null
-
执行如下命令,查看ElasticQuotaTree是否创建成功。
kubectl get elasticquotatree -A
预期输出:
NAMESPACE NAME AGE kube-system elasticquotatree 7s
表示ElasticQuotaTree创建成功。
-
创建测试任务。
说明
-
为了测试任务队列效果,测试任务的资源配额应该小于执行所有任务需要的总资源。
-
为了方便测试,TFJob用busybox镜像替代真正的tensorflow镜像。模拟训练过程,每个容器Sleep 30秒。
-
使用如下YAML,创建两个TFJob进行测试。
展开查看YAML文件
apiVersion: "kubeflow.org/v1" kind: "TFJob" metadata: name: "job1" annotations: scheduling.x-k8s.io/suspend: "true" spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi Worker: replicas: 2 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi -- apiVersion: "kubeflow.org/v1" kind: "TFJob" metadata: name: "job2" annotations: scheduling.x-k8s.io/suspend: "true" spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi Worker: replicas: 2 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi
-
待任务提交后,查看任务状态。
-
执行如下命令,查看任务状态。
kubectl get tfjob
预期输出:
NAME STATE AGE job1 Running 3s job2 Queuing 2s
预期输出显示
job1
处于Running状态,job2
处于Queuing状态,符合预期。因为每个TFJob训练任务需要的CPU资源为2 core,ElasticQuotaTree给Default Namespace分配的最大CPU核数为2 core,所以同一时间段内只能运行一个TFJob。 -
稍等片刻后,再次执行如下命令。
kubectl get tfjob
预期输出:
NAME STATE AGE job1 Succeeded 77s job2 Running 77s
预期输出显示
job1
执行成功。job1
执行完成后,job2
开始执行。表明ack-kube-queue可以正常工作。
-
-
ResourceQuota
-
使用如下YAML,创建一个ResourceQuota。
apiVersion: v1 kind: ResourceQuota metadata: name: default spec: hard: cpu: "4" memory: 4Gi
-
执行如下命令,查看ResourceQuota是否创建成功。
kubectl get resourcequota default -o wide
预期输出:
NAME AGE REQUEST LIMIT default 76s cpu: 0/4, memory: 0/4Gi
表示ResourceQuota创建成功。
-
使用如下YAML,创建两个TFJob进行测试。
展开查看YAML文件
apiVersion: "kubeflow.org/v1" kind: "TFJob" metadata: name: "job1" annotations: scheduling.x-k8s.io/suspend: "true" spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox:stable command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi Worker: replicas: 2 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox:stable command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi -- apiVersion: "kubeflow.org/v1" kind: "TFJob" metadata: name: "job2" annotations: scheduling.x-k8s.io/suspend: "true" spec: tfReplicaSpecs: PS: replicas: 1 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox:stable command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi Worker: replicas: 2 restartPolicy: Never template: spec: containers: - name: tensorflow image: busybox:stable command: - /bin/sh - -c - -- args: - "sleep 30s" resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi
-
待任务提交后,执行如下命令,查看任务状态。
kubectl get tfjob NAME STATE AGE job1 Running 5s job2 Queuing 5s kubectl get pods NAME READY STATUS RESTARTS AGE job1-ps-0 1/1 Running 0 8s job1-worker-0 1/1 Running 0 8s job1-worker-1 1/1 Running 0 8s
可以看到job1处于Running状态,job2处于Queuing状态,这是符合预期的。因为每个TFJob训练任务需要的CPU资源为2 core,ResourceQuota给Default Namespace分配的最大CPU核数为2 core,所以同一时间段内只能运行一个TFJob。
-
稍等片刻后,再次执行如下命令。
kubectl get tfjob NAME STATE AGE job1 Succeeded 77s job2 Running 77s kubectl get pods NAME READY STATUS RESTARTS AGE job1-worker-0 0/1 Completed 0 54s job1-worker-1 0/1 Completed 0 54s job2-ps-0 1/1 Running 0 22s job2-worker-0 1/1 Running 0 22s job2-worker-1 1/1 Running 0 21s
可以看到job1执行成功。job1执行完成后,job2开始执行。说明ack-kube-queue可以正常工作。
内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家
阿里云企业补贴进行中: 马上申请
腾讯云限时活动1折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利:同意关联,立享优惠
转转请注明出处:https://www.yunxiaoer.com/169835.html