Overview

kube-scheduler 是kubernetes控制平面的核心组件,其默认行为是将 pod 分配给节点,同时平衡Pod与Node间的资源利用率。通俗来讲就是 kube-scheduler 在运行在控制平面,并将工作负载分配给 Kubernetes 集群。

本文将深入 Kubernetes 调度的使用,包含:”一般调度”,”亲和度“,“污点与容忍的调度驱逐”。最后会分析下 Scheduler Performance Tuning,即微调scheduler的参数来适应集群。

简单的调度

NodeName [1]

最简单的调度可以指定一个 NodeName 字段,使Pod可以运行在对应的节点上。如下列资源清单所示

apiVersion: v1
kind: Pod
metadata:name: netpod
spec:containers:- name: netboximage: cylonchau/netboxnodeName: node01

通过上面的资源清单Pod最终会在 node01上运行。这种情况下也会存在很多的弊端,如资源节点不足,未知的nodename都会影响到Pod的正常工作,通常情况下,这种方式是不推荐的。

$ kubectl describe pods netpod
Name:         netpod
Namespace:    default...QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300snode.kubernetes.io/unreachable:NoExecute for 300s
Events:Type    Reason   Age   From     Message----    ------   ----  ----     -------Normal  Pulling  86s   kubelet  Pulling image "cylonchau/netbox"Normal  Pulled   17s   kubelet  Successfully pulled image "cylonchau/netbox"Normal  Created  17s   kubelet  Created container netboxNormal  Started  17s   kubelet  Started container netbox$ kubectl get pods netpod  -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
netpod   1/1     Running   0          48m   192.168.0.3   node01   <none>           <none>

通过上面的输出可以确定,通过 NodeName 方式是不经过 scheduler 调度的

nodeSelector [2]

label 是 kubernetes中一个很重要的概念,通常情况下,每一个工作节点都被赋予多组 label ,可以通过命令查看对应的 label

$ kubectl get node node01 --show-labels
NAME     STATUS   ROLES    AGE   VERSION    LABELS
node01   Ready    <none>   15h   v1.18.20   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux

nodeSelector 就是根据这些 label ,来选择具有特定一个或多个标签的节点。例如,如果需要在一组特定的节点上运行pod,可以设置在 “PodSpec” 中定义nodeSelector 为一组键值对:

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-nodeselector
spec:selector:matchLabels:app: netpodreplicas: 2 template:metadata:labels:app: netpodspec:containers:- name: netboximage: cylonchau/netboxnodeSelector: beta.kubernetes.io/os: linux

对于上面的pod来讲,Kubernetes Scheduler 会找到带有 beta.kubernetes.io/os: linux标签的节点。对于更多kubernetes内置的标签,可以参考 [3]

对于标签选择器来说,最终会分布在具有标签的节点上

kubectl describe pod netpod-nodeselector-69fdb567d8-lcnv6
Name:         netpod-nodeselector-69fdb567d8-lcnv6
Namespace:    default...QoS Class:       BestEffort
Node-Selectors:  beta.kubernetes.io/os=linux
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300snode.kubernetes.io/unreachable:NoExecute for 300s
Events:Type    Reason     Age    From               Message----    ------     ----   ----               -------Normal  Scheduled  8m18s  default-scheduler  Successfully assigned default/netpod-nodeselector-69fdb567d8-lcnv6 to node01Normal  Pulling    8m17s  kubelet            Pulling image "cylonchau/netbox"Normal  Pulled     7m25s  kubelet            Successfully pulled image "cylonchau/netbox"Normal  Created    7m25s  kubelet            Created container netboxNormal  Started    7m25s  kubelet            Started container netbox

节点亲和性 [4]

对于使用了调度功能的系统来说,亲和度 (Affinity)是个很常见的概念,通常亲和度发生在并行(parallel )环境中;在这种环境下,亲和度提供了在一个节点上运行pod可能比在其他节点上运行更有效,而计算亲和度通常由多种条件组成。一般情况下,亲和度分为“软亲和硬亲和

  • 软亲和,Soft Affinity,是调度器尽可能将任务保持在同一个节点上。这只是一种尝试;如果不可行,则将进程迁移到另一个节点
  • 硬亲和,Hard affinity,硬亲和度是强行将任务绑定到指定的节点上

