资源调度:
API Server在接受客户端提交Pod对象创建请求后,然后是通过调度器(kube-schedule)从集群中选择一个可用的最佳节点来创建并运行Pod,而这一个创建Pod对象
在调度的过程当中有3个阶段:节点预选、节点优选、节点选定,从而筛选出最佳的节点
- 节点预选:基于一系列的预选规则对每个节点进行检查,将那些不符合条件的节点过滤,从而完成节点的预选
- 节点优选:对预选出的节点进行优先级排序,以便选出最合适运行Pod对象的节点
- 节点选定:从优先级排序结果中挑选出优先级最高的节点运行Pod,当这类节点多于1个时,则进行随机选择
当我们有需求要将某些Pod资源运行在特定的节点上时,我们可以通过组合节点标签,以及Pod标签或标签选择器来匹配特定的预选策略并完成调度,如MatchInterPodAfinity、MatchNodeSelector、PodToleratesNodeTaints等预选策略,这些策略常用于为用户提供自定义Pod亲和性或反亲和性、节点亲和性以及基于污点及容忍度的调度机制
常用预选策略:
预选策略实际上就是节点过滤器,例如节点标签必须能够匹配到Pod资源的标签选择器(MatchNodeSelector实现的规则),以及Pod容器的资源请求量不能大于节点上剩余的可分配资源(PodFitsResource规则)等等,执行预选操作,调度器会逐一根据规则进行筛选,如果预选没能选定一个合适的节点,此时Pod会一直处于Pending状态,直到有一个可用节点完成调度,其常用的预选策略如下:
- CheckNodeCondition:检查是否可以在节点报告磁盘,网络不可用或未准备好的情况下将Pod对象调度其上
- GeneralPredicates:
- HostName:如果Pod对象拥有spec.hostname属性,则检查节点名称字符串是否和该属性值匹配
- PodFitsHostPorts:如果Pod对象定义了ports.hostPort属性,则检查Pod指定的端口是否已经被节点上的其他容器或服务占用
- MatchNodeSelector:如果Pod对象定义了spec.nodeSelector属性,则检查节点标签是否和该属性匹配
- PodFitsResources:检查节点上的资源(CPU、内存)可用性是否满足Pod对象的运行需求
- NoDiskConflict:检查Pod对象请求的存储卷在该节点上可用
- PodToleratesNodeTaints:如果Pod对象中定义了spec.tolerations属性,则需要检查该属性值是否可以接纳节点定义的污点(taints)
PodToleratesNodeNoExecuteTaints:如果Pod对象定义了spec.tolerations属性,检查该属性是否接纳节点的NoExecute类型的污点 - CheckNodeLabelPresence:仅检查节点上指定的所有标签的存在性,要检查的标签以及其可否存在取决于用户的定义
- CheckServiceAffinity:根据当前Pod对象所属的Service已有其他Pod对象所运行的节点调度,目前是将相同的Service的Pod对象放在同一个或同一类节点上
- MaxEBSVolumeCount:检查节点上是否已挂载EBS存储卷数量是否超过了设置的最大值,默认值:39
- MaxGCEPDVolumeCount:检查节点上已挂载的GCE PD存储卷是否超过了设置的最大值,默认值:16
- MaxAzureDiskVolumeCount:检查节点上已挂载的Azure Disk存储卷数量是否超过了设置的最大值,默认值:16
- CheckVolumeBinding:检查节点上已绑定和未绑定的PVC是否满足Pod对象的存储卷需求
- NoVolumeZoneConflct:在给定了区域限制的前提下,检查在该节点上部署Pod对象是否存在存储卷冲突
- CheckNodeMemoryPressure:在给定了节点已经上报了存在内存资源压力过大的状态,则需要检查该Pod是否可以调度到该节点上
- CheckNodePIDPressure:如果给定的节点已经报告了存在PID资源压力过大的状态,则需要检查该Pod是否可以调度到该节点上
- CheckNodeDiskPressure:如果给定的节点存在磁盘资源压力过大,则检查该Pod对象是否可以调度到该节点上
- MatchInterPodAffinity:检查给定的节点能否可以满足Pod对象的亲和性和反亲和性条件,用来实现Pod亲和性调度或反亲和性调度
CheckNodeLabelPressure和CheckServiceAffinity可以在预选过程中结合用户自定义调度逻辑,这些策略叫做可配置策略,其他不接受参数进行自定义配置的称为静态策略
优选策略及其函数:
预选策略筛选出一个节点列表就会进入优选阶段,在这个过程调度器会向每个通过预选的节点传递一系列的优选函数来计算其优先级分值,优先级分值介于0-10之间,其中0表示不适用,10表示最适合托管该Pod对象
另外,调度器还支持给每个优选函数指定一个简单的值,表示权重,进行节点优先级分值计算时,它首先将每个优选函数的计算得分乘以权重,然后再将所有优选函数的得分相加,从而得出节点的最终优先级分值,权重可以让管理员定义优选函数倾向性的能力
- LeastRequested:最低要求,(CPU((capacity-sum(requested))10/capacity)+memory((capacity-sum(requested))10/capacity)) 得数越高,得分越高
- BalancedResourceAllocation:以CPU和内存资源占用比率相近的得分越高
- NodePreferAvoidPods:(优先级很高 得分位10 权重10000)根据节点注解信息annotations是否有 “scheduler.alpha.kubernetes.io/preferAvoidePods” 如果有,则不能运行
- TaintToleration:Pod对象的spec.tolerations与节点的taints的进行匹配都检查,匹配度越高,得分越低
- SelectorSpreading: 标签选择器分散度,查找与当前pod对象同属一个标签选择器运行的pod的节点越少的得分越高
- InterPodAffinity: 在节点对Pod所需的资源等进行匹配,匹配的越多得分越高
- NodeAffinity: 根据Pod中的nodeSelector对节点进行匹配都检查,匹配数量越多得分越高
MostRequested:
** (CPU((capacity-sum(requested))**_**10/capacity)+memory((capacity-sum(requested))**_**10/capacity)) **得数越少,得分越低
NodeLabel: 检查节点是否拥有特定标签,无论标签值是否有值,只要存在就得分,条数越多分数越高
- ImageLocality: 检查节点已有Pod所需镜像体积大小之和进行判断,存在的镜像体积越大,得分越高
选择: 根据以上筛选 排序 在多个分数相同的节点选择一个
节点亲和调度:
节点亲和性是用来确定Pod对象调度到哪一个节点的规则,这些规则基于节点上的自定义标签和Pod对象上指定的标签选择器进行定义
定义节点亲和性规则有2种:硬亲和性(require)和软亲和性(preferred)
- 硬亲和性(requiredDuringSchedulingIgnoredDuringExecution):实现的是强制性规则,是Pod调度时必须满足的规则,否则Pod对象的状态会一直是Pending
- 软亲和性(preferredDuringSchedulingIgnoredDuringExecution):实现的是一种柔性调度限制,在Pod调度时可以尽量满足其规则,在无法满足规则时,可以调度到一个不匹配规则的节点之上
定义节点亲和规则的两个要点:一是节点配置是否合乎需求的标签,而是Pod对象定义合理的标签选择器,这样才能够基于标签选择出期望的目标节点
需要注意的是:
preferredDuringSchedulingIgnoredDuringExecution
requiredDuringSchedulingIgnoredDuringExecution
名字中后半段字符串IgnoredDuringExecution表示的是,在Pod资源基于节点亲和性规则调度到某个节点之后,如果节点的标签发生了改变,调度器不会讲Pod对象从该节点上移除,因为该规则仅对新建的Pod对象有效
POD资源亲和调度:
在出于高效通信的需求,有时需要将一些Pod调度到相近甚至是同一区域位置(比如同一节点、机房、区域)等等,比如业务的前端Pod和后端Pod,此时这些Pod对象之间的关系可以叫做亲和性
同时出于安全性的考虑,也会把一些Pod之间进行隔离,此时这些Pod对象之间的关系叫做反亲和性(anti-affinity)
调度器把第一个Pod放到任意位置,然后和该Pod有亲和或反亲和关系的Pod根据该动态完成位置编排,这就是Pod亲和性和反亲和性调度的作用,Pod的亲和性定义也存在硬亲和性和软亲和性的区别,其约束的意义和节点亲和性类似
Pod的亲和性调度要求各相关的Pod对象运行在同一位置,而反亲和性则要求它们不能运行在同一位置,这里的位置实际上取决于节点的位置拓扑,拓扑的方式不同,Pod是否在同一位置的判定结果也会有所不同
如果基于各个节点的kubernetes.io/hostname 标签作为评判标准,那么会根据节点的hostname去判定是否在同一位置区域
污点和容忍度:
污点(taints):是定义在节点上的一组键值型属性数据,用来让节点拒绝将Pod调度到该节点上,除非该Pod对象具有容纳节点污点的容忍度
容忍度(tolerations):是定义在Pod对象上的键值型数据,用来配置让Pod对象可以容忍节点的污点
节点选择器和节点亲和性的调度方式都是通过在Pod对象上添加标签选择器来完成对特定类型节点标签的匹配,实现的是Pod选择节点的方式,而污点和容忍度则是通过对节点添加污点信息来控制Pod对象的调度结果,让节点拥有了控制哪种Pod对象可以调度到该节点上的 一种方式
Kubernetes使用PodToleratesNodeTaints预选策略和TaintTolerationPriority优选函数来完成这种调度方式
污点的定义是在节点的nodeSpec,而容忍度的定义是在Pod中的podSpec,都属于键值型数据,两种方式都支持一个effect标记,语法格式为key=value: effect,其中key和value的用户和格式和资源注解类似,而effect是用来定义对Pod对象的排斥等级,主要包含以下3种类型:
- NoSchedule:不能容忍此污点的新Pod对象不能调度到该节点上,属于强制约束,节点现存的Pod对象不受影响
- PreferNoSchedule:NoSchedule属于柔性约束,即不能容忍此污点的Pod对象尽量不要调度到该节点,不过无其他节点可以调度时也可以允许接受调度
- NoExecute:不能容忍该污点的新Pod对象不能调度该节点上,强制约束,节点现存的Pod对象因为节点污点变动或Pod容忍度的变动导致无法匹配规则,Pod对象就会被从该节点上去除
在Pod对象上定义容忍度时,其支持2中操作符:Equal 和 Exists
- Equal:等值比较,表示容忍度和污点必须在key、value、effect三者之上完全匹配
- Exists:存在性判断,表示二者的key和effect必须完全匹配,而容忍度中的value字段使用空值