
Kubernetes调度管理 (下)
作者 | 老郑
来源 |运维开发故事(ID:mygsdcsf)
转载请联系授权(微信ID:wanger5354)
podAntiAffinity
上面介绍了pod的亲和性,这里介绍的podAntiAffinity则是Pod的反亲和性,也就是说不将这类Pod调度到一起。在日常工作中,这种亲和性使用频率还比较高。微服务很少有单Pod,基本都是多个Pod,为了提高应用的高可用,不会将同应用的多个Pod调度到同一台机器上,这时候就要用到podAntiAffinity,如下:
污点调度
在Kubernetes中,有些节点自带污点 ,比如Master节点,这类节点,如果Pod没有配置容忍污点,则这些Pod不会调度到这类节点上。
在实际中,污点调度也是非常有用的,有些场景某些节点只允许某些项目组的Pod允许,比如大数据项目是一些高IO项目,不想和其他普通项目混合在一起,而其他项目如果使用标签选择器配置部署又比较麻烦,这时候就可以使用污点选择器。
我们可以通过kubectl explain node.spec.taints来查看污点相关的配置信息:
其中effect定义对Pod的排斥效果:
- NoSchdule:仅影响调度过程,对现存在的Pod不产生影响;
- NoExecute:不仅影响调度,而且还影响现存Pod,不容忍的Pod对象将被驱逐;
- PreferNoSchedule:软排斥,不是完全禁止Pod调度;
如果要给节点添加污点,则如下:
给节点 kk-node01增加一个污点,它的键名是 node-type,键值是 dev,效果是 NoSchedule。这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 kk-node01这个节点。
如果要删除污点,则使用如下命令:
如果要配置容忍污点,则如下:
operator支持Equal和Exists,默认是Equal。
如果是Equal,表示污点的键值需要一致,如果使用Exists,则表示只要存在该键的污点,比如:
该配置表示只要匹配容忍度,并且key1的健存在即可调度。
如果一个容忍度的 key 为空且 operator 为 Exists, 表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点。如果 effect 为空,则可以与所有键名 key1 的效果相匹配。
你可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点,特别是以下情况:
- 如果未被忽略的污点中存在至少一个 effect 值为 NoSchedule 的污点, 则 Kubernetes 不会将 Pod 调度到该节点。
- 如果未被忽略的污点中不存在 effect 值为 NoSchedule 的污点, 但是存在 effect 值为 PreferNoSchedule 的污点, 则 Kubernetes 会 尝试 不将 Pod 调度到该节点。
- 如果未被忽略的污点中存在至少一个 effect 值为 NoExecute 的污点, 则 Kubernetes 不会将 Pod 调度到该节点(如果 Pod 还未在节点上运行), 或者将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)。
例如,假设你给一个节点添加了如下污点
假定有一个 Pod,它有两个容忍度:
在这种情况下,上述 Pod 不会被调度到上述节点,因为其没有容忍度和第三个污点相匹配。但是如果在给节点添加上述污点之前,该 Pod 已经在上述节点运行, 那么它还可以继续运行在该节点上,因为第三个污点是三个污点中唯一不能被这个 Pod 容忍的。
通常情况下,如果给一个节点添加了一个 effect 值为 NoExecute 的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐,任何可以忍受这个污点的 Pod 都不会被驱逐。但是,如果 Pod 存在一个 effect 值为 NoExecute 的容忍度指定了可选属性 tolerationSeconds 的值,则表示在给节点添加了上述污点之后, Pod 还能继续在节点上运行的时间。例如:
这表示如果这个 Pod 正在运行,同时一个匹配的污点被添加到其所在的节点, 那么 Pod 还将继续在节点上运行 3600 秒,然后被驱逐。如果在此之前上述污点被删除了,则 Pod 不会被驱逐。
重新调度
在Kubernetes中,kube-scheduler负责将Pod调度到合适的Node上,但是Kubernetes是一个非常动态的,高度弹性的环境,有时候会造成某一个或多个节点pod数分配不均,比如:
一些节点利用率低下或过度使用
添加删除标签或添加删除污点,pod或Node亲和性改变等造成原调度不再满足
一些节点故障,其上运行的Pod调度到其他节点
新节点加入集群
由于以上种种原因,可能导致多个Pod运行到不太理想的节点,而整个K8S集群也会处于一段时间不均衡的状态,这时候就需要重新平衡集群。Descheduler就是这样一个项目。
Descheduler可以根据一些规则配置来重新平衡集群状态,目前支持的策略有:
- RemoveDuplicates
- LowNodeUtilization
- RemovePodsViolatingInterPodAntiAffinity
- RemovePodsViolatingNodeAffinity
- RemovePodsViolatingNodeTaints
- RemovePodsViolatingTopologySpreadConstraint
- RemovePodsHavingTooManyRestarts
- PodLifeTime
这些策略可以启用,也可以关闭,默认情况下,所有策略都是启动的。
另外,还有一些通用配置,如下:
- nodeSelector:限制要处理的节点
- evictLocalStoragePods: 驱除使用LocalStorage的Pods
- ignorePvcPods: 是否忽略配置PVC的Pods,默认是False
- maxNoOfPodsToEvictPerNode:节点允许的最大驱逐Pods数
由于我集群版本是1.24.2,所以安装descheduler v0.24版本。
(1)下载对应的Helm chart,我这里选择的是0.24版本
(2)如果可以科学上网,直接使用以下命令部署即可。
如果不能科学上网,就替换镜像,修改value.yaml里的镜像信息,如下:
然后再执行安装命令。
安装完成过后,会配置默认的调度策略,如下:
其中配置了:
- LowNodeUtilization:设置了cpu\内存\pod水位,thresholds表示未充分利用,targetThresholds表示过度使用
- RemoveDuplicates:开启同节点只有一个Pod运行
- RemovePodsViolatingInterPodAntiAffinity:删除违反亲和性的Pod
- RemovePodsViolatingNodeAffinity:删除不满足Node亲和性的Pod
- RemovePodsViolatingNodeTaints:删除不被Node污点容忍的Pod
并且会创建一个CronJob,周期性的执行调度均衡。
该Job会每2分钟执行一次均衡调度。
总结
Kubernetes的调度策略是非常复杂的,里面有许多复杂的算法,这里介绍的只是一些常用的调度策略,足够满足日常使用。如果想更深入的研究可以多看看官方文档以及源码。
