Kubernetes 调度器详解

news2024/10/5 13:08:25

kube-scheduler是 kubernetes 系统的核心组件之一,主要负责整个集群资源的调度功能,根据特定的调度算法和策略,将 Pod 调度到最优的工作节点上面去,从而更加合理、更加充分的利用集群的资源,这也是我们选择使用 kubernetes 一个非常重要的理由。如果一门新的技术不能帮助企业节约成本、提供效率,我相信是很难推进的。

调度流程

默认情况下,kube-scheduler 提供的默认调度器能够满足我们绝大多数的要求,我们前面和大家接触的示例也基本上用的默认的策略,都可以保证我们的 Pod 可以被分配到资源充足的节点上运行。但是在实际的线上项目中,可能我们自己会比 kubernetes 更加了解我们自己的应用,比如我们希望一个 Pod 只能运行在特定的几个节点上,或者这几个节点只能用来运行特定类型的应用,这就需要我们的调度器能够可控。

kube-scheduler 是 kubernetes 的调度器,它的主要作用就是根据特定的调度算法和调度策略将 Pod 调度到合适的 Node 节点上去,是一个独立的二进制程序,启动之后会一直监听 API Server,获取到 PodSpec.NodeName 为空的 Pod,对每个 Pod 都会创建一个 binding。

这个过程在我们看来好像比较简单,但在实际的生产环境中,需要考虑的问题就有很多了:

  • 如何保证全部的节点调度的公平性?要知道并不是说有节点资源配置都是一样的
  • 如何保证每个节点都能被分配资源?
  • 集群资源如何能够被高效利用?
  • 集群资源如何才能被最大化使用?
  • 如何保证 Pod 调度的性能和效率?
  • 用户是否可以根据自己的实际需求定制自己的调度策略?

考虑到实际环境中的各种复杂情况,kubernetes 的调度器采用插件化的形式实现,可以方便用户进行定制或者二次开发,我们可以自定义一个调度器并以插件形式和 kubernetes 进行集成。

kubernetes 调度器的源码位于 kubernetes/pkg/scheduler 中,大体的代码目录结构如下所示:(不同的版本目录结构可能不太一样)

kubernetes/pkg/scheduler
-- scheduler.go         //调度相关的具体实现
|-- algorithm
|   |-- predicates      //节点筛选策略
|   |-- priorities      //节点打分策略
|-- algorithmprovider
|   |-- defaults         //定义默认的调度器

其中 Scheduler 创建和运行的核心程序,对应的代码在 pkg/scheduler/scheduler.go,如果要查看kube-scheduler的入口程序,对应的代码在 cmd/kube-scheduler/scheduler.go。

调度主要分为以下几个部分:

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

Predicates阶段首先遍历全部节点,过滤掉不满足条件的节点,属于强制性规则,这一阶段输出的所有满足要求的 Node 将被记录并作为第二阶段的输入,如果所有的节点都不满足条件,那么 Pod 将会一直处于 Pending 状态,直到有节点满足条件,在这期间调度器会不断的重试。

所以我们在部署应用的时候,如果发现有 Pod 一直处于 Pending 状态,那么就是没有满足调度条件的节点,这个时候可以去检查下节点资源是否可用。

Priorities阶段即再次对节点进行筛选,如果有多个节点都满足条件的话,那么系统会按照节点的优先级(priorites)大小对节点进行排序,最后选择优先级最高的节点来部署 Pod 应用。

下面是调度过程的简单示意图:

kube-scheduler filter

