Kubernetes 是如何调度的?

作者 | 阿文,责编 | 郭芮

头图 | CSDN 下载自东方IC

出品 | CSDN(ID:CSDNnews)

自互联网出现以来 ,云计算的概念已经提出了有 50 年。从1957 年,John McCarthy 将计算机中的分时共享概念设计成了一种工具。从此以后,这个概念的名字经历过数次变化:从“服务中心(service bureau)”到应用服务提供商,到互联网即服务,到云计算,再到软件定义的数据中心。

一直以来基础设施是云计算的基础核心,基础设施服务(Infrastructure as a Service,IaaS)将IT基础设施资源(计算、网络与存储)以一种弹性的服务方式对外提供。近十余年来随着云计算不断发展与落地,云基础设施技术架构也在不断往前演进,从传统虚拟化、基础设施资源管理走向软件定义架构。随着近5年来以容器和微服务为代表的云原生技术兴起,云基础设施架构需要演进以全面拥抱云原生技术。

以容器、容器编排、微服务、服务网格为代表的云原生技术正在日益体现出期在云计算领域的非凡价值,众所周知,容器编排中 Kubernetes 已经成为容器编排领域的事实标准。

kubernetes 可以提供所需的编排和管理功能,以便针对工作负载大规模部署容器。借助 Kubernetes 编排功能,可以快速的构建跨多个容器的应用服务、跨集群调度、扩展这些容器,并长期持续管理这些容器的健康状况。在 Kubernetes 中,调度 是指将 Pod 放置到合适的 Node上,然后对应 Node 上的 Kubelet才能够运行这些 pod。

那么kubernetes 是如何进行调度的呢?我们来一起看下。

Kubernetes  是如何调度的?

kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群 控制面的一部分。同时 kube-scheduler 在设计上是允许你自己写一个调度组件并替换原有的 kube-scheduler。

对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会选择一个最优的 Node 去运行这个 Pod。那么kube-scheduler 是如何选择最优的 Node 呢?

kube-scheduler监听apiserver的/api/pod/,当发现集群中有未得到调度的pod(即PodSpec.NodeName为空)时,会查询集群各node的信息,经过Predicates(过滤)、Priorities(优选器),得到最适合该pod运行的node后,再向apiserver发送请求,将该容器绑定到选中的node上。

Kubernetes Scheduler 提供的调度流程分三步:

  • 过滤, 遍历nodelist,选择出符合要求的候选节点,Kubernetes内置了多种预选规则供用户选择。

  • 打分, 在选择出符合要求的候选节点中,采用优选规则计算出每个节点的积分,最后选择得分最高的。

  • 绑定,  选出其中得分最高的 Node 来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做绑定。

整个过程,如图所示:

预选的算法可以参考源码predicates.go(https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/algorithm/predicates/predicates.go):

