用 Volcano 填补私有集群的空闲时间
引子
在私有 Kubernetes 场景下,因为硬件规模是一定的,不太会随着业务高峰低谷进行裁撤,因此缩减下来的服务资源并不能带来成本上的优势,如果在闲时~挖挖矿~跑跑 AI 大数据什么的是不是可以贴补一下家用呢?Volcano 值得一试。
Volcano(https://volcano.sh/zh/) 是“一个用于高性能工作负载场景下基于Kubernetes 的容器批量调度引擎”,项目主页上罗列了为数众多的应用案例和适配的 AI、大数据平台。
它提供了Kubernetes目前缺少的一套机制,这些机制通常是许多高性能 工作负载所必需的,包括:
机器学习/深度学习
生物学计算/基因计算
大数据应用
这些类型的应用程序通常运行在像 Tensorflow、Spark、PyTorch、 MPI 等通用领域框架上,Volcano 无缝对接这些框架。
场景
假设这样一种场景,忙时会占用集群 60% 的 CPU 资源,而闲时则只需要一半,我们需要这样一个能力:
闲时自动启动任务
多个任务排队完成
如果主业务启动,则自行停止队列任务
使用 Volcano,简单的几个 YAML 就能完成任务。
部署
可以用 YAML 直接部署 Volcano,K8s 版本要求在 1.13-1.21 之间(1.22 因为 CRD 资源组升级为 v1,需要进行一些修改才能部署),部署文件如下:
x86_64:
https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yamlarm64:
https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development-arm64.yaml
部署之后,会生成若干 CRD,以及一个 volcano-system 命名空间,其中包含 Volcano 的工作负载。
启动工作负载
我用了一个单节点 Kubernetes 集群,剩余可用资源刚好 1 CPU:
$ kubectl describe node single | grep -E "^\s+cpu\s+"cpu 1 (50%) 0 (0%) 创建一个 Deployment,为方便控制,我们使用两个占用 300m CPU 的实例(源码见附录 workload.yaml):
$ kubectl apply -f workload.yaml
deployment.apps/sleep created
$ kubectl describe node single | grep -E "^\s+cpu\s+"cpu 1600m (80%) 600m (30%) 可以看到,CPU Request 已经上升至 80%。
创建 Volcano 队列
源码见附录 queue.yaml,创建之后查看其状态:
$ kubectl apply -f queue.yaml
queue.scheduling.volcano.sh/q800 created
$ kubectl describe queue q800
...
Spec:Capability:Cpu: 800mReclaimable: falseWeight: 1
Status:State: Open 上面结果表明,创建了一个 CPU 容量为 800m 且状态开放的队列。
创建 Valcano 任务
在创建任务之前,我们首先要给 Volcano 和工作负载分别创建一个 PriorityClass:
apiVersion: scheduling.k8s.io/v1
description: Used for volcano jobs
kind: PriorityClass
metadata:name: volcano-task
preemptionPolicy: PreemptLowerPriority
value: -1
---
apiVersion: scheduling.k8s.io/v1
description: Used for workloads
kind: PriorityClass
metadata:name: workload-task
preemptionPolicy: PreemptLowerPriority
value: 1 没有标明 PriorityClass 的 Pod ,其缺省优先级为 0,所以使用 -1 优先级的 Pod 就属于人见人踩的小角色了。而 workload-task 声明的 PreemptLowerPriority 策略,会在调度过程中抢占低优先级任务的资源。
接下来定义一个 Volcano 任务,源码见 job1.yaml,定义其优先级为刚刚创建的 volcano-task。这个 Job 配置最小可用副本为 2,和 Deployment 的定义类似,必须有两个 Pod 全部启动。
$ kubectl apply -f job.yaml
job.batch.volcano.sh/jobb created 查看各种对象:
$ vcctl job list
Name Creation Phase JobType Replicas Min Pending Running Succeeded Failed Unknown RetryCount
jobb 2021-09-09 Pending Batch 2 2 2 0 0 0 0 0
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
jobb-sleep-0 0/1 Pending 0 7s
jobb-sleep-1 0/1 Pending 0 7s
sleep-6458fc8f96-qr6s6 1/1 Running 0 14m
sleep-6458fc8f96-tmf9k 1/1 Running 0 14m 看到任务和 Pod 都处于 Pending 状态,查看 Pod 的状态,会发现 Pending 原因是:
$ kubectl describe po jobb-sleep-0
...
Warning FailedScheduling 8m22s volcano all nodes are unavailable: 1 node(s) resource fit failed. 因为资源不足,导致任务被挂起,这是我们期待的效果。
工作负载扩缩容
假设闲时工作负载资源需求降低 50%,看看会发生什么:
$ kubectl scale deployment sleep --replicas=1
deployment.apps/sleep scaled
$ vcctl job list
Name Creation Phase JobType Replicas Min Pending Running Succeeded Failed Unknown RetryCount
jobb 2021-09-09 Running Batch 2 2 0 2 0 0 0 0 此时看到队列中的 Job 已经启动运行。
如果工作负载开始增加,优先级就会发生作用了:
dustise:mine/ $ kubectl scale deployment sleep --replicas=2 [15:15:25]
deployment.apps/sleep scaled
dustise:mine/ $ kubectl get pods [15:15:29]
NAME READY STATUS RESTARTS AGE
jobb-sleep-0 0/1 Pending 0 4m17s
jobb-sleep-1 0/1 Pending 0 4m17s
sleep-7f67d6c47c-5cp7s 1/1 Running 0 5m12s
sleep-7f67d6c47c-jrsqh 1/1 Running 0 4m29s 可以看到 jobb 已经退回 Pending 状态,任务回到排队状态。
$ vcctl queue list
Name Weight State Inqueue Pending Running
...
q800 1 Open 1 0 0 0 后记
也不知道 Volcano 啥时候弄个挖矿调度器。。
源码
workload.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: sleepname: sleep
spec:replicas: 2selector:matchLabels:app: sleeptemplate:metadata:labels:app: sleepspec:containers:- image: dustise/sleep:v0.9.8name: sleepresources:requests:cpu: 300mlimits:cpu: 300m job1.yaml
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:name: jobb
spec:minAvailable: 2schedulerName: volcanoqueue: q800priorityClassName: volcano-taskpolicies:- event: PodEvictedaction: RestartJobtasks:- replicas: 2name: sleeppolicies:- event: TaskCompletedaction: CompleteJobtemplate:spec:containers:- image: dustise/sleep:v0.9.8name: sleepresources:requests:cpu: 300mlimits:cpu: 300mrestartPolicy: Never queue.yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:name: q800
spec:weight: 1reclaimable: falsecapability:cpu: 800m
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