而在kubernetes中也支持亲和度的概念,而亲和度是与 nodeSelector 配合形成的一个算法。其中硬亲和被定义为requiredDuringSchedulingIgnoredDuringExecution;软亲和被定义为 preferredDuringSchedulingIgnoredDuringExecution

  • 硬亲和性(requiredDuringSchedulingIgnoredDuringExecution):必须满足条件,否则调度程序无法调度 Pod。
  • 软亲和性 (preferredDuringSchedulingIgnoredDuringExecution):scheduler 将查找符合条件的节点。如果没有满足要求的节点将忽略这条规则,scheduler 将仍会调度 Pod。

Node Affinity

Node Affinity参数说明

调度程序会更倾向于将 pod 调度到满足该字段指定的亲和性表达式的节点,但它可能会选择违反一个或多个表达式的节点。最优选的节点是权重总和最大的节点,即对于满足所有调度要求(资源请求、requiredDuringScheduling 亲和表达式等)的每个节点,通过迭代该字段的元素来计算总和如果节点匹配相应的matchExpressions,则将“权重”添加到总和中;具有最高和的节点是最优选的。

如果在调度时不满足该字段指定的亲和性要求,则不会将 Pod 调度到该节点上。如果在 pod 执行期间的某个时间点不再满足此字段指定的亲和性要求(例如,由于更新),系统可能会或可能不会尝试最终将 pod 从其节点中逐出。

affinity 范围应用于 Pod.Spec 下,参数如下:

  • nodeAffinity:node亲和度相关根配置

    • preferredDuringSchedulingIgnoredDuringExecution:软亲和

      • preference (required):选择器

        • matchExpressions:匹配表达式,标签可以指定部分

          • key (<string> -required-):
          • operator (<string> -required-):# 与一组 key-values的运算方式。
            • In, NotIn, Exists, DoesNotExist, Gt, Lt。
          • values (<[]string>):
        • matchFields: 匹配字段
          • key (<string> -required-):
          • operator (<string> -required-):# 与一组 key-values的运算方式。
            • In, NotIn, Exists, DoesNotExist, Gt, Lt。
          • values (<[]string>):
      • weight (required):范围为 1-100,具有最高和的节点是最优选的
    • requiredDuringSchedulingIgnoredDuringExecution:硬亲和
      • nodeSelectorTerms

        • matchExpressions

          • key (<string> -required-):
          • operator (<string> -required-):# 与一组 key-values的运算方式。
            • In, NotIn, Exists, DoesNotExist, Gt, Lt。
          • values (<[]string>):
        • matchFields
          • key (<string> -required-):
          • operator (<string> -required-):一组 key-values 的运算方式。
            • In, NotIn, Exists, DoesNotExist, Gt, Lt。
          • values (<[]string>):

Notes: matchFields使用的是资源清单的字段(kubectl get node -o yaml),而matchExpressions匹配的是标签

Node Affinity示例

上面的介绍了解到了Kubernetes中相对与 nodeSelector可以更好表达复杂的调度需求:节点亲和性,使用PodSpec中的字段 .spec.affinity.nodeAffinity 指定相关 affinity 配置。

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-nodeselector
spec:selector:matchLabels:app: netpodreplicas: 2 template:metadata:labels:app: netpodspec:containers:- name: netboximage: cylonchau/netboxaffinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: appoperator: Invalues:- test

上面的清单表明,当节点存在 app: test 标签时,会调度到对应的Node上,如果没有节点匹配这些条件也不要紧,会根据普通匹配进行调度。

当硬策略和软策略同时存在时的情况,根据设置的不同,硬策略优先级会高于软策略,哪怕软策略权重设置为100

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-nodeselector
spec:selector:matchLabels:app: netpodreplicas: 2 template:metadata:labels:app: netpodspec:containers:- name: netboximage: cylonchau/netboxaffinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: appoperator: In values:- testrequiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: topology.kubernetes.io/zoneoperator: Invalues:- antarctica-east1- antarctica-west1

下面是报错信息