const (// MatchInterPodAffinityPred defines the name of predicate MatchInterPodAffinity.MatchInterPodAffinityPred = "MatchInterPodAffinity"// CheckVolumeBindingPred defines the name of predicate CheckVolumeBinding.CheckVolumeBindingPred = "CheckVolumeBinding"// GeneralPred defines the name of predicate GeneralPredicates.GeneralPred = "GeneralPredicates"// HostNamePred defines the name of predicate HostName.HostNamePred = "HostName"// PodFitsHostPortsPred defines the name of predicate PodFitsHostPorts.PodFitsHostPortsPred = "PodFitsHostPorts"// MatchNodeSelectorPred defines the name of predicate MatchNodeSelector.MatchNodeSelectorPred = "MatchNodeSelector"// PodFitsResourcesPred defines the name of predicate PodFitsResources.PodFitsResourcesPred = "PodFitsResources"// NoDiskConflictPred defines the name of predicate NoDiskConflict.NoDiskConflictPred = "NoDiskConflict"// PodToleratesNodeTaintsPred defines the name of predicate PodToleratesNodeTaints.PodToleratesNodeTaintsPred = "PodToleratesNodeTaints"// CheckNodeUnschedulablePred defines the name of predicate CheckNodeUnschedulablePredicate.CheckNodeUnschedulablePred = "CheckNodeUnschedulable"// CheckNodeLabelPresencePred defines the name of predicate CheckNodeLabelPresence.CheckNodeLabelPresencePred = "CheckNodeLabelPresence"// CheckServiceAffinityPred defines the name of predicate checkServiceAffinity.CheckServiceAffinityPred = "CheckServiceAffinity"// MaxEBSVolumeCountPred defines the name of predicate MaxEBSVolumeCount.// DEPRECATED// All cloudprovider specific predicates are deprecated in favour of MaxCSIVolumeCountPred.MaxEBSVolumeCountPred = "MaxEBSVolumeCount"// MaxGCEPDVolumeCountPred defines the name of predicate MaxGCEPDVolumeCount.// DEPRECATED// All cloudprovider specific predicates are deprecated in favour of MaxCSIVolumeCountPred.MaxGCEPDVolumeCountPred = "MaxGCEPDVolumeCount"// MaxAzureDiskVolumeCountPred defines the name of predicate MaxAzureDiskVolumeCount.// DEPRECATED// All cloudprovider specific predicates are deprecated in favour of MaxCSIVolumeCountPred.MaxAzureDiskVolumeCountPred = "MaxAzureDiskVolumeCount"// MaxCinderVolumeCountPred defines the name of predicate MaxCinderDiskVolumeCount.// DEPRECATED// All cloudprovider specific predicates are deprecated in favour of MaxCSIVolumeCountPred.MaxCinderVolumeCountPred = "MaxCinderVolumeCount"// MaxCSIVolumeCountPred defines the predicate that decides how many CSI volumes should be attached.MaxCSIVolumeCountPred = "MaxCSIVolumeCountPred"// NoVolumeZoneConflictPred defines the name of predicate NoVolumeZoneConflict.NoVolumeZoneConflictPred = "NoVolumeZoneConflict"// EvenPodsSpreadPred defines the name of predicate EvenPodsSpread.EvenPodsSpreadPred = "EvenPodsSpread"
)

常用的预选策略:

  • PodFitsHostPorts:如果 Pod 中定义了 hostPort 属性,那么需要先检查这个指定端口是否 已经被 Node 上其他服务占用了。

  • PodFitsHost:若 pod 对象拥有 hostname 属性,则检查 Node 名称字符串与此属性是否匹配。

  • PodFitsResources:检查 Node 上是否有足够的资源(如,cpu 和内存)来满足 pod 的资源请求。

  • PodMatchNodeSelector:检查 Node 的 标签 是否能匹配 Pod 属性上 Node 的 标签 值。

  • NoVolumeZoneConflict:检测 pod 请求的 Volumes 在 Node 上是否可用,因为某些存储卷存在区域调度约束。

  • NoDiskConflict:检查 Pod 对象请求的存储卷在 Node 上是否可用,若不存在冲突则通过检查。

  • MaxCSIVolumeCount:检查 Node 上已经挂载的 CSI 存储卷数量是否超过了指定的最大值。

  • CheckNodeMemoryPressure:如果 Node 上报了内存资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。

  • CheckNodePIDPressure:如果 Node 上报了 PID 资源压力过大,而且没有配置异常,那么 Pod 将不会被调度到这个 Node 上。

  • CheckNodeDiskPressure:如果 Node 上报了磁盘资源压力过大(文件系统满了或者将近满了), 而且配置异常,那么 Pod 将不会被调度到这个 Node 上。

  • CheckNodeCondition:Node 可以上报其自身的状态,如磁盘、网络不可用,表明 kubelet 未准备好运行 pod。如果 Node 被设置成这种状态,那么 pod 将不会被调度到这个 Node 上。

  • PodToleratesNodeTaints:检查 pod 属性上的 tolerations 能否容忍 Node 的 taints。

  • CheckVolumeBinding:检查 Node 上已经绑定的和未绑定的 PVCs 能否满足 Pod 对象的存储卷需求。