更详细的流程是这样的:

  • 首先,客户端通过 API Server 的 REST API 或者 kubectl 工具创建 Pod 资源
  • API Server 收到用户请求后,存储相关数据到 etcd 数据库中
  • 调度器监听 API Server 查看为调度(bind)的 Pod 列表,循环遍历地为每个 Pod 尝试分配节点,这个分配过程就是我们上面提到的两个阶段:
    • 预选阶段(Predicates),过滤节点,调度器用一组规则过滤掉不符合要求的 Node 节点,比如 Pod 设置了资源的 request,那么可用资源比 Pod 需要的资源少的主机显然就会被过滤掉
    • 优选阶段(Priorities),为节点的优先级打分,将上一阶段过滤出来的 Node 列表进行打分,调度器会考虑一些整体的优化策略,比如把 Deployment 控制的多个 Pod 副本分布到不同的主机上,使用最低负载的主机等等策略
  • 经过上面的阶段过滤后选择打分最高的 Node 节点和 Pod 进行 binding 操作,然后将结果存储到 etcd 中
  • 最后被选择出来的 Node 节点对应的 kubelet 去执行创建 Pod 的相关操作

其中Predicates过滤有一系列的算法可以使用,我们这里简单列举几个:

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

除了这些过滤算法之外,还有一些其他的算法,更多更详细的我们可以查看源码文件:k8s.io/kubernetes/pkg/scheduler/algorithm/predicates/predicates.go。

Priorities优先级是由一系列键值对组成的,键是该优先级的名称,值是它的权重值,同样,我们这里给大家列举几个具有代表性的选项:

  • LeastRequestedPriority:通过计算 CPU 和内存的使用率来决定权重,使用率越低权重越高,当然正常肯定也是资源是使用率越低权重越高,能给别的 Pod 运行的可能性就越大
  • SelectorSpreadPriority:为了更好的高可用,对同属于一个 Deployment 或者 RC 下面的多个 Pod 副本,尽量调度到多个不同的节点上,当一个 Pod 被调度的时候,会先去查找该 Pod 对应的 controller,然后查看该 controller 下面的已存在的 Pod,运行 Pod 越少的节点权重越高
  • ImageLocalityPriority:就是如果在某个节点上已经有要使用的镜像节点了,镜像总大小值越大,权重就越高
  • NodeAffinityPriority:这个就是根据节点的亲和性来计算一个权重值,后面我们会详细讲解亲和性的使用方法

除了这些策略之外,还有很多其他的策略,同样我们可以查看源码文件:k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/ 了解更多信息。每一个优先级函数会返回一个0-10的分数,分数越高表示节点越优,同时每一个函数也会对应一个表示权重的值。最终主机的得分用以下公式计算得出:

finalScoreNode = (weight1 * priorityFunc1) + (weight2 * priorityFunc2) + … + (weightn * priorityFuncn)

自定义调度

上面就是 kube-scheduler 默认调度的基本流程,除了使用默认的调度器之外,我们也可以自定义调度策略。

调度器扩展

kube-scheduler在启动的时候可以通过 --policy-config-file参数来指定调度策略文件,我们可以根据我们自己的需要来组装PredicatesPriority函数。选择不同的过滤函数和优先级函数、控制优先级函数的权重、调整过滤函数的顺序都会影响调度过程。

下面是官方的 Policy 文件示例:

{
  "kind" : "Policy",
  "apiVersion" : "v1",
  "predicates" : [
      {"name" : "PodFitsHostPorts"},
      {"name" : "PodFitsResources"},
      {"name" : "NoDiskConflict"},
      {"name" : "NoVolumeZoneConflict"},
      {"name" : "MatchNodeSelector"},
      {"name" : "HostName"}
  ],
  "priorities" : [
      {"name" : "LeastRequestedPriority", "weight" : 1},
      {"name" : "BalancedResourceAllocation", "weight" : 1},
      {"name" : "ServiceSpreadingPriority", "weight" : 1},
      {"name" : "EqualPriority", "weight" : 1}
  ]
}

多调度器

如果默认的调度器不满足要求,还可以部署自定义的调度器。并且,在整个集群中还可以同时运行多个调度器实例,通过 podSpec.schedulerName 来选择使用哪一个调度器(默认使用内置的调度器)。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  schedulerName: my-scheduler  # 选择使用自定义调度器 my-scheduler
  containers:
  - name: nginx
    image: nginx:1.10

