在 Kubernetes 中,调度是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 Pod 。

kube-scheduler 是集群控制平面的主要组件之一。Kubernetes 通过它来决定如何调度集群中的 Pod。它会使用基于预选(断言 predicate)和基于优选(优先级 priority)的评分算法,根据集群中的约束以及用户指定的约束来优化资源。

预选(过滤)

kube-scheduler 首先使用预选函数来制定调度策略,决定 Pod 可以在哪些节点上进行调度。它意味着一个硬性约束条件,因此函数的返回值为布尔值。例如,一个 Pod 请求 10GB 的内存,而节点 A 的配置为 8 GB,那么节点 A 将返回 false 并从 Pod 的候选调度节点中剔除。另一个例子是节点 B 被集群管理员执行了 kubectl cordon node-b,被标记节点为不可调度,它也将会被调度决策直接剔除。

调度程序会根据限制条件和复杂性依次进行以下预选检查,检查顺序存储在一个名为 predicatesOrdering (顺序断言)的切片中:

var predicateOrdering = []string{
CheckNodeUnschedulablePred,
GeneralPred, HostNamePred, PodFitsHostPortsPred,
MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred,
PodToleratesNodeTaintsPred, CheckNodeLabelPresencePred,
CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred,
MaxAzureDiskVolumeCountPred, MaxCinderVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred,
EvenPodsSpreadPred, MatchInterPodAffinityPred,
}
  • CheckNodeUnschedulablePred:检查节点是否可调度;
  • GeneralPred:一般性检测,如检测资源是否充足,Pod 的 Host、Port、Selector 是否匹配;
  • HostNamePred:检测 Pod 指定的 Node 名称是否和 Node 名称相同;
  • PodFitsHostPortsPred:检查 Pod 请求的端口(网络协议类型)在节点上是否可用;
  • MatchNodeSelectorPred:检测是否匹配 NodeSelector 节点选择器的设置;
  • PodFitsResourcesPred:检查节点的空闲资源(例如,CPU 和内存)是否满足 Pod 的要求;
  • NoDiskConflictPred:根据 Pod 请求的卷是否在节点上已经挂载,评估 Pod 和节点是否匹配;
  • PodToleratesNodeTaintsPred:检查 Pod 的容忍是否能容忍节点的污点;
  • CheckNodeLabelPresencePred:检测 NodeLabel 是否存在;
  • CheckServiceAffinityPred:检测服务的亲和;
  • MaxEBSVolumeCountPred:已废弃,检测 Volume 数量是否超过云服务商 AWS 的存储服务的配置限制;
  • MaxGCEPDVolumeCountPred:已废弃,检测 Volume 数量是否是否超过云服务商 Google Cloud 的存储服务的配置限制;
  • MaxCSIVolumeCountPred:Pod 附加 CSI 卷的数量,判断是否超过配置的限制;
  • MaxAzureDiskVolumeCountPred:已废弃,检测 Volume 数量是否超过云服务商 Azure 的存储服务的配置限制;
  • MaxCinderVolumeCountPred:已废弃,检测 Volume 数量是否超过云服务商 OpenStack 的存储服务的配置限制;
  • CheckVolumeBindingPred,:基于 Pod 的卷请求,评估 Pod 是否适合节点,这里的卷包括绑定的和未绑定的 PVC 都适用;
  • NoVolumeZoneConflictPred:给定该存储的故障区域限制, 评估 Pod 请求的卷在节点上是否可用;
  • EvenPodsSpreadPred:检测 Node 是否满足拓扑传播限制;
  • MatchInterPodAffinityPred:检测是否匹配 Pod 的亲和与反亲和的设置;

可以看出,Kubernetes 正在逐步移除某个具体云服务商的服务的相关代码,而使用接口(Interface)来扩展功能。

优选(打分)

