Kubernetes调度管理优先级和抢占机制是什么


今天小编给大家分享一下Kubernetes调度管理优先级和抢占机制是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。在日常工作中,每个机场都有调度室,用来管理飞机应该从哪里降落,停在什么地方。在Kubernetes也有这样的调度器,主要作用就是将Pod安排到合适的节点上。Kubernetes中的调度器是kube-scheduler,工作流程如下:在集群中所有Node中,根据调度算法挑选出可以运行该Pod的所有Node;在上一步的基础上,再根据调度算法给筛选出的Node进行打分,筛选出分数最高的Node进行调度;将Pod的spec.nodeName填上调度结果的Node名字;其原理图如下:由上图可知,Kubernetes的调度器核心是两个相互独立的控制循环。1、Informer Path其主要作用是启动一个Informer来监听Etcd中Pod,Node,Service等与调度器相关的API对象的变化。当一个Pod被创建出来后,就被通过Informer Handler将待调度的Pod放入调度队列中,默认情况下,Kubernetes的调度策略是一个优先级队列,并且当集群信息发生变化的时候,调度器还会对调度队列里的内容进行一些特殊操作。而且Kubernetes的默认调度器还负责对调度器缓存(scheduler cache)进行更新,以执行调度算法的执行效率。2、Scheduler Path其主要逻辑是不断从队列中出一个Pod,然后调用Predicates进行过滤,然后得到一组Node(也就是可运行Pod的所有Node信息,这些信息都是来自scheduler cache),接下来调用Priorities对筛选出的Node进行打分,然后分数最高的Node会作为本次调度选择的对象。调度完成后,调度器需要将Pod的spec.nodeName的值修改为调度的Node名字,这个步骤称为Bind。但是在Bind阶段,Kubernetes默认调度器只会更新scheduler cache中的信息,这种基于乐观假设的API对象更新方式被称为Assume。在Assume之后,调度器才会向API Server发起更新Pod的请求,来真正完成Bind操作。如果本次Bind失败,等到scheduler cache更新之后又会恢复正常。正是由于有Assume的原因,当一个Pod完成调度需要在某个Node节点运行之前,kubelet还会进行一步Admit操作来验证该Pod是否能够运行在该Node上,作为kubelet的二次验证。常用的预算策略有:CheckNodeConditionGeneralPredication:HostName, PodFitsHostPort, MatchNodeSelector, PodFitsResourcesNoDiskConflict正常情况下,当一个Pod调度失败后,它会被搁置起来,直到Pod被更新,或者集群状态发生变化,调度器才会对这个Pod进行重新调度。但是有的时候我们不希望一个高优先级的Pod在调度失败就被搁置,而是会把某个Node上的一些低优先级的Pod删除,来保证高优先级的Pod可以调度成功。Kubernetes中优先级是通过ProrityClass来定义,如下:其中的value就是优先级数值,数值越大,优先级越高。优先级是一个32bit的整数,最大值不超过10亿,超过10亿的值是被Kubernetes保留下来作为系统Pod使用的,就是为了保证系统Pod不会被抢占。另外如果globalDefault的值设置为 true的话表明这个PriorityClass的值会成为系统默认值,如果是false就表示只有在申明这个PriorityClass的Pod才会拥有这个优先级,而对于其他没有申明的,其优先级为0。如下定义Pod并定义优先级:上面的PriotiryClassName就是定义我们的PriorityClass,当这个Pod提交给Kubernetes之后,Kubernetes的PriorityAdmissionController会自动将这个Pod的spec.priority字段设置为我们定义的值。而当这个Pod拥有这个优先级之后,高优先级的Pod就可能比低优先级的Pod先出队,从而尽早完成调度。而当一个高优先级的Pod调度失败后,其抢占机制就会被触发,这时候调度器就会试图从当前的集群中寻找一个节点,使得这个节点上的一个或多个低优先级的Pod被删除,然后这个高优先级的Pod就可以被调度到这个节点上。当抢占发生时,这个高优先级Pod并不会立即调度到即将抢占的节点上,调度器只会将这个Pod的spec.nominatedNodeName的值设置为被抢占节点的Node名字,然后这个Pod会重新进入下一个调度周期,然后会在这个周期内决定这个Pod被调度到哪个节点上。在这个重新调度期间,如果有一个更高的优先级Pod也要抢占这个节点,那么调度器就会清空原Pod的nominatedNodeName的值,而更高优先级的Pod将会抢占这个值。**实现原理:**Kubernetes用两个队列来实现抢占算法:ActiveQ和unschedulableQ。ActiveQ:凡是在ActiveQ里的Pod,都是下一个周期需要调度的对象,所以当Kubernetes创建一个新的Pod,这个Pod就会被放入ActiveQ里;unschedulableQ:专门用来存放调度失败的Pod;那么如果一个Pod调度失败,调度器就会将其放入unschedulableQ里,然后调度器会检查这个调度失败的原因,分析并确认是否可以通过抢占来解决此次调度问题,如果确定抢占可以发生,那么调度器就会把自己缓存的所有信息都重新复制一份,然后使用这个副本来模拟抢占过程。如果模拟通过,调度器就会真正开始抢占操作了:调度器会检查牺牲者列表,清空这些Pod所携带的nominatedNodeName字段;调度器会把抢占者的nominatedNodeName的字段设置为被抢占的Node名字;调度器会开启Goroutine,同步的删除牺牲者;接下来调度器就会通过正常的调度流程,把抢占者调度成功。在这个过程中,调度器会对这个Node,进行两次Predicates算法:假设上述抢占者已经运行在这个节点上,然后运行Predicates算法;调度器正常执行Predicates算法;只有上述者两个都通过的情况下,这个Node和Pod才会被 绑定。上面介绍的是Kubernetres默认的调度策略,有时候默认的调度策略不能满足我们的需求,比如想把Pod调免费云主机域名度到指定的节点,或者不让某些节点调度Pod。这时候就要用到更高级的调度策略,主要有如下几种:nodeSelectornodeNamenodeAffinitypodAffinitypodAntiAffinity污点调度nodeSelector也可以叫做节点选择器,其原理是通过在节点上定义label标签,然后Pod中指定选择这些标签,让Pod能够调度到指定的节点上。比如给kk-node01指定env=uat标签,命令如下:现在在Pod的YAML清单中配置nodeSelector,如下:这样,该Pod就会调度到kk-node01节点上,如果该Pod指定为env=prod,则调度不到kk-node01节点。nodeName也是节点选择器,和nodeSelector不同之处在于nodeName是直接指定节点名,这属于强调度,定义方式如下:nodeAffinity叫做节点亲和性调度,其调度方式比nodeSelector和nodeName更强大。目前,nodeAffinity支持两种调度策略:preferredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution表示如果有Node匹配,则优先调度到该Node,如果没有,可以根据配置调度到其他节点。requiredDuringSchedulingIgnoredDuringExecution则表示必须满足条件的节点才允许调度。定义preferredDuringSchedulingIgnoredDuringExecution的例子如下:requiredDuringSchedulingIgnoredDuringExecution的例子如下:其中,operator支持In,NotIn, Exists, DoesNotExist. Gt, and Lt。上面介绍的nodeSelector,nodeName,nodeAffinity都是针对节点的,下面介绍的podAffinity和podAntiAffinity则是针对Pod。podAffinity表示Pod亲和性调度,意识就是把Pod调度到与它比较紧密的Pod上,如下:这表示把后端pod和前端pod调度在一起。podAffinity也有preferredDuringSchedulingIgnoredDuringExecution和requiredDuringSchedulingIgnoredDuringExecution,也就是硬亲和和软亲和,其使用情况和nodeAffinity一样。上面介绍了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支持EqualExists,默认是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可以根据一些规则配置来重新平衡集群状态,目前支持的策略有:RemoveDuplicatesLowNodeUtilizationRemovePodsViolatingInterPodAntiAffinityRemovePodsViolatingNodeAffinityRemovePodsViolatingNodeTaintsRemovePodsViolatingTopologySpreadConstraintRemovePodsHavingTooManyRestartsPodLifeTime这些策略可以启用,也可以关闭,默认情况下,所有策略都是启动的。另外,还有一些通用配置,如下:nodeSelector:限制要处理的节点evictLocalStoragePods: 驱除使用LocalStorage的PodsignorePvcPods: 是否忽略配置PVC的Pods,默认是FalsemaxNoOfPodsToEvictPerNode:节点允许的最大驱逐Pods数由于我集群版本是1.24.2,所以安装descheduler v0.24版本。(1)下载对应的Helm chart,我这里选择的是0.24版本(2)如果可以科学上网,直接使用以下命令部署即可。如果不能科学上网,就替换镜像,修改value.yaml里的镜像信息,如下:然后再执行安装命令。安装完成过后,会配置默认的调度策略,如下:其中配置了:LowNodeUtilization:设置了cpu内存pod水位,thresholds表示未充分利用,targetThresholds表示过度使用RemoveDuplicates:开启同节点只有一个Pod运行RemovePodsViolatingInterPodAntiAffinity:删除违反亲和性的PodRemovePodsViolatingNodeAffinity:删除不满足Node亲和性的PodRemovePodsViolatingNodeTaints:删除不被Node污点容忍的Pod并且会创建一个CronJob,周期性的执行调度均衡。该Job会每2分钟执行一次均衡调度。以上就是“Kubernetes调度管理优先级和抢占机制是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注百云主机行业资讯频道。

相关推荐: nginx如何禁止访问php

这篇“nginx如何禁止访问php”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“nginx如何禁止访问php”文章吧。 nginx禁止访问php…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 02/23 22:22
Next 02/23 22:22

相关推荐