K8s 是如何完成调度和权重调整?

 容器魔方   2024-04-03 14:59   202 人阅读  0 条评论

K8s 是如何完成调度和权重调整?  第1张

一、概述

kube-scheduler作为 K8s 集群的默认调度器,它监听(watch机制)kube-apiserver,查询还未调度的 pod,根据调度策略将 pod 调度至集群内最适合的Node。

二、调度流程

首先我们通过 API 或者 kubectl 工具创建 pod,kube-apiserver 收到请求信息存储到 etcd 中,调度器通过 watch 机制监听 apiserver 查看到还未被调度的 pod 列表,循环遍历的为每个 pod 尝试分配 node,这个分配过程如下:

  • kube-scheduler 内 Informer 组件 list-watch apiserver,使用spec.nodeName=""筛选出还未调度的 Pod
  • 预选(predicate):调度器通过 Predicate 算法过滤掉不满足条件的节点
  • 优选(priorlty):对于通过预选的节点,通过打分机制,筛选出得分最高的node
  • 当调度器为 Pod 选择了一个合适的节点后,将 Pod 和节点进行绑定(将节点名称赋值给 pod 的 spec.nodeName 字段)

K8s 是如何完成调度和权重调整?  第2张

注意:Pod.spec.nodeName 用于强制约束将 Pod 调度到指定的 Node上,通过指定 nodeName 可直接绕过调度器,并不会做任何的资源过滤和检查。

三、kuble-scheduler 调度原理

Kube-scheduler 的调度框架,在 Kubernetes 里面叫作 Scheduler Framework。Pod 在调度过程中,都需要依次经过以下的各个阶段,每个阶段自带调度算法,调度算法由插件提供,也可以在指定阶段开发自己的插件。每个插件可以在指定阶段实现具体的调度算法,比如 NodeAffinity 插件在 Filter 阶段过滤掉与 Pod 不亲和的节点。

  • PreFilter:预处理 Pod 的相关信息,或者检查集群或 Pod 必须满足的某些条件。如果 PreFilter 插件返回错误,则调度周期将终止
  • Filter: 过滤出不能运行该 Pod 的节点。对于每个节点,调度器将按照其配置顺序调用这些过滤插件。如果任何过滤插件将节点标记为不可行,则节点直接排除,不会为该节点调用剩下的过滤插件
  • PostFilter: 在 Filter 阶段后调用,但仅在该 Pod 没有可行的节点时调用。典型的后筛选实现是抢占,试图通过抢占其他 Pod 的资源使该 Pod 可以调度
  • PreScore: 运行评分任务以生成可评分插件的共享状态,如果 PreScore 插件返回错误,则调度周期将终止
  • Score: 通过调用每个评分插件对可调度节点评分
  • NormalizeScore: 规范每个插件的打分在[0,100]之间
  • Reserve: 在绑定周期之前选择保留的节点
  • Permit: 批准或拒绝 pod 调度周期的结果
  • PreBind: 用于执行 Pod 绑定前所需的任何工作。例如,一个预绑定插件可能需要提供网络卷并且在允许 Pod 运行在该节点之前 将其挂载到目标节点上
  • Bind用于将 Pod 绑定到节点上。直到所有的 PreBind 插件都完成,Bind 插件才会被调用
  • PostBind: 这是个信息性的扩展点。绑定后插件在 Pod 成功绑定后被调用。这是绑定周期的结尾,可用于清理相关的资源

调度器预选阶段对应filter,主要用于过滤不满足 Pod 调度条件的节点;优选阶段对应 score,主要用于为每个节点打分,节点分数=插件打分*插件权重;然后排序选出分数最高的节点。

调度阶段

实现插件名称

插件功能介绍








filter

PodTopologySpread

判断节点是否满足 Pod 的拓扑分布,不满足则过滤该节点

InterPodAffinity

判断节点是否满足 Pod 的亲和性配置,不满足则过滤该节点

NodePorts

判断节点是否满足 Pod 的端口申请,不满足则过滤该节点

NodeAffinity

判断节点是否满足 Pod 的节点亲和性配置,不满足则过滤该节点

