Kubernetes 如何走向统一调度之路
原文:How Kubernetes Is Transforming into a Universal Scheduler
计算机科学里,调度指的是一种能够为作业分配满足其执行所需资源的方法。IBM 在 60 年代的 S/360 中首次提出这一概念,可以说是年代久远了。
对所有存在资源需求的作业来说,调度都是至关重要的。在操作系统的上下文中,作业可能是个简单的程序,资源可能是 CPU 核心。类似的,操作系统中的调度器可能就只是一些用于操作线程或信号的代码。
分布式计算将调度器的疆土从内部的进程和线程扩展到了物理机集群之中。90 年代中,Corba、DCOM 以及 J2EE 等分布式平台应运而生,在应用服务器集群内发展了各自的调度组件。
再后来,出现了 Amazon EC2、Azure Fabric 以及 OpenStack Nova 这样的 IaaS 平台,这些平台的控制平面完成了对运行于物理机基础之上的虚拟机的调度工作。根据资源需求将虚拟机实例安置在合适的物理机上。
基于 Apache Hadoop 和 MapReduce 算法的大数据工作负载对调度算法非常依赖。Hadoop 的文件系统 HDFS 就用于保障集群上的节点能够访问到数据集。这一架构聚焦于资源的的稳定性和可用性保障。
Cloud Foundry 和 Heroku 这样的 PaaS 实现中包含了设计精密的调度逻辑,用来为服务提供隔离的环境。每个服务都被打包,部署在虚拟或物理服务器的执行环境之中。
横空出世的容器,强迫业界重新审视资源调度器的设计。新一代调度器的设计理念更加重视简单性和伸缩性。传统应用服务器面对的是少量服务器,而容器管理平台要管理的容器工作节点数量可能从几台到几千台。
Kubernetes 和 Mesosphere 是当代资源调度器的代表。它们的设计对底层基础设施进行了抽象,用透明的方式为用户提供调度服务。
Kubernetes 中的调度
Kubernetes 平台中,调度器是一个关键组件。它在主节点上运行,和 API Server 以及 Controller 紧密合作。调度器的核心任务就是对 Pod 和 Node 进行撮合。可以在 Kubernetes architecture 一文中透彻的了解其架构。
调度器会在多个方面对可用资源进行评估,从而为 Pod 分配合适的节点。另外还可以通过对节点亲和性的设置,为 Pod 分配指定特性的节点。例如一个一个高 IO 的数据库 Pod 可能需要调度到配有 SSD 存储的节点上。还有可能为了降低延迟,将一系列的 Pod 调度到同一节点上,这一操作称为 Pod 亲和性。Kubernetes 还支持自定义调度器,完全由第三方实现分配逻辑。
Kubernetes 调度器的最大亮点就是其简单性。前面描述的多数策略都能很轻松的实现。只要通过一点注解和标签,就能完成 Pod 和节点之间的亲和或排斥的定义。通过对 Pod 和节点的键值对设置就能够实现成熟的调度逻辑。
超越 Pod 和节点的 Kubernetes 调度器
Kubernetes 可能是目前最好的资源调度器之一。兼顾简单和扩展能力的调度器让用户能够解决很多传统分布式系统中的调度问题。
在高度分布的环境中,Kubernetes 正在成为首选的作业调度和管理工具。这些作业包括在物理服务器上部署虚拟机、在边缘设备上运行容器,甚至还具有将控制平面扩展到 Serverless 环境这样的其他调度器上的能力。
KuberVirt 就是一个 Kubernetes 上的虚拟机管理插件,它让用户能够像 Pod 一样在 Kubernetes 或 OpenShift 集群上运行虚拟机。这一系统用 CRD 的形式来进行虚拟机的设置,完成了对 Kubernetes 的扩展。KubeVirt 虚拟机运行在普通的 Kubernetes Pod 之内,从而具有了访问标准 Pod 网络和存储的能力,并且可以使用标准的 kubectl
或者类似的 Kubernetes 工具来进行管理。
来自 Mirantis 的 Virtlet 项目让虚拟机可以在 Kubernetes 集群中像普通 Pod 一样运行。运维人员可以用 kubectl
命令管理虚拟机,并且将虚拟机以一等公民的身份纳入集群网络。有了 Virtlet 就可以构建高级的 Kubernetes 对象,例如 Deployment、Statefulset 或者 DaemonSet。
微软的 Virtual Kubelet 是最有趣的一个调度器。Virtual Kubelet 是一个 Agent,运行在注册为 Kubernetes 集群节点的外部环境之中。这个 Agent 会通过 Kubernetes API 创建节点资源。通过对污染和隔离功能的使用,会通过本地 API 来进行外部环境中的 Pod 调度。
Virtual Kubelet 可以在 Azure Container Instance、Azure IoT Edge 以及 AWS Fargate 上运行。
另外,我还写过其他文章,介绍了 Virtual Kubelet 的架构和部署指南,可供读者参考。
更进一步——自定义调度器和 CRD
上面讨论的例子只是冰山一角。Kubernetes 正在成为当代基础设施的基础,正在迈入传统业务应用领域——例如 ERP 和 CRM。
应用提供商们将会越来越重的依赖 Kubernetes 的两个功能:自定义调度器和 CRD。
正如前文所说,Kubernetes 的自定义调度器让开发者可以实现自己的调度逻辑。Pod 的声明中就可以通知控制面跳过缺省调度器,转而采用自定义调度。这一机制能够保障集群内的 Pod 得到正确安置。
Portworx 是一个云原生生存储公司,它使用自定义调度器来创建 STORK(Kubernetes 存储编排运行时:STorage Orchestrator Runtime for Kubernetes)。从而保障它的 Stateful Pod 只会在安装了 Portworx 驱动和存储的节点上运行。这一功能对于运行其上的数据库负载的可用性保障很有帮助。
Kubernetes 中的 CRD 为自定义对象提供了简单且强大的生命周期支持。自定义资源是一种对象,对 Kubernetes API 进行了扩展,开发人员可以利用这一机制将自己的 API 引入 Kubernetes。CRD 文件声明了自定义对象的定义,让 API Server 能够处理整个生命周期。在 Kubernetes 中部署 CRD,就是让 Kubernetes API Server 开始支持某种自定义资源。
CRD 创建之后,运维人员可以使用 kubectl
或者第三方工具来进行管理,这一过程和 Pod 等内置对象并无二致。ISV 可以利用 CRD 的方式将自己的软件进行打包和部署。
Kubernetes 的扩展性,使其具备了成为统一调度管理工具的潜质。