一、简介
Scheduler 是 Kubernetes 的调度器,属于核心组件,主要的任务是把定义的 Pod 分配到集群的节点上,听起来非常简单,但是有很多要考虑的问题:
-
公平:如果保证每个节点都能被分配资源
-
资源高效利用: 集群所有资源最大化被使用
-
效率:调度的性能更好,能够尽快地对大批量的 Pod 完成调度工作
-
灵活:允许用户根据自己的需求控制调度的逻辑
Scheduler 是作为单独的程序运行的,启动之后回一直监听 API Server,获取 PodSpec,NodeName 为空的 Pod 都会创建一个 binding,表明该 Pod 应该放在哪个节点上。
二、调度过程
Kubernetes Scheduler 的作用是将待调度的 Pod 按照一定的调度算法和策略绑定到集群中一个合适的 Node 上,并将绑定信息写入到 etcd 中,之后目标 Node 中 kubelet 服务通过 API Server 监听到 Scheduler 产生的 Pod 绑定事件获取 Pod 信息,然后下载镜像启动容器,调度流程如图所示:
Scheduler 提供的调度流程分为预选 (Predicates) 和优选 (Priorities) 两个步骤:
-
预选,K8S会遍历当前集群中的所有 Node,筛选出其中符合要求的 Node 作为候选
-
优选,K8S将对候选的 Node 进行打分
经过预选筛选和优选打分之后,最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。 如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。
1、预选规则
预选是从所有的节点当中,去排除那些完全不能符合对应pod的基本运行要求的节点。
如果预选阶段没有合适的节点,Pod 会一直处于 Pending 状态,不断重试调度,直到有节点满足条件。
名称 | 描述 |
CheckNodeCondition | 检查节点是 Ready |
GeneralPredicates | 检查 Pod 数量上限、CPU、内存、GPU 等资源是否符合要求 |
HostName | 检查Pod对象是否定义了pod.spec.hostname |
PodFitsHostPorts | 检查绑定在节点的x个端口上,如果节点端口被占用,那么就不满足 |
MatchNodeSelector | 检查 Node 是否包含 Pod 标签选择器指定的标签 |
PodFitsResources | 检查Pod的资源需求是否能被节点所满足 |
NoDiskConflict | 检查Pod依赖的存储卷是否能满足需求 |
PodToleratesNodeTaints | 检查Pod上的spec.tolerations可容忍的污点是否完全包含节点上的污点 |
PodToleratesNodeNoExecuteTaints | 是检查pod的容忍污点是否能接纳NoExecute的污点 |
CheckNodeLabelPresence | 根据标签是否存在是否接受调度此节点(默认关闭) |
CheckServiceAffinity | 将相同service的pod尽可能地放在一起(默认关闭) |
MaxEBSVolumeCount | 检查节点是否满足 AWS EBS 卷限制 |
MaxGCEPDVolumeCount | 检查该节点是否满足 GCP-PD 卷限制 |
MaxAzureDiskVolumeCount | 检查该节点是否满足 Azure 卷限制 |
CheckVolumeBinding | 检查PVC和PV是否符合要求 |
NoVolumeZoneConflict | 给定的区域限之中检查存储卷冲突 |
CheckNodeMemoryPressur | 检查节点内存是否过载(内存压力过大就不符合要求) |
CheckNodePIDPressure | 检查节点pid数量资源压力过大 |
CheckNodeDiskPressure | 检查节点磁盘IO是否过高 |
MatchInterPodAffinity | 检查节点是否满足POD是否满足亲和或者反亲和(需要自己定义) |
CheckNodeDiskPressure | 检查节点磁盘IO是否过高 |
MatchInterPodAffinity | 检查节点是否满足POD是否满足亲和或者反亲和(需要自己定义) |
2、优选规则
如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。
LeastRequested | 由节点的空闲资源与节点的总容量来比较一个比值 |
BalancedResourceAllocation | CPU和内存资源被占用率相近的胜出 |
NodePreferAvoidPods | 优先级较高,根据节点是否由注解信息来判定 |
TaintToleration | 将Pod对象的spec.tolerations列表项与节点的taints列表项进行匹配度检查,匹配条目越多,得分越低; |
SeletorSpreading | 把同一个标签选择器的pod散开至多个节点 |
InterPodAffinity | 匹配项越多得分越高 |
NodeAffinity | 节点亲和型 |
MostRequested | 跟LeastRequested相反,空闲越小的分越高,尽可能把一个节点资源用完(默认关闭) |
ImageLocality | 根据满足当前Pod对象需求的已有镜像的体积大小之和(默认关闭) |
三、自定义调度器
除了 Kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec:schedulername 参数指定调度器的名字,可以为 Pod 选择某个调度器进行调度。比如下面的 Pod 选择 my-scheduler 进行调度,而不是默认的 default-scheduler。
apiVersion: v1
kind: Pod
metadata:
name: annotatino-second-scheduler
labels:
name: multischeduler-example
spec:
schedulername: my-scheduler
containers:
- name: pod-with-second-annotation-container
image: gcr.io/google_containers/pause:2.0
Reference:
https://kubernetes.io/zh/docs/reference/scheduling/config/
https://www.kubernetes.org.cn/5627.html