九、调度器
本文最后更新于135 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

1.简介

Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单,但有很多要考虑的问题:

  • 公平:如何保证每个节点都能被分配资源
  • 资源高效利用:集群所有资源最大化被使用
  • 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
  • 灵活:允许用户根据自己的需求控制调度的逻辑

Sheduler 是作为单独的程序运行的,启动之后会一直监听 API Server,获取 PodSpec.NodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上

调度过程

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为 预选;然后对通过的节点按照优先级排序,这个是 优选;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误

预选 有一系列的算法可以使用:

  • PodFitsResources:节点上剩余的资源是否大于 pod 请求的资源
  • PodFitsHost:如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配
  • PodFitsHostPorts:节点上已经使用的 port 是否和 pod 申请的 port 冲突
  • PodSelectorMatches:过滤掉和 pod 指定的 label 不匹配的节点
  • NoDiskConflict:已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读

如果在 预选 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续 优选 过程: 按照优先级大小对节点排序

优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:

  • LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点
  • BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用
  • ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高

通过算法对所有的优先级项目和权重进行计算,得出最终的结果

自定义调度器

除了 kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec:schedulername 参数指定调度器的名字,可以为 pod 选择某个调度器进行调度。比如下面的 pod 选择 my-scheduler 进行调度,而不是默认的 default-scheduler
但是想想就得了,谷歌的调度器很牛逼,这么多年也没新的调度器

apiVersion: v1
kind: Pod
metadata:
  name: test-scheduler
  labels:
    name: test-scheduler
spec:
  schedulername: test-scheduler
  containers:
  - name: pod-with-second-annotation-container
    image: cedarz/myapp:v2

2.亲和性

节点亲和性 pod node

pod.spec.nodeAffinity

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略

如果有多个满足亲和性,那么就进行优选,选择最优解

示例

requiredDuringSchedulingIgnoredDuringExecution

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: wangyanglinux/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - k8s-node03

preferredDuringSchedulingIgnoredDuringExecution

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: wangyanglinux/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: source
            operator: In
            values:
            - qikqiak

合体:
结合目的是目标可以不一样,比如硬亲和一定要有GPU,软亲和第一个节点(3090ti)

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: wangyanglinux/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - k8s-node02
      preferredDuringSchedulingIgnoredDuringExecution:
      # 有多个亲和的话谁的权重高亲和谁
      - weight: 1
        # 偏好
        preference:
          matchExpressions:
          - key: source
            operator: In
            values:
            - qikqiak

键值运算关系

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExpressions有多个选项的话,则必须同时满足这些条件才能正常调度 POD

Pod 亲和性

pod.spec.affinity.podAffinity/podAntiAffinity

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    app: pod-3
spec:
  containers:
  - name: pod-3
    image: wangyanglinux/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-2
          topologyKey: kubernetes.io/hostname

亲和性/反亲和性调度策略比较

调度策略 匹配标签 操作符 拓扑域支持 调度目标
nodeAffinity 主机 In, NotIn, Exists, DoesNotExist, Gt, Lt 指定主机
podAffinity POD In, NotIn, Exists, DoesNotExist POD与指定POD同一拓扑域
podAnitAffinity POD In, NotIn, Exists, DoesNotExist POD与指定POD不在同一拓扑域

pod亲和性是不支持大于小于的,可以在节点亲和的时候设置大于四个CPU等等
而节点亲和性不支持拓扑域

举例:

就像是你是为了和小明在一起去的北京,还是为了去北京,去了之后跟小明在一起
如果有一天小明跑上海去了,那么节点亲和性的小红就留在北京,而pod亲和性的小红会在日后去找小明
如果是nginx和Tomcat,nginx是Tomcat的静态资源缓存,需要经常互动,那么pod的亲和性就很好用
同样,如果一个是lamp的数据库,一个是bbs的数据库,数据库对磁盘的I/O要求很高,那么非亲和性就很重要

拓扑域

假如不同机器的拓扑域是disktype=ssd
在一起不代表在一台机器
那么新建的pod可能在两台具有disktype=ssd标签的任意一台机器上创建

拓扑域的意义:

如果一台机器运行的有点多,放不下新的pod了,那么要尽量同机架,同机房,同数据中心
因为光靠节点不足以进行区分,那么就可以拓扑域设置为同机房,同机架同数据中心等等
也就是说,只要这两个pod的拓扑域的key和values相同,就算在一起了,不一定在一个节点
拓扑域只写key,不用values,但是key和值是一样的才算一个拓扑域,比如node01和node02就不是一个拓扑域

举例:

济宁医学院PACS系统上线时,医院选择的是联通云环境部署.但是联通属实有点坑,一共六台虚拟机分布在三个不同的拓扑域,甚至是不在同一个数据中心,就导致部署k8s集群以后,其他节点上都无法与node1,node2上的所有podIP通信,node1与node2也无法通信,底层物理机的路由没有配置好,而且不支持BGP模式,只支持IPIP模式.


Taint 和 Toleration

节点亲和性,是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点。Taint 则相反,它使 节点 能够 排斥 一类特定的 pod

Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有匹配 taint 的节点上

污点(Taint)

Ⅰ、 污点 ( Taint ) 的组成

使用 kubectl taint 命令可以给某个 Node 节点设置污点,Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去

每个污点的组成如下:

key=value:effect

values是可以省略的,设置的时候等于空就是省略

每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。当前 taint effect 支持如下三个选项:

  • NoSchedule:表示 k8s 将不会把 Pod 调度到具有该污点的 Node 上(有特定资源的,比如GPU)
  • PreferNoSchedule:表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上(- 比如多master的时候,干看着也浪费,干点是点)
  • NoExecute:表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去(比如更新的时候,加个内存条啥的,pod会一点一点死,去别的地方重建起来,然后再关机升级;驱离一般会加个限期,比如60s,3600s,让pod可以有序的离开)

Ⅱ、污点的设置、查看和去除

# 设置污点
kubectl taint nodes node1 key1=value1:NoSchedule

# 节点说明中,查找 Taints 字段
kubectl describe pod  pod-name  

# 去除污点,就是在后面加个-
kubectl taint nodes node1 key1:NoSchedule-

容忍(Tolerations)

设置了污点的 Node 将根据 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上。 但我们可以在 Pod 上设置容忍 ( Toleration ) ,意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的 Node 上

pod.spec.tolerations

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule"

Ⅰ、当不指定 key 值时,表示容忍所有的污点 key:

tolerations:
- operator: "Exists"

Ⅱ、当不指定 effect 值时,表示容忍所有的污点作用

tolerations:
- key: "key"
  operator: "Exists"

Ⅲ、有多个 Master 存在时,防止资源浪费,可以如下设置

  kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule

指定调度节点

Ⅰ、Pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配
跳过的是优选,因为必须满足运行条件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 7
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeName: k8s-node01
      containers:
      - name: myweb
        image: wangyanglinux/myapp:v1
        ports:
        - containerPort: 80

Ⅱ、Pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,而后调度 Pod 到目标节点,该匹配规则属于强制约束

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeSelector:
        type: backEndNode1
      containers:
      - name: myweb
        image: harbor/tomcat:8.5-jre8
        ports:
        - containerPort: 80
男孩子都是香香软软的小猪

评论

  1. test
    Windows Chrome
    4 月前
    2024-7-10 9:55:42

    写的不错哦

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