Warning  FailedScheduling  4s (x3 over 24s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match node selector.

Pod亲和性 [4]

pod亲和性和反亲和性是指根据节点上已运行的Pod的标签而不是Node标签来限制Pod可以在哪些节点上调度。例如:X 满足一个或多个运行 Y 的条件,这个时候 Pod满足在X中运行。其中 X 为拓扑域,Y 则是规则。

Notes:官方文档中不推荐pod亲和度在超过百个节点的集群中使用该功能 [5]

Pod亲和性配置

Pod亲和性和反亲和性与Node亲和性类似,affinity 范围应用于 Pod.Spec.podAffinity 下,这里不做重复复述,可以参考Node亲和性参数说明部分。

topologyKey,不允许是空值,该值将影响Pod部署的位置,影响范围为,与亲和性条件匹配的对应的节点中的什么拓扑,topologyKey的拓扑域由label标签决定。

除了 topologyKey 之外,还有标签选择器 labelSelector 与 名称空间 namespaces 可以作为同级的替代选项

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-podaffinity
spec:selector:matchLabels:app: podaffinityreplicas: 1 template:metadata:labels:app: podaffinityspec:containers:- name: podaffinityimage: cylonchau/netboxaffinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- netpodtopologyKey: zone

如果没有Pod匹配到规则,则pending状态

Warning  FailedScheduling  59s (x2 over 59s)  default-scheduler  0/2 nodes are available: 2 node(s) didn't match pod affinity rules, 2 node(s) didn't match pod affinity/anti-affinity.

Pod Anti-Affinity

在某些场景下,部分节点不应该有很多资源,即某些节点不想被调度。例如监控运行节点由于其性质,不希望该节点上有很多资源,或者因节点配置的不同,配置较低节点不希望调度很多资源;在这种情况下,如果将符合预期之外的Pod调度过来会降低其托管业务的性能。这种情况下就需要 反亲和度Anti-Affinity)来使Pod远离这组节点

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-podaffinity
spec:selector:matchLabels:app: podaffinityreplicas: 1 template:metadata:labels:app: podaffinityspec:containers:- name: podaffinityimage: cylonchau/netboxaffinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- netpodtopologyKey: zone

Taints And Tolerations [6]

Taints

亲和度和反亲和度虽然可以阻止Pod在特定节点上运行,但还存在一个问题,就是亲和度和反亲和度需要声明运行的节点或者是不想运行的节点,如果忘记声明,还是会被调度到对应的Node上。Kubernetes还提供了一种驱逐Pod的方法,就是污点(Taints)与容忍(Tolerations)。

创建一个污点

kubectl taint nodes node1 key1=value1:NoSchedule$ kubectl taint nodes mon01 role=monitoring:NoSchedule

删除一个污点,

kubectl taint nodes node1 key1=value1:NoSchedule-

除了 NoSchedule ,还有 PreferNoSchedule 与 NoExecute

  • PreferNoSchedule :类似于软亲和性的属性,尽量去避免污点,但不是强制的。
  • NoExecute 表示,当Pod还没在节点上运行时,并且存在至少一个污点时生效,此时Pod不会被调度到该节点;当Pod已经运行在节点上时,并且存在至少一个污点时生效,Pod将会从节点上被驱逐。

Tolerations

当Node有污点时,在调度时会自动被排除。当调度在受污染的节点上执行Predicate部分时将失败,而容忍度则是使 pod 具有对该节点上的污点进行容忍,即拥有容忍度的Pod可以调度到有污点的节点之上。

apiVersion: apps/v1
kind: Deployment
metadata:name: netpod-podaffinity
spec:selector:matchLabels:app: podaffinityreplicas: 1 template:metadata:labels:app: podaffinityspec:containers:- name: podaffinityimage: cylonchau/netboxtolerations:- key: "role"operator: "Equal"value: "monitoring"effect: "NoSchedule"affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- netpodtopologyKey: zone

容忍度中存在一个特殊字段 TolerationSeconds ,表示容忍的时间,默认不会设置,即永远容忍污点。设置成0或者负数表示理解驱逐。仅在污点为 NoExecute 时生效

operator 属性有两个值 ExistsEqual

  • 如果 operator 为 Exists,则无需 value 属性,因为判断的是有污点的情况下。

  • 如果 operator 为 Equal,则表示 key 与 value 之间的关系是 key=valuekey=valuekey=value

  • 空 key,并且operator为 Exists,将匹配到所有,即容忍所有污点

  • effect 匹配所有 effect ,即匹配所有污点;这种情况下加上条件的话,可以容忍所有类型的污点

驱逐 [7]

当污点设置为 NoExecute这种情况下会驱逐Pod,驱逐条件又如下几个:

  • 不容忍污点的 pod 会立即被驱逐
  • 容忍污点但未配置 tolerationSeconds 属性的会保持不变,即该节点与Pod保持绑定
  • 容忍指定污点的 pod 并且配置了tolerationSeconds 属性,节点与Pod绑定状态仅在配置的时间内。

