简介
默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。
在实际使用中,一些情况下我们想控制某些Pod到达某些节点。
kubernetes提供了四类调度方式:
- 自动调度:运行在哪个Node节点上完全由Scheduler经过一系列的算法计算得出
- 定向调度:NodeName、NodeSelector
- 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
- 污点/容忍调度:Taints、Toleration
自动调度
运行容器选择Node节点完全由Scheduler经过一系列的算法计算得出选定
定向调度
利用在Pod上声明的nodeName或nodeSelector,以此将Pod调度到期望的Node节点上。
注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,Pod会运行失败
NodeName
强制约束,直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点
创建pod-nodename.yaml
启动
查看(强行调度到不存在的node3,status为Pending状态)
删除
nodeSelector
将Pod调度到添加了指定标签的Node节点,通过kubernetes的label-selector机制实现
Pod在创建之前由Scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将Pod调度到目标节点
该匹配规则是强制约束
给node节点添加标签
查看node标签
创建pod-nodename.yaml
启动
查看(node1标签是pro所以pod会调度到node1)
删除
删除标签
亲和性调度
定向调度如果没有满足条件的Node那么Pod将不会被运行,即使在集群中还有可用的Node列表也不行,这就限制了它的使用场景。
为了解决上述问题引入了亲和性调度(Affinity)。它在nodeSelector的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使得调度更加灵活。
Affinity主要分为三类:
- nodeAffinity(node亲和性):以Node为目标,解决Pod可以调度到那些Node的问题
- podAffinity(pod亲和性):以Pod为目标,解决Pod可以和那些已存在的Pod部署在同一个拓扑域中的问题
- podAntiAffinity(pod反亲和性):以Pod为目标,解决Pod不能和那些已经存在的Pod部署在同一拓扑域中的问题
关于亲和性和反亲和性的使用场景的说明:
亲和性:如果两个应用频繁交互,那么就有必要利用亲和性让两个应用尽可能的靠近,这样可以较少因网络通信而带来的性能损耗。
反亲和性:当应用采用多副本部署的时候,那么就有必要利用反亲和性让各个应用实例打散分布在各个Node上,这样可以提高服务的高可用性。
nodeAffinity
以Node为目标,解决Pod可以调度到那些Node的问题
如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都满足,Pod才能运行在指定的Node上。
如果nodeAffinity指定了多个nodeSelectorTerms,那么只需要其中一个能够匹配成功即可。
如果一个nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有的才能匹配成功。
如果一个Pod所在的Node在Pod运行期间其标签发生了改变,不再符合该Pod的nodeAffinity的要求,则系统将忽略此变化。
使用说明
关系符的使用说明
硬限制
Node节点必须满足指定的所有规则才可以,不满足运行失败
创建node标签
创建pod-nodeaffinity-required.yaml
启动
查看(没有node拥有xxx或yyy的标签,不满足调度条件,硬限制的status状态为Pending)
查看日志
删除
删除node标签
软限制
优先调度到满足指定的规则的Node,不满足随机指定node运行
创建pod-nodeaffinity-preferred.yaml
启动
查看(node节点没有xxx或yyy标签,不满足调度条件,但软限制会自动分配到其他node)
查看日志
删除
podAffinity
以运行的Pod为目标,实现让新创建的Pod和参照的Pod在一个区域的功能。
使用说明
topologyKey用于指定调度的作用域,例如:
如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围。
如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分。
硬限制
匹配调试满足运行,不满足运行失败
创建参照pod(一个具有pro标签的pod)
启动
查看(具有pro标签的参照pod运行在node1)
创建pod-podaffinity-requred.yaml
启动
查看(没有找到符合条件的pod所以status状态为Pending)
查看日志
删除
删除参照pod
podAntiAffinity
"反亲和性"让新Pod和参照Pod不在一个区域
创建参照pod(一个具test标签的pod)
启动
查看(具有test标签的参照pod运行在node2)
创建pod-podantiaffinity-requred.yaml
启动
查看(具有test标签的参照pod运行在node2,反亲和性规则生效新pod运行在node1)
查看日志
删除
删除参照pod
污点/容忍调度
污点(Taints)
亲和性和反亲和性调度都是站在Pod的角度上,污点可以站在Node的角度上,通过在Node上添加污点属性,来决定Pod调度。
Node被设置了污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。
污点的格式:key=value:effect,key和value是污点的标签,effect描述污点的作用,支持如下三个选项:
- PreferNoSchedule:尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可以调度。
- NoSchedule:不会把Pod调度到具有该污点的Node上,但是不会影响当前Node上已经存在的Pod。
- NoExecute:不会把Pod调度到具有该污点的Node上,同时也会将Node上已经存在的Pod驱逐。
因为master节点设置了默认污点(NoSchedule),所以pod不会调度到master上来,查看masrer的污点信息
PreferNoSchedule
规避将Pod调度到具有该污点的Node,除非没有其他节点可以调度。
设置污点至node1
查看污点
创建pod
查看pod(当前只有一个node1节点,没有其他节点可以调度,PreferNoSchedule最终允许调度到node1)
取消污点
NoSchedule
Pod不会调度到具有该污点的Node上,并且不会影响当前Node上已经存在的Pod
设置污点
查看污点
查看刚才创建的pod(nginx的pod依然在运行,NoSchedule不会驱离之前的pod)
再次创建一个pod
查看((nginx-1的pod处于Pending状态,NoSchedule不允许调度到node1)
删除污点
NoExecute
Pod不会调度到具有该污点的Node上,并且当前区域不满足条件的pod将会被驱离
设置污点
查看污点
查看刚才创建的2个pod(NoExecute驱离了所有pod)
再次创建一个pod
查看(NoExecute不允许调度任何pod)
删除污点
查看(删除node1的污点后所有pod都会自动调度到node1运行)
删除pod
容忍(Toleration)
污点就是拒绝,容忍就是忽略,Node通过污点拒绝Pod调度上去,Pod通过容忍忽略拒绝。
容忍的详细配置
kubectl explain pod.spec.tolerations
......
FIELDS:
key # 对应着要容忍的污点的键,空意味着匹配所有的键
value # 对应着要容忍的污点的值
operator # key-value的运算符,支持Equal和Exists(默认)
effect # 对应污点的effect,空意味着匹配所有影响
tolerationSeconds # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间
给node1设置NoExecute污点拒绝所有pod调度
查看污点
创建pod
查看pod(当前只有一个node1节点,没有其他节点可以调度,PreferNoSchedule最终允许调度到node1)
设置容忍 pod-toleration.yaml
启动
查看(新创建的nginx-toleration设置了针对NoExecute的容忍所以成功运行到node1)
删除污点
删除pod