1 volcano 调度架构简介
主要概念及解释:
-
volcano 调度对象是 vcjob(volcano 创建的 CRD),即上图的 JobInfo(这是 scheduler 组件内定义的类)。
-
一个 vcjob 包含一个或者多个 pod,每个 pod 声明各自的资源要求(如 cpu 多少个 core,memory 多少 GB,gpu 多少卡)
-
每个 vcjob 对应一个 PodGroup 概念, 描述整个 vcjob 的状态,最低资源要求,资源队列等信息。
当我们向 kube-apisever 创建一个 vcjob 之后,scheduler 组件会将其记录到 Cache 中。scheduler 组件每隔(默认)1 秒循环执行如下调度过程:
-
OpenSession()初始化本次调度:加载所有 plugins,并调用每个 plugin 的 OnSessionOpen()方法
-
依次调用每个 action(默认是 enqueue,allocate,backfill)
-
每个 action 会遍历所有的 JobInfo,分别对其进行处理
-
enqueu 过滤 JobInfo 是否需要进入下一轮 allocate
-
allocate 是资源调度的主要过程,主要概念与 kubernetes 原生调度器相似,首先 predicate 过滤 node 节点,然后 priority 排序 node 节点,最后(如有则)绑定 pod 到一个 node。
-
CloseSession()结束本次调度:调用每个 plugin 的 OnSessionClose()方法
2 volcano 组件及 vcjob 创建过程
前面我们看到 scheduler 内部如何对 vcjob 做资源调度,但是 pod 和 PodGroup 是如何被创建的,以及 volcano 组件在整个 vcjob 的创建过程中的作用是如何?
2.1 volcano 组件
首先,我们看下图,volcano 组件及 vcjob 创建过程
当我们部署 volcano 完成后,可以看到在 kubernetes 机器上,主要创建了以上三个 service:
-
webhook-manager 服务:通过向 kubernetes 服务注册 MutatingWebhookConfigurations 和 ValidatingWebhookConfigurations,修改及校验 vcjob。主要职责包括如下:
-
mutate:设置 schedulerName,queue,taskName 等
-
validate:检查 jobSpec 参数,tasks,plugins 等合法性检查
-
controller-manager 服务:监听 kube-apiserver 上的所有 vcjob,pod,PodGroup 等资源,主要管理整个 vcjob 的生命周期,包括其相关的 pod 和 PodGroup 的创建,修改(如状态和事件),以及销毁。
-
scheduler 服务:pod 资源调度及绑定
2.2 vcjob 创建过程:webhook-manager 校验
从零开始运行Volcano作业:
1)用户创建一个 Volcano 作业
2)Volcano Admission 拦截作业的创建请求,并进行合法性校验
3)Kubernetes 持久化存储 Volcano Job 到 ETCD
4)ControllerManager 通过 List-Watch 机制观察到Job 资源的创建,创建任务(Pod)
5)Scheduler 负责任务的调度,绑定 Node
6)Kubelet Watch 到 Pod的创建,接管 Pod 的运行
7)ControllerManager 监控所有任务的运行状态,保证所有的任务在期望的状态下运行
首先,我们看官方示例 vcjob 定义:
apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: job-1 spec: minAvailable: 1 schedulerName: volcano queue: test policies: - event: PodEvicted action: RestartJob tasks: - replicas: 1 name: nginx policies: - event: TaskCompleted action: CompleteJob template: spec: containers: - command: - sleep - 10m image: nginx:latest name: nginx resources: requests: cpu: 1 limits: cpu: 1 restartPolicy: Never
通过如下方式想 kubernetes 集群创建 vcjob
kubectl create vcjob demo.yaml
该命令在执行过程中,kube-apiserver 服务将调用 webhook-manager 服务注册的 webhook 操作,如下:
-
webhook-manager 将对 vcjob 做如下修改:
-
如果 schedulerName 未设置,则使用默认值 volcano。这是用于指定使用哪个调度器,对 pod 资源进行调度。这个很关键,vcjob 关联的 pod 将沿用该 schedulerName 值,否则该值如果为 default 或者未设置,则 kubernetes 调度服务将会处理该 pod,这将导致冲突。
-
如果 queue 未设置,则使用默认值 default,即使用默认的资源队列。注,volcano 支持多个资源队列(queue),每个 queue 可配置资源大小及优先级
-
如果 taskName 未设置,则使用 index 创建默认名称。注:vcjob 内的每个 task 定义,根据 replica 数量,对应到 kubernetes 内的多个 pod。
-
webhook-mananger 对 vcjob 信息做如下校验:
-
vcjob spec 基本信息是否合法,包括 MinAvailable,MaxRetry
-
spec.Tasks 信息:名称,Replicas, Policies
-
spec.Plugins:是否合法,是被支持的
-
spec.Queue:是否存在,且状态是 Open
如果 webhook-manager 校验通过,则 vcjob 被成功创建。可通过如下命令查看到:
kubectl get vcjob
.3 vcjob 创建过程:controller-manager 创建 pod 及 PodGroup
当 vcjob 被创建后,controller-manager 将监听到该信息,并开始管理整个 vcjob 生命周期的所有相关资源(包括 pod 及 PodGroup),主要操作如下:
-
根据 vcjob 的 spec,创建 pod:
-
设置 schedulerName(默认使用 vcjob 的 schedulerName),这样该 pod 就不会被其他 scheduler 处理了。
-
设置 annotations 信息,主要包含 GroupName 信息,即将 pod 关联到 PodGroup
-
pod 名称:使用 job 名称,task 名称及 index(task 可能包含多个 replicas)
-
设置 labels
-
创建 PodGroup:先有 pod 被创建,再有 PodGroup 被创建
-
设置 annotations 信息:从 pod 复制 annotations 信息
-
设置 OwnerReferences:关联到 pod
-
设置 queue
当 pod 和 PodGroup 被创建之后,可以通过如下命令查看到:
root@ubuntu:~# kubectl get pods -o wide --all-namespaces | grep job default test-job-default-nginx-0 1/1 Running 0 41h 10.244.29.15 bogon <none> <none> default test-job-default-nginx-1 1/1 Running 0 41h 10.244.29.16 bogon <none> <none> default test-job-default-nginx-2 1/1 Running 0 41h 10.244.29.11 bogon <none> <none> default test-job-default-nginx-3 1/1 Running 0 41h 10.244.29.14 bogon <none> <none> default test-job-default-nginx-4 1/1 Running 0 41h 10.244.29.12 bogon <none> <none> default test-job-default-nginx-5 1/1 Running 0 41h 10.244.29.13 bogon <none> <none> root@ubuntu:~# kubectl get podgroup --all-namespaces No resources found root@ubuntu:~#
2.4 vcjob 创建过程:scheduler 调度 pod
当 pod 创建完成之后,scheduler 服务将监听到该信息,并根据 pod 和 PodGroup 信息,对 pod 进行资源调度和绑定(bind),过程如第一节所述。
当绑定完成后,再通过 kubect get pod 查看时,可以看到 pod 状态已变成 ContainerCreating 或者 Running,即相应 node 节点的 kubelet 服务已监听到该 bind 信息,并为该 pod 创建相应的 Container。
3 小结
以上是从 vcjob 创建到 pod 运行的简略过程,由此我们可以了解 volcano 三个组件的主要职责,以及关键节点。这将有利于使用过程中的问题排查及效率优化。
不足之处,本文略过了很多其他细节信息,包括 volume 信息,queue,metrics 等。这些将在后续文章补充。
For x86_64: kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml For arm64: kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development-arm64.yaml
root@ubuntu:~# kubectl get pods -n volcano-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES volcano-admission-6cc49fdc5-5zgzs 1/1 Running 0 34m 10.244.29.8 bogon <none> <none> volcano-admission-init-qgh9b 0/1 Completed 0 34m 10.244.29.6 bogon <none> <none> volcano-controllers-5f5c4f4785-8dbgl 1/1 Running 0 34m 10.244.29.7 bogon <none> <none> volcano-scheduler-7f48dddb8f-8g6b5 1/1 Running 0 34m 10.244.29.5 bogon <none> <none> root@ubuntu:~# kubectl get services -n volcano-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE volcano-admission-service ClusterIP 10.103.9.198 <none> 443/TCP 35m
cat <<EOF >job.yaml apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: test-job spec: minAvailable: 3 schedulerName: volcano policies: - event: PodEvicted action: RestartJob plugins: ssh: [] env: [] svc: [] maxRetry: 5 queue: default # Comment out the following section to enable volumes for job input/output. #volumes: # - mountPath: "/myinput" # - mountPath: "/myoutput" # volumeClaimName: "testvolumeclaimname" # volumeClaim: # accessModes: [ "ReadWriteOnce" ] # storageClassName: "my-storage-class" # resources: # requests: # storage: 1Gi tasks: - replicas: 6 name: "default-nginx" template: metadata: name: web spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: "1" restartPolicy: OnFailure EOF
kubectl create -f job.yaml
root@ubuntu:~# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-job-default-nginx-0 1/1 Running 0 14s 10.244.29.15 bogon <none> <none> test-job-default-nginx-1 1/1 Running 0 14s 10.244.29.16 bogon <none> <none> test-job-default-nginx-2 1/1 Running 0 14s 10.244.29.11 bogon <none> <none> test-job-default-nginx-3 1/1 Running 0 14s 10.244.29.14 bogon <none> <none> test-job-default-nginx-4 1/1 Running 0 14s 10.244.29.12 bogon <none> <none> test-job-default-nginx-5 1/1 Running 0 14s 10.244.29.13 bogon <none> <none> root@ubuntu:~#
root@ubuntu:~# kubectl get pods -o wide --all-namespaces | grep job default test-job-default-nginx-0 1/1 Running 0 41h 10.244.29.15 bogon <none> <none> default test-job-default-nginx-1 1/1 Running 0 41h 10.244.29.16 bogon <none> <none> default test-job-default-nginx-2 1/1 Running 0 41h 10.244.29.11 bogon <none> <none> default test-job-default-nginx-3 1/1 Running 0 41h 10.244.29.14 bogon <none> <none> default test-job-default-nginx-4 1/1 Running 0 41h 10.244.29.12 bogon <none> <none> default test-job-default-nginx-5 1/1 Running 0 41h 10.244.29.13 bogon <none> <none> root@ubuntu:~#
root@ubuntu:~# kubectl get vcjob NAME AGE test-job 41h root@ubuntu:~# kubectl describe vcjob Name: test-job Namespace: default Labels: <none> Annotations: <none> API Version: batch.volcano.sh/v1alpha1 Kind: Job Metadata: Creation Timestamp: 2021-07-05T09:39:59Z Generation: 1 Managed Fields: API Version: batch.volcano.sh/v1alpha1 Fields Type: FieldsV1 fieldsV1: f:spec: .: f:maxRetry: f:minAvailable: f:plugins: .: f:env: f:ssh: f:svc: f:policies: f:queue: f:schedulerName: Manager: kubectl Operation: Update Time: 2021-07-05T09:39:59Z API Version: batch.volcano.sh/v1alpha1 Fields Type: FieldsV1 fieldsV1: f:spec: f:tasks: f:status: .: f:controlledResources: .: f:plugin-env: f:plugin-ssh: f:plugin-svc: f:minAvailable: f:running: f:state: .: f:lastTransitionTime: f:phase: Manager: vc-controller-manager Operation: Update Time: 2021-07-05T09:40:11Z Resource Version: 938444 Self Link: /apis/batch.volcano.sh/v1alpha1/namespaces/default/jobs/test-job UID: 3df22478-aac7-4185-8a8b-dfc4ce9944ec Spec: Max Retry: 5 Min Available: 3 Plugins: Env: Ssh: Svc: Policies: Action: RestartJob Event: PodEvicted Queue: default Scheduler Name: volcano Tasks: Name: default-nginx Replicas: 6 Template: Metadata: Name: web Spec: Containers: Image: nginx Image Pull Policy: IfNotPresent Name: nginx Resources: Requests: Cpu: 1 Restart Policy: OnFailure Status: Controlled Resources: Plugin - Env: env Plugin - Ssh: ssh Plugin - Svc: svc Min Available: 3 Running: 6 State: Last Transition Time: 2021-07-05T09:40:10Z Phase: Running Events: <none> root@ubuntu:~#
root@ubuntu:~# kubectl get podgroup --all-namespaces No resources found root@ubuntu:~#