Kubernetes内置了一些污点,此时 Controller 会自动污染节点:

  • node.kubernetes.io/not-ready: Node故障。对应 NodeCondition 的Ready = False

  • node.kubernetes.io/unreachable:Node控制器无法访问节点。对应 NodeCondition Ready= Unknown

  • node.kubernetes.io/memory-pressure:Node内存压力。

  • node.kubernetes.io/disk-pressure:Node磁盘压力。

  • node.kubernetes.io/pid-pressure:Node有PID压力。

  • node.kubernetes.io/network-unavailable:Node网络不可用。

  • node.kubernetes.io/unschedulable:Node不可调度。

Notes:Kubernetes node.kubernetes.io/not-ready 属性和 node.kubernetes.io/unreachable 属性添加容差时效 tolerationSeconds=300。即在检测到其中问题后,Pod 将保持绑定5分钟。

优先级和抢占

kubernetes中也为Pod提供了优先级的机制,有了优先级机制就可以在并行系统中提供抢占机制,有了抢占机制后,当还未调度时,高优先级Pod会比低优先级Pod先被调度,在资源不足时,低优先级Pod可以被高优先级Pod驱逐。

优先级功能由 PriorityClasses 提供。PriorityClasses 是作为集群级别资源而不是命名空间级别资源,只是用来声明优先级级别。

value 作为优先级级别,数字越大优先级级别越高。而 name 是这个优先级的名称,与其他资源name值相似,值的内容需要符合DNS域名约束。

globalDefault 是集群内默认的优先级级别,仅只有一个 PriorityClass 可以设置为 true

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

Notes:

  • 如果集群内不存在任何 PriorityClass ,则存在的Pod的优先级都为0
  • 当对集群设置了 globalDefault=true 后,不会改变已经存在的 Pod 的优先级。仅对于 PriorityClass globalDefault=true 后创建的 Pod。
  • 如果删除了 PriorityClass ,存在还是使用的这个 PriorityClass 的Pod保持不变,新创建的Pod无法使用这个 PriorityClass

非抢占

preemptionPolicy: Never 时,Pod不会抢占其他Pod,但不可调度时,会一直在调度队列中等待调度,直到满足要求才会被调度。非抢占式pod仍可能被其他高优先级的pod抢占

Notes:preemptionPolicy在Kubernetes v1.24 [stable]

preemptionPolicy 是作为非抢占的配置,默认参数为 PreemptLowerPriority;表示了允许高优先级Pod抢占低优先级Pod。如果 preemptionPolicy: Never,代表Pod是非抢占式的。

下列是一个非抢占式的配置样例

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "This priority class will not cause other pods to be preempted."

当配置了优先级后,优先级准入控制器会使用 priorityClassName 中配置的对应的 PriorityClass 的 value值来填充当前Pod的优先级,如果没有找到对应抢占策略,则拒绝。

下面是在Pod中配置优先级的示例

apiVersion: v1
kind: Pod
metadata:name: nginxlabels:env: test
spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentpriorityClassName: high-priority

抢占

当创建Pod之后,Pod会进入队列并等待被调度。scheduler 从队列中选择一个 Pod 并尝试将其调度到一个节点上。如果没有找到满足 Pod 的所有指定要求的 Node,则为 Pending 的 Pod 触发抢占。当Pod在找合适的节点时,即试图抢占一个节点,会在这个Node中删除一个或多个优先级低于当前Pod的Pod,使当前Pod能够被调度到对应的Node上。当低优先级Pod被驱逐后,当前Pod可以被调度到该Node,这个过程被称为抢占 preemption

而提供可驱逐资源的Node成为被提名Node(nominated Node ),在当Pod抢占到一个Node时,其 nominatedNodeName 会被标注为这个 Node的名称,当然标注后也不一定,一定是被抢占到这个Node之上,例如,当前Pod在等待驱逐低优先级Pod的过程中,有其他节点变成可用节点 FN 时,这个时候Pod会被抢占到这个节点。

Reference

[1] 创建一个会被调度到特定节点上的 Pod

[2] nodeSelector

[3] labels annotations taints

[4] affinity and anti-affinity

[5] inter pod affinity and anti affinity

[6] taint and toleration

[7] evictions

[8] pod priority preemption

