ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Kubernetes调度器原理与算法详解:从资源分配到故障排查

Kubernetes调度器原理与算法详解:从资源分配到故障排查 1. 调度器到底在解决什么问题为什么不能靠人工分配先说个真实场景。有次我帮朋友排查一套生产集群总共二十多台工作节点跑着两百多个服务资源水位一直很紧张。结果发现有个核心业务Pod已经Pending了三天没人发现原因特别基础它要4核8G的规格而集群里所有节点剩下的碎片资源没有一台能完整满足这个组合需求。当时的维护者说了一句话让我印象很深我以为它会自动帮我分到最合适的机器上没想到它连这台机器在哪都找不到。这就是调度的本质问题调度器不是分配机器而是决策并找到一台条件完全满足的节点。它要替整个集群回答一个非常现实的问题——在这几百台配置不同、负载不同、还不断有旧Pod结束、新Pod启动的动态环境里我手上的每个工作负载到底放到哪台机器上才算合理。很多人觉得这是个小事情节点多就随便放呗。真不是。我常拿停车位打比方一个好的调度器相当于一个脑子清醒的停车场管理员他不仅知道哪里有空位还知道哪个车位离电梯最近、哪条通道容易堵、哪辆车的车主赶时间、哪片区域晚上有活动不能停。而糟糕的调度器就像闭着眼随便指位置的管理员结果是资源明明够有些车就是停不进去或者停进去了晚点想把车开出来得挪一排车。放在分布式系统里调度器要同时满足三个看似矛盾的目标资源利用率要足够高一台机器只要没被用满对你来说就是在亏钱。不管你是自建机房还是按量付费空转的CPU和内存都是真金白银。服务质量要足够稳不能为了凑利用率把两个互相争抢CPU的敏感业务塞到同一台机器上导致业务互相拖垮。系统要能扛故障某台节点出问题的时候调度器不能假装看不见继续把新任务送过去更得能让旧任务快速换一台机器重新跑起来。所以调度器本质上是资源拍卖师交通警察保险理赔员三个角色的集合体。这也是为什么业界几乎所有集群管理系统——Kubernetes、YARN、Mesos、Slurm、HashiCorp Nomad——都把调度器当成最核心的组件来设计而不是用一套脚本简单处理。现在调度器已经从单机按条件挑一台进化成了全局打分排序择优录取从只看CPU内存进化成了考虑GPU、网络带宽、存储拓扑、数据本地性、Pod间亲和反亲和、优先级抢占这些复杂因素。你只有理解了它存在的根本动机后面遇到那些明明资源很充足但就是调度不上去的问题时才能有方向去排查而不是一头扎进日志里瞎翻。2. 三种主流调度算法的设计逻辑FIFO、容量调度与公平调度的取舍调度器不是只有一种实现思路。不同历史时期、不同业务场景各家公司摸索出了几套截然不同的调度算法。搞懂它们各自的模型和代价比单纯背概念有用得多。2.1 最朴素的先来先服务FIFO调度最早期的集群调度就是排队。谁先提交任务谁就先进去被安排。这个方案的优点是实现简单、逻辑清晰提交顺序就是执行顺序谁都无话可说。但它的致命缺陷也显而易见队头阻塞。想象一下第一个来的任务要求一台万中无一的特定机器比如指定GPU型号后面排队的那些只需要普通CPU的任务全都得等它找到合适的机器才能往下走。我见过一个真实案例一个团队提交了个需要某种特殊GPU的深度学习任务但当时集群里根本没这种卡后面几百个正常的Spark任务就全被堵在队列里整个集群利用率掉到5%以下。这就是FIFO最大的坑——它只关心顺序不关心资源匹配度遇到一个刁钻的任务就能摧毁整条流水线。现在的纯FIFO调度基本只在单机进程级调度里还能看到影子多租户集群已经没人敢直接裸用了。2.2 容量调度给每个团队圈好责任田容量调度的思路是把整个集群的物理资源按比例划分成一个个独立的队列每个队列有自己固定的资源上限。A团队最多用30%的CPUB团队最多用20%谁都不能越界。这套方案最明显的好处是隔离性极强。某个团队哪怕写了个资源黑洞应用最多也只能把自己那个队列吃满影响不到别人。YARN的Capacity Scheduler、Kubernetes的ResourceQuota本质都是这个思路——通过配额把故障爆炸半径限制住。不过代价也很直接很容易造成资源浪费。假设A团队凌晨没有任务他那30%的资源空着B团队业务量突然暴涨就算B需要更多算力也拿不到A的空闲份额。内存和CPU又不像人一样可以借来借去。所以后来主流实现都做了弹性借用的改良队列A空闲时允许队列B临时借用一旦队列A有新任务提交借出去的要还回来。这个机制很实用但它要求调度器要非常敏锐地感知任务进出队列的时机实现复杂度一下子就上来了。2.3 公平调度力争让大家差不多满意公平调度的核心思想简单说就是动态维持一个均衡水位。调度器实时统计每个用户/队列的累计使用量在分配新任务时优先把手头资源给用得最少的那个队列。最经典的实现是Max-Min Fairness先把资源均分给每个队列有人用不满的份额再拿出来二次分配循环往复。这是一个很优雅的增量算法一套公式就能保证最终出来一个相对均衡的结果。公平调度的优势是天然适配多租户共享集群。适合那种很多个团队共用一套集群、谁都不希望自己老被饿着的场景。但要注意它也有自身的问题为了追求绝对公平调度器会增加很多额外的计算量而且如果每个队列的需求本身就差异巨大单纯追求公平会导致大任务吃不饱、小任务被反复让位。实际落地时通常要加上权重配置比如核心业务队列权重是10实验性业务队列权重是1让公平在加权的基础上慢慢收敛。2.4 为什么实际系统都是混合模式我个人的经验是真正能用于生产的调度系统几乎没有只用上述某一种纯算法的。Kubernetes默认调度器就玩了个组合先跑一轮filter阶段把不满足硬性条件的节点全部剔除然后在剩下的节点里按打分规则排序这就不是单纯谁先来谁先得了而是条件优先分数择优。YARN里你还可以给队列同时配置容量上限和公平权重实现长周期看配额、短周期看公平。理解了这三类算法你才看得懂生产系统里那一堆调度参数的初衷而不是照抄别人的配置。3. 一次调度请求的完整生命周期从Pod提交到节点绑定的每一步纸上谈兵没意思直接看Kubernetes调度器的工作流程最有代表意义。一套完整的调度流程绝不止看哪个节点空闲就放过去那么简单它分为四个阶段我一个个拆开讲。3.1 调度器凭什么能看到所有Pod和节点Kubernetes里的调度器是一个独立组件kube-scheduler它通过API Server监听集群状态。你要理解一个关键点调度器本身没有任何直接操控节点的能力它只是一个决策大脑所有的判断依据来自API Server给它推送的数据快照。所以集群里每次有节点标注变化、Pod申请新资源、或者某个节点状态异常API Server都会通知调度器调度器内部维护着一份当前集群全景图的内存缓存。这一层设计使得调度器不用每次都去所有节点上一个个问你还有多少内存性能大幅提升。但也正因为是缓存它会有一个视图一致性问题——比如某个节点的资源明明已经被其他Pod占了但调度器缓存的可用资源还没更新这时新来的Pod就有可能被调度到一个实际上已经放不下的节点上。解决思路一般是通过资源预留机制或者后续的二次确认兜底后面我讲坑的时候会细说。3.2 过滤阶段把根本不可能的节点直接淘汰这个阶段在Kubernetes里叫Predicates新版本代码里叫Filter。它做的是大量硬性检查只要节点有任何一项硬性条件不满足这个节点就被直接踢出候选名单。常见的检查项包括节点资源是否够请求的CPU、内存、GPU、临时存储都必须在节点当前可分配量范围内。PodSelector是否匹配调度Pod的时候经常打上nodeSelector要求只调度到拥有标签envprod的节点不匹配的直接排除。端口冲突如果两个Pod都要绑同一个宿主端口比如8080那二选一不能放在同一台机器。磁盘和卷冲突某些存储类型比如ReadWriteOnce的云盘只能被一台机器挂载如果一个节点已经被占用后续需要挂载同一块盘的Pod就不能调度过去。污点容忍度节点打了污点taintPod如果没有对应容忍toleration就不能上去。你可以把这个阶段理解为海选不管节点分高分低先把那些有硬伤的筛掉。很多新手第一反应是我Pod调度不到节点上是不是资源不足其实有大量情况是卡在这个过滤阶段比如标签没匹配上、存储冲突、宿主端口被占用。3.3 打分阶段从都能放里选最合适的过滤完剩下的节点全部满足硬性条件。这时进入第二阶段的打分Kubernetes里叫Priorities新版本叫Score。这个阶段的主要工作就是按一组策略规则给每个候选节点打分分数最高者获胜。打分策略五花八门常见的包括LeastRequestedPriority资源最空优先把请求量小的节点排前尽量把负载铺平防止资源碎片化。BalancedResourceAllocation资源均衡优先CPU和内存平衡的节点分数更高避免出现一台节点CPU内存配比极端不均衡还继续塞新任务。ImageLocality本地镜像优先如果节点上已经有启动Pod需要的镜像就不用再拉了启动时间大幅缩短这类节点得分更高。NodeAffinity节点亲和性如果有软性偏好偏好比如preferredDuringScheduling满足偏好的节点会加分。打分阶段本质就是把集群运营目标数字化。注意最合适不等于空闲最多因为某些场景里数据在本地比资源多一点重要得多——比如大数据任务如果调度到一台没有对应数据的节点光拉数据就能把任务的收益抵消掉。3.4 绑定阶段与最终执行选出了最优节点调度器仍然不能自己做主。它只是向API Server发起一个绑定Binding请求——把Pod和Node关联起来。这个过程是异步的API Server持久化这个绑定记录之后目标节点的kubelet会发现有一个新Pod归我了然后它再去调容器运行时把Pod真正启动起来。看到没有调度器只负责决策不负责执行。这个边界很重要因为在多调度器并存的场景下它可以做到可以随时换调度器不影响节点上已经跑着的Pod。这也是控制器模式的核心哲学分工明确各司其职。3.5 一个完整的时间线例子我举个例子方便你理解全链路。假设你在Kubernetes里提交了一个名为nginx-frontend的Pod请求1核CPU、512M内存要求调度到带有zoneshanghai标签的节点上Pod被创建进入Pending状态调度器第一时间通过API Server感知到这个新Pod的出现。调度器遍历集群全部节点先做过滤把所有没有zoneshanghai标签的节点全部排除同时检查内存、CPU是否满足端口是否冲突污点是否容忍。假设100个节点里剩5个符合条件。进入打分环节同样的512M请求空闲度高的节点分高如果某个节点本地已经缓存了nginx镜像可能还会再拿3~5分的镜像本地加分。最后选了最高分节点比如node-073。调度器发起绑定Pod的spec里被记录上nodeName: node-073状态从Pending变成Running或者说Scheduled。node-073的kubelet发现有新Pod拉镜像、创建容器、启动健康检查最终Pod Ready。整个流程从提交到最终绑定在几百节点的集群里通常只需要毫秒到秒级的时间。调度器之所以快是因为它不需要等容器真正启动只做软决策。4. 亲和性、污点与自定义调度器把话说得更细的控制手段默认调度器已经能处理一般场景但生产环境里总有我要把这批Pod放到同一个机架、这个节点只能给某个特殊业务用这种精细需求。Kubernetes和YARN都提供了对应控制原语。4.1 亲和性与反亲和性先说节点亲和性。它分硬性要求requiredDuringScheduling和软性偏好preferredDuringScheduling。硬性要求其实就是高级版nodeSelector条件不满足时直接不调度软性偏好则是我更喜欢但实在没有也能接受。Pod间亲和性PodAffinity则解决另一个痛点把多个相关的服务尽量放到同一个拓扑域里。举个典型场景两个服务A和B之间高频调用如果把它们放到不同的可用区请求延迟和流量费用都会增加设置PodAffinity让B优先调度到A已经在跑的节点就能让数据路径变短、整体吞吐量提升。反亲和性PodAntiAffinity正好相反目的是分散风险。比如有两个业务副本我不想让它们落在同一台机器上——一台机器故障不会把两个副本同时打挂。这在部署核心有状态服务比如Kafka、ZooKeeper、Redis集群时几乎是必配项。我要提醒一点强制的PodAffinity是有调度代价的。当两个Pod必须放在同一台机器上你就把候选节点范围缩小了一大截很容易出现另一个Pod在想调度的节点上但因为它的副本数量一直在变导致这个Pod永远等不到它过来的循环等待。所以我一般建议核心服务用软性偏好配合反亲和性的强制规则。4.2 污点和容忍度白名单式的准入控制污点Taint和容忍度Toleration的设计逻辑很有意思它和亲和性正好互补。亲和性是我能接受哪类节点污点则是我不想接收哪类Pod。给节点打上一个污点比如dedicatedbigdata:NoSchedule所有没有明确容忍这个大数据的Pod就不会被调度到这个节点上。这个机制在规划专用节点池时特别有效GPU节点打上污点只有带GPU需求的Pod容忍它才能被调度过去管理面节点打上污点业务Pod默认就不会跑上去确保集群核心组件不被业务流量挤爆。污点还有个带特殊效果的类型叫NoExecute。它不光阻止新Pod上来还会把节点上已存在但不容忍该污点的旧Pod直接驱逐。这在节点预维护、网络故障隔离的时候非常有用——给故障节点打上NoExecute污点上面的业务就会自动迁移走了不需要人工一台台去删。4.3 什么时候需要自己写一个调度器默认调度器的扩展点已经很强了但总有些场景它覆盖不了业务调度依赖很专有数据比如电影渲染任务需要知道每个节点当前GPU温度、渲染队列排队长度默认调度器拿不到这些数据也没法用通用打分策略表达。需要全局最优而不仅是节点局部最优有些批处理系统要一次性调度几千个Task希望总体完成时间最短单纯逐个Pod按当前状态决策做不到这种全局规划。调度逻辑涉及业务资源配额体系比如某个公司内部有一套业务线信用分要按信用分决定资源投放优先级这属于业务策略不是基础设施策略。遇到这些情况你可以做自定义调度器。Kubernetes提供了多调度器并存机制只要你的调度器通过API Server监听Pod并且定期提交绑定请求就能和默认调度器互不干扰。你只需要在Pod的spec里显式声明schedulerName: my-custom-scheduler即可“点名”让某个Pod走自定义调度器。不过我得泼盆冷水自定义调度器是个双刃剑。你接手了全部策略实现什么过滤、打分、高可用、cache一致性全得自己搞定。大多数公司没必要从零写完全可以先扩展默认调度器比如用Scheduler Framework的Plugin机制实现自定义打分和过滤不满足需求再考虑完全自研。我见过有团队为了调度一个极小众场景直接自研了一套调度器结果后来维护成本远超收益最后又迁回默认调度器了。4.4 调度器Framework的扩展点用法Kubernetes从1.19开始正式把调度器改成可插拔的Framework架构内置了一系列扩展点Extension Points。常用的包括QueueSort决定Pod在调度队列里的排序规则。PreFilter / Filter相当于过滤阶段的预检查和主检查。PostFilter过滤完发现没有可用节点时可以尝试抢占低优先级Pod来腾位置。Score打分阶段可以注册自己的计分算法。Bind自定义绑定逻辑比如某些场景需要先预留资源再绑定。这个机制比自研整套调度器轻量得多。我实际做过的一个案例给一个AI训练平台写了两个插件一个在Filter里检查节点是否有空闲GPU显存、另一个在Score里根据节点上已部署同类训练任务的个数加分实现了把同批次训练任务尽量散开的效果最终任务排队时间比默认调度少了30%左右。所以我的建议是先默认调度器再到Framework插件最后才轮到全自研。顺序千万不能反了。5. 抢占、优先级与混部调度资源不够用的时候怎么办资源永远是不够用的。调度器常规分配之外还有一个重要职责当新任务到来而集群已经没有足够资源时决定谁让位、什么时候让位。5.1 优先级类和抢占调度Kubernetes里通过PriorityClass定义优先级从-1000到100000000010亿数字越大优先级越高。调度器在处理Pod时会优先调度高优先级Pod。当高优先级Pod到达但无节点满足资源条件时调度器会尝试抢占挑一个低优先级Pod赶走把资源腾出来给高优先级用。这个逻辑特别像救灾时的交通管制救护车来了普通车辆要全部让路。但引入抢占也带来了资源抖动的代价被抢占的Pod说没就没如果它不是无状态服务会导致数据丢失或事务回滚。所以生产上我只给两类场景开高优先级抢占集群控制面组件比如DNS、网络组件挂了整个集群都受影响这种必须能抢占。在线核心交易链路可以抢占离线计算任务但不能抢占其他在线服务。而且要把PriorityClass的差设计得合理核心业务优先级5离线任务优先级1不要动不动就搞10亿否则会出现大猴子抢小猴子的凳子大猴子又被更大的猴子抢的连环抢占风暴。5.2 延迟绑定和声明式资源做内存资源超卖很多集群为了让利用率更好看会开内存压缩/超卖但调度器一超卖就可能出事。你可以给每个节点设置可分配量Allocatable比物理总量小很多并在节点上预留一部分系统保留和驱逐阈值。比较实用的一个技巧是用DSDaemonSet方式在每个节点固定放一个资源占位容器声明给这个节点留下500M内存缓冲。这样调度器天然以为这台节点可分配量少了500MPod实际使用量即便偶尔超一点也不太容易触达内核OOM。这个思路本质上是利用调度器的声明式资源模型来人为预留安全垫在传统超卖方案里非常好用。5.3 混部调度在线服务离线任务一体化的最佳实践混部Colocation是这几年的大趋势业务高峰和离线计算高峰通常错峰白天在线业务忙晚上离线批处理闲不住把它们按比例放在同一批节点上能极大提升集群整体资源利用率。但混部的难点在于在线业务对延迟极度敏感离线任务又爱争抢CPU缓存和内存带宽。调度器需要能识别两种任务特征并做出分级保障在线Pod开启CPU绑核/独占策略离线任务只能用空闲CPU。离线任务设置更低的资源Request实际运行中在线资源不足时优先驱逐离线Pod。通过Monitoring侧数据动态调整节点上的调度水位如果在线业务延迟上升就收缩可混部的离线条数。Kubernetes社区有Crane、Koordinator这些开源组件专门做这类混部调度优化。我自己体验下来它们最大的价值是让调度器从静态配置转变为数据驱动的动态调整——调度器不再只看Request还会参考实际监控指标来决策。这一点对追求极致性价比的公司很有吸引力但同时也对监控体系和稳定性保障提出了很高要求。5.4 调度性能上百节点时需要注意什么这节虽然放最后但生产上经常被忽略。默认Kubernetes调度器在几百节点规模内表现没问题但到几千节点、每秒大量Pod提交时容易出现两个坑调度器性能受节点过滤遍历制约每次都要过一遍所有节点节点越多耗时越长。社区的解决思路是做节点数分片和并行比如把节点分成多个组并行过滤然后汇总结果。Resync周期导致视图滞后如果调度器缓存和真实集群状态差距过大会出现调度到了但绑定失败的窘境。Kubernetes会在绑定后再次做一轮调度结果检查来兜底但如果你的自定义调度器没有这层保障就得自己实现一个异步确认机制。我的实践建议是超过500个节点的集群给kube-scheduler单独做资源配额和独立故障域别让它跟业务Pod抢资源。最好再配置一个健康检查专门盯着调度器的调度时延和队列堆积数这两个指标有异常及时报警否则调度队列一旦堵了整个集群看起来还活着实际上新业务全部Pending。6. 一个真实疑难杂症的排查过程节点资源充足但Pod一直Pending纸上得来终觉浅。我选一个真实案例带你完整走一遍排查链路。这个案例我印象很深因为它隐藏得太深了——你说它是调度问题吧它更像配置问题你说它是配置问题吧它又牵涉到调度器工作机制。6.1 故障现象用户反馈在Kubernetes集群里提交了一个Deployment创建了3个副本但有一个副本永远Pending。看节点资源CPU和内存都充足怎么看都不像资源不够。6.2 初步排查看Pod状态和事件我第一步永远是kubectl describe pod xxx看Events。结果发现事件里没有任何调度器日志只是显示Pending。这个细节很关键正常情况下如果调度器真的跑过调度流程Events里会显示类似Successfully assigned default/xxx to node-073这种信息。如果一个Pod长时间Pending且没有任何调度事件要么就是调度器根本没看到这个Pod要么就是Pod的spec里指定了一个不存在的schedulerName导致没有任何调度器认领它。6.3 深挖发现自定义schedulerName残留查看Pod的YAML果然发现schedulerName: my-scheduler。但集群里根本没有部署这个自定义调度器所以默认的kube-scheduler看到这个名字就直接跳过了——就像你给一份快递写了个不存在的快递公司名称所有快递员看到都绕道走。这种问题常见于一些DevOps平台或自动化发布系统它们为了支持自定义调度会默认注入这个字段结果在没部署对应调度器的环境里就留下了一个坑。解法很简单把schedulerName删掉或改成default-schedulerPod立刻就能被调度了。排错心得遇到Pending先别查资源先看Events里有没有调度事件。没有调度事件优先怀疑schedulerName不匹配或者调度器整体挂了有调度事件但失败再去查过滤阶段的标签、污点、资源。6.4 第二个坑节点有污点Pod没有容忍度另一个类似案例里Events能看到调度器在尝试但显示的提示是0/8 nodes available: 8 node(s) had taint {dedicatedgpu: NoSchedule}。这就是前面讲的污点机制生效了。解决办法两种要么给Pod加对应的Toleration要么把节点上的污点去掉如果不是刻意要做隔离的话。生产上这个坑特别常见平台团队给某批新节点打了污点还没来得及给业务方同步业务的人就开始用——然后一排服务全部Pending。6.5 第三个坑端口冲突还有一次比较隐蔽两个微服务都监听宿主机的30080端口调度器过滤阶段就把所有节点都刷掉了因为每个节点都已经被其中一个服务占了端口。这种问题Events会提示node(s) had existing hostPort conflicts。排查思路也简单把那两个服务的hostPort改成不同端口或者一个不用hostPort改用NodePortIngress方式暴露即可。这个坑的隐蔽性在于如果你事先不知道两个服务用同一个端口扫日志半天也看不出问题。6.6 推荐的工具和调试姿势排查调度问题我常用的三板斧kubectl get pod -o wide快速看Pod被调度到哪个节点。kubectl describe pod看Events这是第一手线索。kubectl get events --sort-by.lastTimestamp按时间排整个命名空间的事件流经常能看到调度器在一堆小动作之后的最终决定。如果是大规模集群调度性能问题再配合看kube-scheduler的metrics比如scheduler_scheduling_algorithm_duration_seconds、scheduler_pod_scheduling_attempts。这个指标可以告诉你调度器本身耗不耗时。7. 调度器之外还剩哪些细节容易翻车最后聊几个我在实际部署中反复踩过的边角问题虽然不直接影响调度算法但每次翻车都跟调度二字有关。第一件是资源请求和限额的设置有讲究。很多团队习惯把Pod的Request写得特别低、Limit写得特别高试图提高装箱率。这确实能让调度器塞下更多Pod但一旦节点实际负载撞到Limit上限内核会开始出现CPU Throttling延迟直线上升。调度器看不懂这个假象它只会按Request做决定。所以我建议也设置一下命名空间级别的ResourceQuota防止团队之间堆高Limit导致节点超卖太狠。第二件是节点的标签管理。亲和性、污点、拓扑分布约束都依赖标签标签一乱调度全乱。生产环境最好对标签做统一规范哪些标签是基础设施层的比如node-role哪些是业务层的比如app-name谁有权限增删都要有明确约速。有次我们排查一个Pod分配不均匀的问题最后发现是有个节点漏打了区域标签调度器以为它不在任何可用区导致大量Pod挤在了其他区域内。第三件是调度器自身的高可用。kube-scheduler默认是多副本部署的副本间通过选主机制leader election来保证同一时刻只有一个调度器在真正干活。很多人以为多副本就是多个调度器一起干活不是的——只有leader在处理请求。这也就意味着就算你有两个kube-scheduler副本如果选主机制出问题或者leader节点网络抖动调度任务照样会停摆。建议监控一下kube-scheduler的leader状态这个指标出问题的时候集群表面上一切正常但所有新Pod都会被卡在Pending。最后说个团队文化层面的事。调度器是基础设施但影响的是所有人的业务体验。最好建一个调度资源申请表和配套的规范文档明确说明什么样的场景该用亲和性、什么样的场景该用污点、什么样的配置可以放宽Request。很多调度问题根本不是技术故障而是没人知道这个集群还有这个约束结果新服务一上来就撞上历史遗留的调度策略排障排了两天最后发现加一个toleration就完事了。8. 调度器的下一步从单集群走向多集群统一调度现在很多公司不止一套Kubernetes集群有按地域分的有按环境分的有按业务部门分的。虽然各集群内部调度器还没有到必须统一改造的程度但我发现越来越多的团队已经在讨论多集群调度的问题。这个问题核心是当一个业务应用需要跨集群扩容时谁来决策放到哪个集群如果每个集群的调度器只关心自己集群内部的节点那跨集群的选择就只能靠上层流量调度比如Ingress权重、DNS轮询或者人工来决策。但这不够精细——如果上海集群CPU已经跑满90%但杭州集群只有40%流量权重还硬按50/50分配那就白白浪费了杭州的算力。目前业界的思路是在调度器之上再做一个集群选择层或者说是一个集群级别调度器。它负责回答A应用要部署该去上海还是杭州、还是两地都部署而下层每个集群的调度器再负责在这个集群内部找到最合适的节点。这个分层架构的好处是上层的决策可以综合网络延迟、成本、数据主权、容灾等级这些全局因素下层的调度器不需要也没办法了解全局只做好自己内部的资源分配就行。我判断未来一两年这个方向会有更多产品化落地机会。不过这也不意味着每个人都得立刻开始搞多集群统一调度。如果你公司目前只有一两个集群、规模也不大那单集群内部的调度优化反而更值得投入。先把节点的标签规范、资源配额、污点隔离这些基本功做好比引入一个复杂的大一统调度器更实际。技术选型永远不要为了赶概念而超前把当下集群里的水端平了比什么都强。
返回列表