预选通过返回 true 或者 false 来表示节点是否参与调度,而优选则是根据优先级的相对值对所有可调度节点进行排名,以下是为节点评分的优先级列表:

  • EqualPriority:给予所有节点相等的权重;
  • MostRequestedPriority:支持最多请求资源的节点。 该策略将 Pod 调度到整体工作负载所需的最少的一组节点上;
  • RequestedToCapacityRatioPriority:使用默认的打分方法模型,创建基于 ResourceAllocationPriority 的 requestedToCapacity;
  • SelectorSpreadPriority:属于同一 Service、 StatefulSet 或 ReplicaSet 的 Pod,尽可能地跨 Node 部署(鸡蛋不要只放在一个篮子里,分散风险,提高可用性);
  • ServiceSpreadingPriority:对于给定的 Service,此策略旨在确保该 Service 关联的 Pod 在不同的节点上运行。 它偏向把 Pod 调度到没有该服务的节点。 整体来看,Service 对于单个节点故障变得更具弹性;
  • InterPodAffinityPriority:实现了 Pod 间亲和性与反亲和性的优先级;
  • LeastRequestedPriority:偏向最少请求资源的节点。 换句话说,节点上的 Pod 越多,使用的资源就越多,此策略给出的排名就越低;
  • BalancedResourceAllocation:偏向平衡资源使用的节点;
  • NodePreferAvoidPodsPriority:根据节点的注解 scheduler.alpha.kubernetes.io/preferAvoidPods 对节点进行优先级排序。 你可以使用它来暗示两个不同的 Pod 不应在同一节点上运行;
  • NodeAffinityPriority:根据节点亲和中 PreferredDuringSchedulingIgnoredDuringExecution 字段对节点进行优先级排序;
  • TaintTolerationPriority:根据节点上无法忍受的污点数量,给所有节点进行优先级排序。 此策略会根据排序结果调整节点的等级;
  • ImageLocalityPriority:偏向已在本地缓存 Pod 所需容器镜像的节点;
  • EvenPodsSpreadPriority:实现了 Pod 拓扑扩展约束的优先级排序;

这些分值将会累计为节点的总分,用来表明其优先级。例如,如果一个 Pod 需要 1 个 cpu 核心的资源,而有两个候选节点满足这一要求,其中节点 A 有 2 个 CPU 核心可供分配,节点 B 有 4 个核心可供分配,则节点 B 将具有更高的优先级。 如果多个节点返回相同的优先级,调度程序将会使用轮循的方式来选择节点。

最优解

kube-scheduler 使用基于预选和基于优选的评分算法,理论上需要遍历所有 Node(实际上有缓存逻辑),而当集群中的 Node 数量超过一定数量后,调度算法的开销将变得很大。所以 kube-scheduler 为了解决性能问题,引入了"全局最优解"和"局部最优解"两种最优解。

  • 全局最优解:遍历集群中的所有节点,找出全局最优的节点;
  • 局部最优解:只遍历集群中的部分节点,找出局部最有的节点;

在小型集群中(例如 100 个节点),使用全局最优解。而在超大型集群中(例如 5000 个节点)使用局部最优解。

抢占机制

Pod 可以设置优先级(PriorityClass,注意:此处的 Pod 优先级与优选算法的优先级评分不是一个概念)。 Pod 优先级表示一个 Pod 相对于其他 Pod 的重要性。 如果一个 Pod 无法被调度,调度程序会尝试抢占(驱逐)较低优先级的 Pod。

要使用优先级和抢占,需要:

  1. 新增 PriorityClass 对象,并设置 value 值;
  2. 将 Pod 的 Spec.priorityClassName 设置为上述新增的 PriorityClass;

上述设置了高优先级的 Pod(暂称为 pod-h) ,如果 kube-scheduler 没有找到满足其指定要求的节点,则触发抢占逻辑。抢占逻辑试图找到某个节点,在该节点中删除/驱逐一个或多个优先级低于 pod-h 的 Pod。被驱逐的 Pod 消失后,pod-h 可以被调度到该节点上。

更多

更多经典示例请参考:https://github.com/jxlwqq/kubernetes-examples

