作者:王庆璨 张凯
前言
Kubernetes已经成为目前事实标准上的容器集群管理平台。它为容器化应用提供了自动化部署、运维、资源调度等全生命周期管理功能。经过3年多的快速发展,Kubernetes在稳定性、扩展性和规模化方面都有了长足进步。 尤其是Kubernetes控制平面的核心组件日臻成熟。而作为决定容器能否在集群中运行的调度器Kube-scheduler,更是由于长久以来表现稳定,且已能满足大部分Pod调度场景,逐渐不被开发人员特别关注。
伴随着Kubernetes在公有云以及企业内部IT系统中广泛应用,越来越多的开发人员尝试使用Kubernetes运行和管理Web应用和微服务以外的工作负载。典型场景包括机器学习和深度学习训练任务,高性能计算作业,基因计算工作流,甚至是传统的大数据处理任务。此外,Kubernetes集群所管理的资源类型也愈加丰富,不仅有GPU,TPU和FPGA,RDMA高性能网络,还有针对领域任务的各种定制加速器,比如各种AI芯片,NPU,视频编解码器等。开发人员希望在Kubernetes集群中能像使用CPU和内存那样简单地声明式使用各种异构设备。
总的来说,围绕Kubernetes构建一个容器服务平台,统一管理各种新算力资源,弹性运行多种类型应用,最终把服务按需交付到各种运行环境(包括公共云、数据中心、边缘节点,甚至是终端设备),已然成为云原生技术的发展趋势。
阿里云容器服务团队结合多年Kubernetes产品化与客户支持经验,对Kube-scheduler进行了大量扩展和改进,逐步使其在多种场景下依然能稳定、高效地调度复杂工作负载类型。
《进击的Kubernetes调度系统》系列文章将把我们的经验、技术思考和实现细节全面地展现给Kubernetes用户和开发者,期望帮助大家更好地了解Kubernetes调度系统的强大能力和未来发展方向。
早期方案
首先,让我们来了解一下Kubernetes社区都有过哪些提升调度器扩展能力的方案。
要统一管理和调度异构资源与更多复杂工作负载类型,首先面对挑战的就是Kube-scheduler。在Kubernetes社区里关于提升调度器扩展能力的讨论一直不断。sig-scheduling给出的判断是,越多功能加入,使得调度器代码量庞大,逻辑复杂,导致维护的难度越来越大,很多bug难以发现、处理。而对于使用了自定义调度的用户来说,跟上每一次调度器功能更新,都充满挑战。
在阿里云,我们的用户遇到了同样的挑战。Kubernetes原生调度器循环处理单个Pod容器的固定逻辑,无法及时、简单地支持用户在不同场景的需求。所以针对特定的场景,我们会基于原生Kube-scheduler扩展自己的调度策略。
最初对于Kube-scheduler进行扩展的方式主要有两种,一种是调度器扩展(Scheduler Extender), 另外一种是多调度器(Multiple schedulers)。接下来我们对这两种方式分别进行介绍和对比。
Scheduler Extender
社区最初提供的方案是通过Extender的形式来扩展scheduler。Extender是外部服务,支持Filter、Preempt、Prioritize和Bind的扩展,scheduler运行到相应阶段时,通过调用Extender注册的webhook来运行扩展的逻辑,影响调度流程中各阶段的决策结果。
以Filter阶段举例,执行过程会经过2个阶段:
- scheduler会先执行内置的Filter策略,如果执行失败的话,会直接标识Pod调度失败。
- 如何内置的Filter策略执行成功的话,scheduler通过Http调用Extender注册的webhook, 将调度所需要的Pod和Node的信息发送到到Extender,根据返回filter结果,作为最终结果。
我们可以发现Extender存在以下问题:
- 调用Extender的接口是HTTP请求,受到网络环境的影响,性能远低于本地的函数调用。同时每次调用都需要将Pod和Node的信息进行marshaling和unmarshalling的操作,会进一步降低性能。
- 用户可以扩展的点比较有限,位置比较固定,无法支持灵活的扩展,例如只能在执行完默认的Filter策略后才能调用。
基于以上介绍,Extender的方式在集群规模较小,调度效率要求不高的情况下,是一个灵活可用的扩展方案,但是在正常生产环境的大型集群中,Extender无法支持高吞吐量,性能较差。
Multiple schedulers
Scheduler在Kubernetes集群中其实类似于一个特殊的Controller,通过监听Pod和Node的信息,给Pod挑选最佳的节点,更新Pod的spec.NodeName的信息来将调度结果同步到节点。所以对于部分有特殊的调度需求的用户,有些开发者通过自研Custom Scheduler来完成以上的流程,然后通过和default scheduler同时部署的方式,来支持自己特殊的调度需求。