k8s调度

  往 kube-ApiServer 里面提交 yaml 文件,ApiServer 会先把这个待创建的请求路由给 webhooks 的 Controlles 进行校验。

  通过校验之后,ApiServer 会在集群里面生成一个 pod,但此时生成的 pod,它的 nodeName 是空的,并且它是 Pending 状态。在生成了这个 pod 之后,kube-Scheduler 以及 kubelet 都能 watch 到这个 pod 的生成事件,kube-Scheduler 发现这个 pod 的 nodeName 是空的之后,会认为这个 pod 是处于未调度状态。

  通过一系列的调度算法,包括一系列的过滤和打分的算法后,Schedule 会选出一台最合适的节点,并且把这一台节点的名称绑定在这个 pod 的 spec 上,完成一次调度的过程。

  更新完 nodeName 之后,在 节点 上的 kubelet 会 watch 到这个 pod 是属于自己节点上的一个 pod。然后它会把这个 pod 拿到节点上进行操作,包括创建一些容器 storage 以及 network,最后等所有的资源都准备完成,kubelet 会把状态更新为 Running,这样一个完整的调度过程就结束了。

基础调度能力

  资源调度  Resources 的配置方式  Qos  Resource Quota

  关系调度  pod 和 pod 之间的关系场景  pod 和 node 之间的关系场景

  container 里面有一个 resources 字段。resources 包含两个部分:第一部分是 request;第二部分是 limits。

  资源调度

  四大类的基础资源:

    第一类是 CPU 资源;第二类是 memory;第三类是 ephemeral-storage,一种临时存储;第四类是通用的扩展资源,比如说像 GPU。

  K8s 在 pod resources 里面提供了两种填写方式:第一种是 request,第二种是 limit。它其实是为用户提供了对 Pod 一种弹性能力的定义。

  Qos 全称是 Quality of Service,它其实是 Kubernetes 用来表达一个 pod 在资源能力上的服务质量的标准,Kubernetes 提供了三类的 Qos Class:

     第一类是 Guaranteed,它是一类高的 Qos Class,一般用 Guaranteed 来为一些需要资源保障能力的 pod 进行配置;基础资源(就是包括 CPU 和 memory),必须它的 request==limit

    第二类是 Burstable,它其实是中等的一个 Qos label,一般会为一些希望有弹性能力的 pod 来配置 Burstable;只要满足 CPU/Memory  的 request 和 limit 不相等

    第三类是 BestEffort,通过名字我们也知道,它是一种尽力而为式的服务质量。所有资源的 request/limit 都不填

    用户没法指定自己的 pod 是属于哪一类 Qos,而是通过 request 和 limit 的组合来自动地映射上 Qos Class。在 spec 提交成功之后,Kubernetes 会自动给补上一个 status,里面是 qosClass: xxx

  调度表现,调度器只会使用 request 进行调度,也就是不管你配了多大的 limit,它都不会进行调度使用,它只会使用 request 进行调度。

  非整数的 Guaranteed/Burstable/BestEffort,它们的资源 会放在一块,组成一个share pool,被非整数的 Guaranteed/Burstable/BestEffort 共享

  在 memory 上也会按照不同的 Qos 进行划分:OOMScore。比如说 Guaranteed,它会配置默认的 -998 的 OOMScore;Burstable 的话,它会根据内存设计的大小和节点的关系来分配 2-999 的 OOMScore。BestEffort 会固定分配 1000 的 OOMScore,OOMScore 得分越高的话,在物理机出现 OOM 的时候会优先被 kill 掉。

  发生 eviction 的时候,会优先考虑驱逐 BestEffort 的 pod。所以不同的 Qos 其实在底层的表现是截然不同的。这也反过来要求我们在生产过程中,根据不同业务的要求和属性来配置资源的 Limits 和 Request,做到合理的规划 Qos Class。

  ResourceQuota 。可以做到限制 namespace 资源用量。它的 spec 包括了一个 hard 和 scopeSelector。hard 内容其实和 Resourcelist 很像,这里可以填一些基础的资源。但是它比 ResourceList 更丰富一点,它还可以填写一些 Pod,这样可以限制 Pod 数量能力。scopeSelector 字段定义更丰富的索引能力,包括 Terminating/Not Terminating,BestEffort/NotBestEffort,PriorityClass。

  关系调度

     Pod 亲和调度:PodAffinity

        podAffinity,然后填上 required 要求,假如能找到带 key: k1 的 Pod 所在节点,就会调度成功。假如这个集群不存在这样的 Pod 节点,或者是资源不够的时候,那就会调度失败。这是一个严格的亲和调度,我们叫做尝试亲和调度。

        把 required 改成 preferred,变成一个优先亲和调度。也就是优先可以调度带 key: k2 的 Pod 所在节点。并且这个 preferred 里面可以是一个 list 选择,可以填上多个条件,比如权重等于 100 的是 key: k2,权重等于 10 的是 key: k1。那调度器在调度的时候会优先把这个 Pod 分配到权重分更高的调度条件节点上去。

    Pod 反亲和调度:PodAntAffinity

        语法上基本上是一样的,只是 podAffinity 换成了 podAntiAffinity,做到的效果也是 required 强制反亲和,以及一个 preferred 优先反亲和

    Node 亲和调度

      和 PodAffinity 有点类似,也提供了两类调度的策略:第一类是 required,必须调度到某一类 Node 上;第二类是 preferred,就是优先调度到某一类 Node 上。

    第三类调度,可以通过给 Node 打一些标记,来限制 Pod 调度到某些 Node 上。Kubernetes 把这些标记称之为 Taints,它的字面意思是污染。

      taints 内容包括 key、value、effect:key 就是配置的键值,value 就是内容,effect 是标记了这个 taints 行为是什么

      目前 Kubernetes 里面有三个 taints 行为:NoSchedule 禁止新的 Pod 调度上来;PreferNoSchedul 尽量不调度到这台;NoExecute 会 evict 没有对应 toleration 的 Pods,并且也不会调度新的上来。

      想要调度到这个节点时,需要在 Pod 上打一个 Pod Tolerations。在 Pod 的 spec 中填写一个 Tolerations,它里面也包含了 key、value、effect,这三个值和 taint 的值是完全对应的,taint 里面的 key,value,effect 是什么内容,Tolerations 里面也要填写相同的内容。