VolumeBinding

判断节点是否满足 pv 的节点亲和性,并且将满足动态创建 pvc 条件(比如拓扑)的节点保存起来,以便后续阶段使用

TaintToleration

根据 Pod 容忍和节点污点的 NoSchedule 和 NoExecute过滤节点







Score

NodeAffinity

根据插件权重算出得分,再根据策略权重比例算出节点分数,分数区间0~100,权重默认2

NodeResourcesBalancedAllocatio

根据不同resource(cpu、mem、volume)对节点容量的占比再加上对应 resource 的权重得到分数,分数区间0~100,权重默认1

ImageLocality

根据 Pod 中镜像大小以及镜像在所有节点上的分布来打分,分数区间0~100,权重默认1

InterPodAffinity

根据插件权重算出得分,再根据策略权重比例算出节点分数,分数区间0~100,权重默认2

TaintToleration

根据PreferNoSchedule策略算出分数,分数区间0~100,权重默认3

NodeResourcesFit

三种策略:LeastAllocated (分配越少得分越高)、MostAllocated (分配越多得分越高)、RequestedToCapacityRatio (请求值与容量比率)

PodTopologySpread

根据拓扑匹配度和权重得出分数,分数区间0~100,权重默认2

3.1 kubernetes 1.23版本调度器filter阶段和score阶段源码分析

K8s 是如何完成调度和权重调整?  第3张

3.2 修改调度器插件默认权重示例

3.2.1 环境准备

环境:集群中有两个节点:k8s-0001和 k8s-0002;已有工作负载 nginx,调度至节点 k8s-0002,工作负载 test),yaml 文件如下: 


apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  selector:
    matchLabels:
      app: test
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
        - name: container-1
          image: nginx:latest
      dnsPolicy: ClusterFirst
      affinity:
        nodeAffinity:     #利用节点亲和使其调度至k8s-0001
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              preference:
                matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                      - k8s-0001
        podAffinity:      #利用负载亲和使其调度至k8s-0002
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - nginx
                namespaces:
                  - default
                topologyKey: kubernetes.io/hostnam


3.2.2 调整InterPodAffinity权重,使工作负载test调度至节点k8s-0002

apiVersion: v1
kind: ConfigMap
metadata:
  name: scheduler-config
  namespace: kube-system
data:
  scheduler-config.yaml: |
    apiVersion: kubescheduler.config.k8s.io/v1beta3  #1.23以上版本集群可用v1beta3
    kind: KubeSchedulerConfiguration
    profiles:
    - schedulerName: default-scheduler 
      plugins:
        score:
          disabled:
          - name: InterPodAffinity
          - name: NodeAffinity
          enabled:
          - name: InterPodAffinity  #提高负载亲和权重
            weight: 100
          - name: NodeAffinity
            weight: 1

查看 kube-scheduler 调度日志,k8s-002 score得分为打分100 * 权重 100共得10000分,调度到 k8s-002 节点上。

K8s 是如何完成调度和权重调整?  第4张

3.2.3 调整NodeAffinity权重,使工作负载test调度至节点k8s-0001

apiVersion: v1
kind: ConfigMap
metadata:
  name: scheduler-config
  namespace: kube-system
data:
  scheduler-config.yaml: |
    apiVersion: kubescheduler.config.k8s.io/v1beta3
    kind: KubeSchedulerConfiguration
    profiles:
    - schedulerName: default-scheduler 
      plugins:
        score:
          disabled:
          - name: InterPodAffinity
          - name: NodeAffinity
          enabled:
          - name: InterPodAffinity
            weight: 1
          - name: NodeAffinity      #提高节点亲和权重
            weight: 100

K8s 是如何完成调度和权重调整?  第5张


本文转载自:容器魔方,版权归原作者所有。





免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!



K8s 是如何完成调度和权重调整?  第6张
本文地址:https://www.dockerworld.cn/?id=371
温馨提示:文章内容系作者个人观点,不代表Docker中文社区对观点赞同或支持。
版权声明:本文为转载文章,来源于 容器魔方 ,版权归原作者所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

还没有留言,还不快点抢沙发?