打分策略如下:

  • SelectorSpreadPriority:尽量将归属于同一个 Service、StatefulSet 或 ReplicaSet 的 Pod 资源分散到不同的 Node 上。

  • InterPodAffinityPriority:遍历 Pod 对象的亲和性条目,并将那些能够匹配到给定 Node 的条目的权重相加,结果值越大的 Node 得分越高。

  • LeastRequestedPriority:空闲资源比例越高的 Node 得分越高。换句话说,Node 上的 Pod 越多,并且资源被占用的越多,那么这个 Node 的得分就会越少。

  • MostRequestedPriority:空闲资源比例越低的 Node 得分越高。这个调度策略将会把你所有的工作负载(Pod)调度到尽量少的 Node 上。

  • RequestedToCapacityRatioPriority:为 Node 上每个资源占用比例设定得分值,给资源打分函数在打分时使用。

  • BalancedResourceAllocation:优选那些使得资源利用率更为均衡的节点。

  • NodePreferAvoidPodsPriority:这个策略将根据 Node 的注解信息中是否含有 scheduler.alpha.kubernetes.io/preferAvoidPods 来 计算其优先级。使用这个策略可以将两个不同 Pod 运行在不同的 Node 上。

  • NodeAffinityPriority:基于 Pod 属性中 PreferredDuringSchedulingIgnoredDuringExecution 来进行 Node 亲和性调度。你可以通过这篇文章 Pods 到 Nodes 的分派 来了解到更详细的内容。

  • TaintTolerationPriority:基于 Pod 中对每个 Node 上污点容忍程度进行优先级评估,这个策略能够调整待选 Node 的排名。

  • ImageLocalityPriority:Node 上已经拥有 Pod 需要的 容器镜像 的 Node 会有较高的优先级。

  • ServiceSpreadingPriority:这个调度策略的主要目的是确保将归属于同一个 Service 的 Pod 调度到不同的 Node 上。如果 Node 上 没有归属于同一个 Service 的 Pod,这个策略更倾向于将 Pod 调度到这类 Node 上。最终的目的:即使在一个 Node 宕机之后 Service 也具有很强容灾能力。

  • CalculateAntiAffinityPriorityMap:这个策略主要是用来实现pod反亲和。

  • EqualPriorityMap:将所有的 Node 设置成相同的权重为 1。

自定义调度器

除了 kubernetes 自带的调度器,考虑到实际环境中的各种复杂情况,kubernetes 的调度器采用插件化的形式实现,可以方便用户进行定制或者二次开发,我们可以自定义一个调度器并以插件形式和 kubernetes 进行集成。你也可以编写自己的调度器。通过 spec:schedulername 参数指定调度器的名字,可以为 pod 选择某个调度器进行调度。

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

比如下面的 pod 选择 test-my-scheduler 进行调度,而不是默认的 default-scheduler:

apiVersion: v1
kind: Pod
metadata:name: test-schedulerlabels:name: testscheduler-example
spec:schedulername: test-my-schedulercontainers:- name: pod-with-second-annotation-containerimage: gcr.io/google_containers/pause:2.0

调度器的编写请参考 kubernetes 默认调度器的实现,最核心的内容就是读取 apiserver 中 pod 的值,根据特定的算法找到合适的 node,然后把调度结果会写到 apiserver。

官方给出的范例:

#!/bin/bash
SERVER='localhost:8001'
while true;
dofor PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | select(.spec.schedulerName == "my-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"')
;doNODES=($(kubectl --server $SERVER get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))NUMNODES=${#NODES[@]}CHOSEN=${NODES[$[ $RANDOM % $NUMNODES ]]}curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding", "metadata": {"name": "'$PODNAME'"}, "target": {"apiVersion": "v1", "kind"
: "Node", "name": "'$CHOSEN'"}}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/echo "Assigned $PODNAME to $CHOSEN"donesleep 1
done