Kubernetes调度相关推荐

  1. Kubernetes — 调度系统

    目录 文章目录 目录 调度系统 Kubernetes 调度器的设计 Kubernetes 调度器的工作流 Kubernetes 调度系统的未来 Scheduler Extender(调度器扩展) Mu ...

  2. 进击的 Kubernetes 调度系统(二):支持批任务的 Coscheduling/Gang scheduling

    作者 | 王庆璨(阿里云技术专家).张凯(阿里云高级技术专家) **导读:**阿里云容器服务团队结合多年 Kubernetes 产品与客户支持经验,对 Kube-scheduler 进行了大量优化和扩 ...

  3. 进击的 Kubernetes 调度系统(一):Kubernetes scheduling framework

    作者 | 王庆璨(阿里云技术专家).张凯(阿里云高级技术专家) 导读:阿里云容器服务团队结合多年 Kubernetes 产品与客户支持经验,对 Kube-scheduler 进行了大量优化和扩展,逐步 ...

  4. 从零开始入门 K8s | Kubernetes 调度和资源管理

    作者 | 子誉  蚂蚁金服高级技术专家 关注"阿里巴巴云原生"公众号,回复关键词**"入门"**,即可下载从零入门 K8s 系列文章 PPT. Kubernet ...

  5. 进击的Kubernetes调度系统(一):SchedulingFramework

    作者:王庆璨 张凯 前言 Kubernetes已经成为目前事实标准上的容器集群管理平台.它为容器化应用提供了自动化部署.运维.资源调度等全生命周期管理功能.经过3年多的快速发展,Kubernetes在 ...

  6. Kubernetes调度之亲和性和反亲和性

    背景 Kubernetes中的调度策略可以大致分为两种,一种是全局的调度策略,要在启动调度器时配置,包括kubernetes调度器自带的各种predicates和priorities算法:另一种是运行 ...

  7. Kubernetes 调度器实现初探

    戳蓝字"CSDN云计算"关注我们哦! 作者:阿里云智能事业群高级开发工程师 萧元 转自:阿里系统软件技术 Kubernetes作为一个分布式容器编排调度引擎,资源调度是它的最重要的 ...

  8. 【博客507】学习阿里巴巴如何扩展Kubernetes 调度器支持 AI 和大数据作业

    学习阿里巴巴如何扩展Kubernetes 调度器支持 AI 和大数据作业

  9. Kubernetes调度器-Pod分配给节点(node-pod亲和性、固定节点)

    1.需求 约束一个Pod只能在特定的 Node(s)上运行,或者优先运行在特定的节点上.有几种方法可以实现这点,推荐的方法都是用标签选择器来进行选择.通常这样的约束不是必须的,因为调度器将自动进行合理 ...

最新文章

  1. Java截取最后一个/后面的所有字符
  2. 《系统集成项目管理工程师》必背100个知识点-46质量与等级
  3. boost::lexical_cast
  4. Python稳基修炼之计算机等级考试易错概念题4(含答案与解析)
  5. 异常:操作可能会破坏运行时稳定性
  6. Python-2 eval函数
  7. [OrCad电路板设计系统].Orcad.Pspice.9.2下载安装
  8. c语言有趣代码,实用有趣的C语言程序
  9. webrtc 研究-带宽控制
  10. 奈奎斯特与香农定理_大神带你理解奈奎斯特定理和香农定理
  11. linux远程主机拒绝连接,linux – Telnet [无法连接到远程主机:拒绝连接]
  12. 目录结构及其文本编辑器
  13. 免费好用的录屏软件OBS-Studio
  14. 2020中国卓越管理公司颁奖晚宴成功举办,四家香港科大EMBA校友企业获奖
  15. Mac上Elasticsearch 安装及PHP使用
  16. java jsf_JSF----概述
  17. 计算机少了4个磁盘,电脑硬盘突然少了几个分区,这是怎么回事?如何修复?...
  18. 【热血传奇】 怪物添加(上)
  19. 穷爸爸富爸爸-读后感和笔记
  20. IGD Display Switch

热门文章

  1. JDBC链接中的问题
  2. radio点击选中,再次点击取消选中
  3. 输入两个质数的乘积,求乘数中较大的那个质数
  4. 微服务构建思路与方法论
  5. Gradle Composite builds 扩展使用
  6. LTE学习-信道估计(LS算法)
  7. python工控开发框架_GitHub - hzglitter/isf: ISF(Industrial Security Framework),基于Python的工控漏洞利用框架...
  8. 哪个服务器便宜又稳定,便宜又稳定的云服务器
  9. 神经网络压缩库Distiller学习
  10. 公众号文章留言评论功能开通方法(详解)