高级调度能力-优先级调度和抢占

  当集群资源足够的话,只需要通过基础调度能力就能组合出合理的使用方式。但是假如资源不够,如何做到集群的合理利用

  优先级策略会比先到先得策略更能够符合生产业务特点  

  使用优先级调度

    需要创建一个 priorityClass,然后再为每个 Pod 配置上不同的 priorityClassName,这样就完成了优先级以及优先级调度的配置。

    只触发优先级调度但是没有触发抢占调度的流程

      有一个 Pod1 和 Pod2,Pod1 配置了高优先级,Pod2 配置了低优先级。同时提交 Pod1 和 Pod2 到调度队列里。调度器处理队列的时候会挑选一个高优先级的 Pod1 进行调度,经过调度过程把 Pod1 绑定到 Node1 上。其次再挑选一个低优先的 Pod2 进行同样的过程,绑定到 Node1 上。

    优先级抢占过程

      高优先级的 Pod 在调度的时候没有资源,会进行整个集群的节点筛选,最后挑出要抢占的 Pod 是 Pod2,此时调度器会把 Pod2 从 Node1 上移除数据。

      一个 Pod 进入抢占的时候,会判断 Pod 是否拥有抢占的资格,有可能上次已经抢占过一次。如果符合抢占资格,它会先对所有的节点进行一次过滤,过滤出符合这次抢占要求的节点,如果不符合就过滤掉这批节点。接着从过滤剩下的节点中,挑选出合适的节点进行抢占。这次抢占的过程会模拟一次调度,也就是把上面优先级低的 Pod 先移除出去,再把待抢占的 Pod 尝试能否放置到此节点上。然后通过这个过程选出一批节点,进入下一个过程叫 ProcessPreemptionWithExtenders。这是一个扩展的钩子,用户可以在这里加一些自己抢占节点的策略,如果没有扩展的钩子,这里面是不做任何动作的。接下来的流程叫做 PickOneNodeForPreemption,就是从上面 selectNodeForPreemption list 里面挑选出最合适的一个节。

      挑选策略:优先选择打破 PDB(Pod Disruption Budget) 最少的节点;其次选择待抢占 Pods 中最大优先级最小的节点;再次选择待抢占 Pods 优先级加和最小的节点;接下来选择待抢占 Pods 数目最小的节点;最后选择拥有最晚启动 Pod 的节点;

posted @ 2023-11-02 22:09  花都八达鸟  阅读(44)  评论(0)    收藏  举报