推荐阅读
  • 实操来了!一文告诉你如何用 Streamlit 和 Heroku 开发 Web

  • 避坑!使用 Kubernetes 最易犯的 10 个错误

  • 雷军:4G 手机已清仓,全力转 5G;QQ音乐播放中途插语音广告引热议;Wine 5.9 发布 | 极客头条

  • 15 岁黑进系统,发挑衅邮件意外获 Offer,不惑之年捐出全部财产,Twitter CEO 太牛了!

  • 必读!53个Python经典面试题详解

  • 赠书 | 1月以来 Tether 增发47亿 USDT,美元都去哪儿了?

真香,朕在看了!

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

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

相关文章

# Schedulerx正式登陆Ali-k8s应用目录

简介 分布式任务调度 SchedulerX 是阿里巴巴基于 Akka 架构自研的的分布式任务调度平台,今天正式登陆阿里云容器服务Kubernetes应用目录,支持用户以云原生的方式获取定时、工作流任务编排、分布式批量调度等功能,同时具有高可靠、海量任务、…

刚刚,阿里巴巴小程序生态联盟重磅启动

9月27日下午,阿里巴巴小程序繁星计划峰会作为杭州云栖大会的压轴好戏,在云栖小镇国际会展中心迎来千余位商家、合作伙伴、个人开发者和行业专家。峰会以“小程序、大生态”为题,发布了阿里巴巴小程序繁星计划补贴的更多细节方案,并…

因为一个跨域请求,我差点丢了饭碗

来源 | 编程技术宇宙责编 | 王晓曼封图 | CSDN下载自视觉中国浏览器基本原理我叫小风,是Windows帝国一个普通的上班族。今天,我入职了一家浏览器公司,公司的主营业务是为人类提供Internet上网服务,我的岗位是负责执行JavaScript代…

MongoDB BI Connector 实战指南

MongoDB 使用 BI Connector 来支持 BI 组件直接使用 SQL 或 ODBC 数据源方式直接访问 MongoDB,在早期 MongoDB 直接使用 Postgresql FDW 来实现 SQL 到 MQL 的转换,后来实现更加轻量级的 mongosqld 来支持 BI 工具的连接。 安装 BI Connector 参考 Inst…

基于Topic消息路由的M2M设备间通信Node JS SDK 示例

概述 M2M(即Machine-to-Machine)是一种端对端通信技术。本章节以Node JS SDK为例,使用基于Topic消息路由的M2M设备间通信,主要介绍如何基于物联网平台构建一个M2M设备间通信架构。 实验步骤 第一部分:配置相关 1、产品…

8 种架构设计模式优缺点大曝光 | 原力计划

作者 | 程序员Tony责编 | 王晓曼出品 | CSDN博客什么是架构我想这个问题,十个人回答得有十一个答案,因为另外的那一个是大家妥协的结果,哈哈,我理解,架构就是骨架。人类的身体的支撑是主要由骨架来承担的,然…

企业实战_06_MyCat 常用的分片算法

接上一篇:企业实战_05_MyCat用户密码加密 https://gblfy.blog.csdn.net/article/details/100056536 下一篇:企业实战_07_MyCat 搭建Mysql 一主一从复制环境 https://gblfy.blog.csdn.net/article/details/118640210

数据库OceanBase创始人阳振坤:通关TPC-C到底有多难?

自从蚂蚁金服自研数据库OceanBase获得TPC-C测试第一名后,引起了行业内外大量关注,我们衷心的感谢大家对OceanBase的支持与厚爱,也虚心听取外界的意见和建议。为了让大家更好的了解测试的技术细节,我们特意邀请了OceanBase的核心研…

为啥程序员下班后只关显示器从不关电脑?

你下班时是不是只将显示器一关,揣上手机就走了?曾有安保人员晚上来办公室巡查时问,为什么这些人不关机就下班呢?因为等一切工具准备就绪后,半个小时已经过去了。你知道程序员的时薪有多贵吗?效率多高吗&…

