在Kubernetes中,调度是指确保Pod与Node节点的匹配度,以便Kubelet可以运行它们。
在kubernetes集群的概念中,调度主要是做两件事情:
调度流程
如图所示,调度流程可分为两大块:
Filtering和Scoring
预选阶段,也称为predicate。
会按照预选过滤器,首先把不符合要求的node节点直接剔除在外。
这一阶段为可行性筛选。
通常,会有不止一个。 如果筛选列表为空,则该Pod尚无法完成调度。
如图所示,经过Filtering阶段,node01和node03已经标红并剔除在外。
常用的预选过滤器,我整理了一个表格供大家参考,所有过滤器可移步Filtering大全。
预选过滤器名 | 说明 |
---|---|
PodFitsHostPorts | 检查node节点是否有可用端口 |
PodFitsHost | 检查pod中是否通过hostname定义了node |
PodFitsResources | 检查标签选择器和node节点标签是否匹配 |
NoVolumeZoneConflict | 检查节点上Pod请求的卷是否可用 |
NoDiskConflict | 检查pod请求的volume是否已经挂载 |
MaxCSIVolumeCount | 评估应该新增多少个CSI卷,以及是否超出配置的限制 |
CheckNodeMemoryPressure | 如果节点处于内存压力,不会将pod调度至此 |
CheckNodePIDPressure | 如果节点pid稀缺,不会将pod调度至此 |
CheckNodeDiskPressure | 如果节点磁盘存在压力,不会将pod调度至此 |
CheckNodeCondition | 检查节点是否具备调度的基础条件,如文件系统是否可用,网络是否可用或者kubelet是否就绪,否则不会将pod调度至此 |
PodToleratesNodeTaints | 检查pod的容忍度是否能容忍节点的污点 |
CheckVolumeBinding | 评估Pod是否适合其所需的容量,这适用于绑定和未绑定的PVC |
2、Scoring
打分阶段,也称为priority。
通过优选函数对节点进行打分,从而决定调度策略。
这一阶段为优选阶段,筛选哪个节点更优。
如图所示,经过Scoring阶段,只剩下node04和node06了。
常用的优选过滤器,我也整理了一个表格供大家参考,所有过滤器可移步Scoring大全。
优选过滤器名 | 说明 |
---|---|
SelectorSpreadPriority | 标签优先级计算 |
InterPodAffinityPriority | pod亲和度计算 |
LeastRequestedPriority | 倾向于调度至请求较少、资源更空闲的节点上 |
MostRequestedPriority | 倾向于调度至请求较多、资源更紧凑的节点上 |
RequestedToCapacityRatioPriority | 使用默认资源打分函数进行优选计算 |
BalancedResourceAllocation | 倾向于调度至资源平衡的节点 |
NodePreferAvoidPodsPriority | 通过scheduler.alpha.kubernetes.io/preferAvoidPods注释,避免pod间调度至同一个node节点 |
NodeAffinityPriority | node亲和度计算 |
TaintTolerationPriority | 根据节点上无法忍受的污点数量,为所有节点准备优先级列表 |
ImageLocalityPriority | 倾向于本地已有pod缓存的节点 |
ServiceSpreadingPriority | 对于给定服务,此策略旨在确保该服务的Pod在不同的节点上运行 |
CalculateAntiAffinityPriorityMap | 此策略有助于实现pod的反亲和力 |
EqualPriorityMap | 所有节点给定一个相同的权重 |
在优选过滤器中,我提到过两个过滤器InterPodAffinityPriority和NodeAffinityPriority,他们是十分重要的,常常也会理解出现偏差。
1、InterPodAffinityPriority
我们称之为pod亲和度,pod对pod的亲和性,表示是否愿意与相关pod调度至一个区域(可以是node、机架、也可以是机房)
如何定义同一区域,则需要使用topologyKey(v1.16特性)进行标识,下一章节我会着重讲解的。
同理,还会有pod反亲和,这个你应该很好理解了。
除此之外,pod亲和度分为以下两种:
pod亲和度的API文档:
kubectl explain pod.spec.affinity.podAffinity
pod反亲和度的API文档:
kubectl explain pod.spec.affinity.podAntiAffinity
2、NodeAffinityPriority
我们称之为node亲和度,pod对node的亲和性,表示是否愿意调度到某个node上,其也细分为以下两种:
node亲和度的api文档:
kubectl explain pod.spec.affinity.nodeAffinity
上面,我提到过pod亲和度的定义,我们再来回顾一下:
pod亲和度,pod对pod的亲和性,表示是否愿意与相关pod调度在一个区域(可以是node、机架、也可以是机房),如何定义同一区域,则需要使用topologyKey(v1.16特性)进行标识。
我们先一起来看一下这个例子:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-with-preferred-pod-affinity
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
name: myapp
labels:
app: myapp
spec:
affinity:
podAffinity: #pod亲和性
preferredDuringSchedulingIgnoredDuringExecution: #软亲和
- weight: 80
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["db"]}
topologyKey: rack
- weight: 20
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["db"]}
topologyKey: zone
containers:
- name: myapp
image: nginx
上面这个例子表示:
1、定义了一个pod软亲和:preferredDuringSchedulingIgnoredDuringExecution
2、软亲和条件有2个,app标签中是否存在值为db的pod资源,但优先度不同;前者80,后者只有20
3、同一位置指标的定义为topologyKey,一个为rack,另一个为zone
可能你还是有点困惑,这里对于调度的情况我再来归纳一下:
这里,我们也再次回顾一下概念,增强记忆。
node亲和度,pod对node的亲和性,表示是否愿意调度到某个node上,也细分为硬亲和和软亲和。
我们现在直接来看下面这个例子,其中:
1、定义了一个软亲和:preferredDuringSchedulingIgnoredDuringExecution
2、表示最期望调度至zone=foo的节点上
3、次期望调度至存在ssd标签的节点
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy-with-node-affinity
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
name: myapp-pod
labels:
app: myapp
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #软亲和
- weight: 60
preference:
matchExpressions:
- {key: zone, operator: In, values: ["foo"]}
- weight: 30
preference:
matchExpressions:
- {key: ssd, operator: Exists, values: []}
containers:
- name: myapp
image: nginx
我们在实际使用过程中,很可能会使用多个表达式来限制调度的期望,可能是多个标签的过滤、也可能是多个表达式的拼接。
那么这些表达式的优先级是怎么样的呢,如果你没搞明白直接操作,会带来意想不到的后果的!(不建议)
我们先来看一个demo:
apiVersion: v1
kind: Pod
metadata:
name: required-nodeAffinity-pod-or
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬亲和
nodeSelectorTerms:
- matchExpressions: #matchExpressions级别是或关系(or)
- {key: zone, operator: In, values: ["foo"]} 我们是(and)与关系,需要都满足
- {key: zone, operator: In, values: ["bar"]} 我们是(and)与关系,需要都满足
- matchExpressions: #matchExpressions级别是或关系(or)
- {key: ssd, operator: Exists, values: []}
containers:
- name: myapp
image: nginx
resources:
requests:
cpu: 6
memory: 20Gi
你可以看到,这是一个多条件的硬亲和例子,对于其中的优先级是这样的:
key级别:是与关系(and)
matchExpressions级别:是或关系(or)