当一个 Pod 被调度时,Kubernetes 内部发生了什么?的更多相关文章

  1. 当你创建了一个 Deployment 时,Kubernetes 内部发生了什么?

    我们通常使用 kubectl 来管理我们的 Kubernetes 集群. 当我们需要一个 Nginx 服务时,可以使用以下命令来创建: kubectl create deployment nginx ...

  2. 使用ArrayList时代码内部发生了什么(jdk1.7)?

    前言 ArrayList(这里的ArrayList是基于jdk1.7)是在项目中经常使用的集合类,例如我们从数据库中查询出一组数据.这篇文章不去剖析它的继承和实现,只是让我们知道实例化及增删改查时它的 ...

  3. kubernetes (k8s) CKA认证之第二课:亲和性与 Pod 的调度

    手动调度一个 pod // cat manual-schedule.yaml apiVersion: v1 kind: Pod metadata: labels: run: pod-manual-sc ...

  4. Docker(二):理解容器编排工具Kubernetes内部工作原理

    一.Kubernetes是什么 要说到Docker就不得不说说Kubernetes.当Docker容器在微服务的环境下数量一多,那么统一的,自动化的管理自然少不了.而Kubernetes就是一个这样的 ...

  5. k8s pod节点调度及k8s资源优化

    一.k8s pod 在节点间调度控制 k8s起pod时,会通过调度器scheduler选择某个节点完成调度,选择在某个节点上完成pod创建.当需要在指定pod运行在某个节点上时,可以通过以下几种方式: ...

  6. kubenetes创建一个pod应用

    Pod是可以创建和管理Kubernetes计算的最小可部署单元.一个Pod代表着集群中运行的一个进程.每个pod都有一个唯一的ip. 一个pod类似一个豌豆荚,包含一个或多个容器(通常是docker) ...

  7. pod(八):pod的调度——将 Pod 指派给节点

    目录 一.系统环境 二.前言 三.pod的调度 3.1 pod的调度概述 3.2 pod自动调度 3.2.1 创建3个主机端口为80的pod 3.3 使用nodeName 字段指定pod运行在哪个节点 ...

  8. 【云计算】K8S DaemonSet 每个node上都运行一个pod

    Kubernetes容器集群中的日志系统集成实践 Kubernetes是原生的容器编排管理系统,对于负载均衡.服务发现.高可用.滚动升级.自动伸缩等容器云平台的功能要求有原生支持.今天我分享一下我们在 ...

  9. [k8s]zookeeper集群在k8s的搭建(statefulset模式)-pod的调度

    之前一直docker-compose跑zk集群,现在把它挪到k8s集群里. docker-compose跑zk集群 zk集群in k8s部署 参考: https://github.com/kubern ...

随机推荐

  1. Mysql 修改本地密码

    第一步 update user set authentication_string=password('root') where user='root' and host='localhost'; 第 ...

  2. Mooc中国大学Python学习笔记--数字类型及操作

    整数类型 只需知道整数无限制,pow(),4进制表示形式 与数学中整数的概念一致 --可正可负,没有取值范限制 --pow(x,y)函数:计算x^y,想算多大算多大 -十进制:10 -二进制,以0b或 ...

  3. 关于对String中intern方法的理解

    在java的String中有个一直被我们忽视了的方法intern方法:它的官方解释是:一个初始时为空的字符串池,它由类 String 私有地维护. 当调用 intern 方法时,如果池已经包含一个等于 ...

  4. Blazor WebAssembly 应用程序中进行 HTTP 请求

    翻译自 Waqas Anwar 2021年5月13日的文章 <Making HTTP Requests in Blazor WebAssembly Apps> [1] 在我的前篇文章< ...

  5. Python3-sqlalchemy-orm 分组统计

    #-*-coding:utf-8-*- #__author__ = "logan.xu" import sqlalchemy from sqlalchemy import crea ...

  6. Qt之文件操作

    虽然文件操作是一项很常用的功能,但是总记不住,今天就干脆记了一下笔记,以后好查阅. 在Qt中,主要使用的是QFile类进行文件操作,因此要包括#include <QFile>头文件.下面就 ...

  7. Python - 面向对象编程 - 小实战(1)

    题目 设计一个类Person,生成若干实例,在终端输出如下信息 小明,10岁,男,上山去砍柴 小明,10岁,男,开车去东北 小明,10岁,男,最爱大保健 老李,90岁,男,上山去砍柴 老李,90岁,男 ...

  8. 浅谈KMP模式匹配算法

    普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...

  9. Eclipse中快速生成Javabean的方法

    总结一下: 先写出属性 无参构造器:Alt+/ 再按回车 全参构造器:Alt+Shift+S 再按字母O键 再按回车 toString方法:Alt+Shift+S 再按字母S键 再按回车 get/se ...

  10. 引人遐想,用 Python 获取你想要的 “某个人” 摄像头照片

    仅用来学习,希望给你们有提供到学习上的作用. 1.安装库 需要安装python3.5以上版本,在官网下载即可.然后安装库opencv-python,安装方式为打开终端输入命令行. 2.更改收件人和发件 ...