从 SOA 到微服务,企业分布式应用架构在云原生时代如何重塑?

阿里妹导读:从十余年前的各种分布式系统研发到现在的容器云,从支撑原有业务到孵化各个新业务,企业的发展离不开统一的、与时俱进的技术架构。本篇文章从企业分布式应用架构层面介绍了云原生计算架构带来的变化,希望能够帮助更多企…

那些年,我们见过的 Java 服务端“问题”

导读 明代著名的心学集大成者王阳明先生在《传习录》中有云: 道无精粗,人之所见有精粗。如这一间房,人初进来,只见一个大规模如此。处久,便柱壁之类,一一看得明白。再久,如柱上有些文藻&#x…

中兴通讯uSmart云电脑,开启安全办公新时代

2020年春天,以5G、人工智能、云计算为代表的“新基建”蔚然成风,着眼国家数字经济体系建设,打造数字经济体系底座的“新基建”,无疑成为中国经济整体应对未来发展的核心方案。可以说,没有任何一个时期比现在更能够彰显…

阿里张磊:云计算生态价值点正迅速聚焦到“应用”上

导读:云原生不再只是基础设施的开发和运维人员的关注点,在应用交付领域小组成立之后,CNCF 基金会正在同应用开发和应用运维人员更紧密的联系在一起。 云原生的理念如今正如火如荼。它不仅仅是一种技术,更是社区基于对云的思考&…

SpringBoot 整合 Spring Cloud Alibaba Nacos 连通性+负载均衡

文章目录一、整合版本说明1. 毕业版本依赖关系(推荐使用)2. 组件版本关系3. 演示版本二、整合实战2.1. 聚合模块设计2.2. 创建聚合parent2.3. 依次创建子项目三、子模块配置3.1. 订单模块3.2. 产品模块3.3. 用户模块3.4. 扣库存模块3.5. 购物车模块四、测试案例4.1. 订单模块4.…

使用dubbo后尽量不用要@Service可能引起冲突

如下有几个包都含有Service dubbo最新版本2.7.8,已经把Service换成DubboService 示例实现类 package com.dubboprovider.service;import org.apache.dubbo.config.annotation.DubboService; import org.springframework.stereotype.Component;//zookeeper 服务注…

面试中遇到这 3 个SQL问题,最容易掉坑里!

作者 | Nathan R译者 | 天道酬勤,责编 | Carol封图 | CSDN下载自视觉中国在本文中,作者将介绍来自3个在技术面试中的真实的SQL问题,这些问题都是在实际公司进行技术筛选时提出的。最常见的读者问题:我应该如何准备SQL面试&#xf…

云原生数据库POLARDB专场“硬核”解析

POLARDB是阿里巴巴自主研发的云原生关系型数据库,目前兼容三种数据库引擎:MySQL、PostgreSQL、Oracle。POLARDB的计算能力最高可扩展至1000核以上,存储容量可达100TB。 POLARDB融合了商业数据库稳定、可靠、高性能的特征,同时具有…

K8s 从懵圈到熟练 – 集群网络详解

导读:阿里云 K8S 集群网络目前有两种方案:一种是 flannel 方案;另外一种是基于 calico 和弹性网卡 eni 的 terway 方案。Terway 和 flannel 类似,不同的地方在于 terway 支持 Pod 弹性网卡,以及 NetworkPolicy 功能。本…

使用dubbo后尽量不用要@Reference可能引起冲突

使用dubbo后尽量不用要Reference可能引起冲突 dubbo最新版本2.7.8,已经把Reference换成DubboReference

年薪高达30万,人才缺口40万,这个神仙职业今年太火了!

我见过市面上很多的 Python 讲解教程和书籍,他们大都这样讲 Python 的:先从 Python 的发展历史开始,介绍 Python 的基本语法规则,Python 的 list, dict, tuple 等数据结构,然后再介绍字符串处理和正则表达式&#xff0…