要开发我们自己的调度器也是比较容易的,比如我们这里的 my-scheduler:

  • 首先需要通过指定的 API 获取节点和 Pod
  • 然后选择phase=PendingschedulerName=my-scheduler的pod
  • 计算每个 Pod 需要放置的位置之后,调度程序将创建一个Binding对象
  • 然后根据我们自定义的调度器的算法计算出最适合的目标节点

优先级调度

与前面所讲的调度优选策略中的优先级(Priorities)不同,前面所讲的优先级指的是节点优先级,而我们这里所说的优先级 pod priority 指的是 Pod 的优先级,高优先级的 Pod 会优先被调度,或者在资源不足低情况牺牲低优先级的 Pod,以便于重要的 Pod 能够得到资源部署。

要定义 Pod 优先级,就需要先定义PriorityClass对象,该对象没有 Namespace 的限制:

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

其中:

  • value为 32 位整数的优先级,该值越大,优先级越高
  • globalDefault用于未配置 PriorityClassName 的 Pod,整个集群中应该只有一个PriorityClass将其设置为 true

然后通过在 Pod 的spec.priorityClassName中指定已定义的PriorityClass名称即可:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

另外一个值得注意的是当节点没有足够的资源供调度器调度 Pod,导致 Pod 处于 pending 时,抢占(preemption)逻辑就会被触发。Preemption会尝试从一个节点删除低优先级的 Pod,从而释放资源使高优先级的 Pod 得到节点资源进行部署。

现在我们通过下面的图再去回顾下 kubernetes 的调度过程是不是就清晰很多了:

kube-scheduler

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/74128.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

构建高性能内存队列:Disruptor yyds~

Java中有哪些队列 ArrayBlockingQueue 使用ReentrantLockLinkedBlockingQueue 使用ReentrantLockConcurrentLinkedQueue 使用CAS等等 我们清楚使用锁的性能比较低,尽量使用无锁设计。接下来就我们来认识下Disruptor。 Disruptor简单使用 github地址:P…

R语言建立和可视化混合效应模型mixed effect model

全文下载链接:http://tecdat.cn/?p20631我们已经学习了如何处理混合效应模型。本文的重点是如何建立和_可视化_ 混合效应模型的结果(点击文末“阅读原文”获取完整代码数据)。相关视频设置本文使用数据集,用于探索草食动物种群对…

Linux Capabilities

Linux Capabilities 入门教程:基础实战篇 为了对 root 权限进行更细粒度的控制,实现按需授权,Linux 引入了另一种机制叫capabilities。Capabilites 作为线程(Linux 并不真正区分进程和线程)的属性存在,每个…

极客时间Kafka - 06 Kafka 消费者组 Consumer Group 到底是什么?

文章目录1. 消费者组到底是什么?2. Consumer Group下的Consumer实例个数3. 消费者位移Offset4. 重平衡1. 消费者组到底是什么? 消费者组,即 Consumer Group,应该算是 Kafka 比较有亮点的设计了。那么何谓 Consumer Group 呢&…

JAVA SCRIPT设计模式--行为型--设计模式之State状态者模式(20)

JAVA SCRIPT设计模式是本人根据GOF的设计模式写的博客记录。使用JAVA SCRIPT语言来实现主体功能,所以不可能像C,JAVA等面向对象语言一样严谨,大部分程序都附上了JAVA SCRIPT代码,代码只是实现了设计模式的主体功能,不代…

ToDesk企业版使用测试:破解企业远程办公难题,更安全更高效

❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主&#x1f3…

Phoenix安装部署

目录官网地址Phoenix 部署连接二次连接,连接失败解决官网地址 link Phoenix 部署 上传并解压 tar 包 更名 复制 server 包并拷贝到各个节点的 hbase/lib 配置环境变量 sudo vim /etc/profile.d/my_env.sh#phoenix export PHOENIX_HOME/opt/module/phoenix e…

抗病毒面料之外,安奈儿价值内核彰显

伴随着防控措施的不断优化,消费板块重回资本视野,其中童装巨头安奈儿因将推出“抗病毒抗菌面料”备受关注,14天收获10个涨停板。 目前安奈儿凭借抗病毒面料吸引了无数资本的目光,但这也是一把双刃剑。虽然抗病毒面料为安奈儿带来了…

数字化棋牌室 | 会员管理预约系统 | 棋牌室小程序

棋牌室在城市与农村都是部分老年人与年轻人的经常去的娱乐场所,以前这些场所里总是挤满了人,但现在越来越多的棋牌室即使环境装修的漂亮、设备高端完善等依然面对流量难题及管理难题,同时由于棋牌室具有社区属性,因此也有不少商家…

ARM微控制器MK24FN1M0VDC12、MKV10Z128VLH7低功耗MCU资料

MK24FN1M0VDC12 IC MCU 32BIT 1MB FLASH 121XFBGA 说明:Kinetis K2x 32位微控制器是低功耗mcu,通过智能片上集成大大节省了BOM。这些mcu基于ArmCortex-M4核心,提供完整和可选的高速USB 2.0 on - on - go (OTG),包括无晶体设备功能…

干货 | 数字经济创新创业——数据是数字经济的基础

下文整理自清华大学大数据能力提升项目能力提升模块课程“Innovation & Entrepreneurship for Digital Economy”(数字经济创新创业课程)的精彩内容。主讲嘉宾:Kris Singh: CEO at SRII, Palo Alto, CaliforniaVisiting Professor of Tsinghua Unive…

RTSP 协议漫谈,揭秘 RTSP 协议内幕

RTSP(Real Time Streaming Protocol)实时流传输协议,定义在 RFC2326,是 TCP/IP 协议体系中的一个应用层协议,由哥伦比亚大学、网景和 RealNetworks 公司提交的 IETF RFC 标准。该协议定义了一对多应用程序如何有效地通…

Linux用户管理详解

Linux用户管理详解 前言 Linux用户即Linux的使用者,是指使用Linux系统或服务的人员,通常用户对应拥有一个用户账号,并对用户名识别。正常登录Linux系统,本质是登录系统,但是Linux支持同一时间多个用户同时登陆&#x…

JSP ssh服装定制电子商务系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh服装定制电子商务系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采 用B/S模式开发。开发环境为TOMCA…

大一学生《Web编程基础》期末网页制作 HTML+CSS+JavaScript 网页设计实例 企业网站制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 ⚽精彩专栏推荐&#x1…

【Docker】第 1 章 Docker概述

1.1 Docker是什么 使用最广泛的开源容器引擎一种操作系统级的虚拟化技术依赖于Linux内核特性:Namespace(资源隔离)和Cgroups(资源限制) 一个简单的应用程序打包工具 1.2 Docker设计目标 提供简单的应用程序打包工具开…

传奇架设需要准备以下条件

传奇架设其实很简单 很多网友非常爱玩这款游戏,可能还有朋友不知道怎么架设这款游戏 今天特意写篇传奇架设教程,希望大家都能打造出真正属于自己的传奇 首先传奇架设需要准备以下几个软件 准备工具: 1、传奇服务端(版本&#…

select组件切换tags时,联动的select组件内容清空

前言 记录在项目开发中遇到问题的解决方案,方便以后遇到快速解决! 问题描述 在该react hooks 页面中,图纸计划附件表格是一个子组件。其中 【单体】和【专业】两个下拉select选择框,数据来源依赖于【厂区】。 后端给的接口&#…

9微电网两阶段鲁棒优化经济调度方法(MATLAB程序)

联系2645521500 复现文章: 微电网两阶段鲁棒优化经济调度方法——刘一欣(中国电机工程学报) 主要内容: 针对微电网内可再生能源和负荷的不确定性,建立了min-max-min 结构的两阶段鲁棒优化模型,可得到最…

SpringCloud微服务网关gateway

SpringCloud微服务网关gateway 网关简介 大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢? 如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去用…