乐趣区

关于kubernetes:Kube-QueueKubernetes-任务排队的利器

批处理作业(Batch Job)常利用于数据处理、仿真计算、科学计算和人工智能等畛域,次要用于执行一次数据处理或模型训练任务。因为这类工作往往须要耗费大量计算资源,因而必须依据工作的优先级和提交者的可用资源状况进行正当排队,能力最大化集群资源的利用效率。

Scheduler 在任务调度畛域水土不服

以后 Kubernetes 的调度器提供了欠缺的 Pod 通用调度性能,然而在面对大量工作排队时,仍然暴露出了局限性:

  • 短少自动化的排队机制

默认状况下,批处理工作会间接创立作业 Pod,当集群可用资源有余时,大量 Pending Pod 会重大拖慢 Kubernetes 调度器的处理速度,影响在线业务扩容和调度。因而,迫切需要可能主动依据集群资源管制作业启停的自动化排队机制。

  • 短少多样化的排队策略

为晋升工作排队效率,须要依据集群资源和工作规模,采取阻塞队列、优先级队列、回填调度等不同的排队策略。然而,Kubernetes 调度器的默认调度策略次要依据优先级和 Pod 创立程序进行排队,难以应答多样化的工作排队需要。

  • 短少多队列能力

为隔离不同用户或租户的工作,防止资源被繁多用户的大量工作占满,导致其它用户“饿死”,工作排队零碎须要反对多队列治理,将不同用户提交的任务分配到不同队列中排队。目前,Kubernetes 调度器仅反对繁多队列,无奈无效防止此类问题。

  • 大量工作类型难以对立

在机器学习、高性能计算、大数据计算和离线工作流等不同利用场景下,用户会提交不同类型的工作,每类工作对资源和优先级的计算方法都有所不同,将这些计算逻辑都集成到调度器中,必然大幅减少保护复杂性和运维老本。

因而,在解决简单的任务调度场景时,云服务提供商通常不将原生 Kubernetes 调度器作为首选计划。

Queue 在 Kubernetes 中的定位与职责

在 Kubernetes 集群中,Queue 与 Scheduler 独特合作以确保工作的高效调度。为了防止“脑裂”等典型的分布式系统问题,必须清晰划分它们的职责。目前,Kubernetes 中的 Queue 能够分为两类:

第一类 Queue 与 Kubernetes 的 Scheduler 属于不同分层。Queue 负责工作的排序和按程序出队,专一于工作的生命周期治理和实现更偏心的用户间出队策略;Scheduler 负责工作 Pod 的正当编排,找到最优的搁置策略,专一于节点亲和性、拓扑感知等方面。这类 Queue 不间接感知底层的物理信息,工作出队后可能会因为节点亲和性、资源碎片化等因素无奈调度,导致队头阻塞。因而,这类队列通常须要引入“工作在无奈调度时从新入队”的机制。本文将介绍的 Kube Queue 和开源社区中的 Kueue 都是这类 Queue 的代表。

第二类 Queue 与 Scheduler 互相耦合,工作只有在确保可能调度的状况下才会出队。这种设计防止了第一类 Queue 的队头阻塞问题,然而仍然存在难以齐全兼容调度器全副调度语法的问题。而且,应用这类 Queue 意味着须要替换默认调度器,对集群而言是较大的变更。这类 Queue 的典型代表有 Volcano 和 YuniKorn。

Kube Queue 概述

Kube Queue 是阿里云容器服务 ACK 的云原生 AI 套件中的一个要害组件,旨在解决以上 Kubernetes 调度器在任务调度场景中存在的问题。Kube Queue 通过与云原生 AI 套件的 Arena 组件以及 ACK 集群的弹性 Quota 个性相结合,可能高效反对多种 AI 工作主动排队和多租户 Quota 治理。

Kube Queue 的架构如下图所示,由以下次要局部形成:

  1. Kube Queue Controller:负责工作排队的外围控制器,如下图左侧所示。
  2. Operator Extension:为不同工作类型提供定制化反对的扩大组件,如下图右侧所示。

Kube Queue 的工作机制

工作排队零碎围绕两个外围形象——Queue 和 QueueUnit:

Queue:代表一个队列实体,是队列进行排队的容器,它蕴含队列的策略、Quota、排队参数等信息。目前 Kube Queue 可能主动感知不同品种的资源配额,如 Resource Quota、Elastic Quota 和 ElasticQuotaTree。Kube Queue Controller 会依据这些 Quota 的配置主动创立对应的 Queue 对象。用户仅须要配置下层的 Quota,无需额定配置底层队列。

QueueUnit:代表一个工作实体,它会疏忽原工作中与排队策略无关的参数信息,从而缩小 Kube Queue Controller 须要监听的对象类型以及与 Api Server 建设的连接数。并且,因为 QueueUnit 屏蔽了理论 Job 的类型,任何须要接入排队零碎的工作,仅需实现 Extension 的排队接口即可,无效实现了工作类型的可扩大。

工作流程如下:

工作提交和入队:当一个可被 Kube Queue 辨认的工作被提交到 Api Server,对应的 Job Operator 和 Operator Extension 会收到工作创立事件。它们会依据工作提交时是否为挂起状态,决定是否接管工作排队。若工作提交时处于挂起状态,Extension 会评估工作所需资源和确定优先级等要害排队参数,并创立 QueueUnit(这是在 Kube Queue 排队的对立对象,其初始状态为 Enqueued)。

工作排队和期待调度:Kube Queue Controller 接管到 QueueUnit 的创立后,会依据外部队列归属策略确定 QueueUnit 所属队列,并在队列内依据优先级与创立工夫进行排序。Kube Queue Controller 通过一个调度循环解决所有队列,每轮循环会从每个队列中抽取出队头的工作尝试调度,以此确保不同队列中的工作数量和优先级不会相互烦扰。

工作出队和执行调度:工作出队后,QueueUnit 状态更新为 Dequeued,Extension 接管到此状态后会移除该工作的挂起状态。Operator 监听到工作解除挂起后,会开始创立工作 Pod,尔后工作进入失常的调度流程。若工作在一个可配置的超时时段内未实现调度,Extension 会将对应的 QueueUnit 重置为 Enqueued 状态,代表工作启动超时,须要从新排队,这样做是为了避免队列呈现队头阻塞。若工作胜利执行,QueueUnit 的状态则会被更新为 Running。

Kube Queue 的排队策略

排队策略是排队零碎不可短少的局部。目前,Kube Queue 提供了三种灵便的排队策略以满足企业客户的多样化需要,且每个队列都可配置独立的排队策略。

轮转策略(默认策略)

ack-kube-queue 默认采纳与 kube-scheduler 雷同的工作轮转机制解决工作,即所有工作在队列中顺次申请资源,申请失败则进入 Unschedulable 队列退却,期待下次调度。该策略确保每个工作均有机会调度,最大效率利用 Quota,但对于出队的工作可能无奈严格保障优先级。举荐在心愿保障集群资源利用率的状况下应用该策略。

阻塞策略

当集群中存在大量资源需求量小的工作时,因为小工作会占用大量队列轮转工夫,资源需求量大的工作将难以获得资源执行,存在长时间 Pending 的危险。为了防止此类情况,ack-kube-queue 提供阻塞队列性能,开启后,队列将只调度队列最前端的工作,使得大工作可能有机会执行。举荐在心愿保障工作优先级的状况下应用该策略。

严格优先级策略

为了保障高优先级工作可能在集群取得闲暇资源时被优先尝试调度,即使它们仍处于退却阶段,ack-kube-queue 提供严格优先级调度性能。开启后,队列将在运行中的工作完结后,从最早提交的高优先级工作开始尝试执行,使其优先取得集群闲暇资源,防止资源被低优先级工作占用。该策略是轮转策略和阻塞策略的折中策略。

疾速上手 Kube Queue

在本节中,咱们将通过一个理论案例演示如何应用 Kube Queue 执行一个根本的工作排队操作。

首先,须要装置 kube-queue 组件,在阿里云容器服务 ACK 产品的云原生 AI 套件页面中即可一键装置。可参考:如何装置及应用工作队列 ack-kube-queue[1]

装置了 Kube Queue 之后,在集群的 kube-queue 命名空间下会存在 Kube Queue Controller 和多个针对不同 Job 类型提供扩大反对的 Controller。每个 Controller 会负责 Kube Queue 与一种类型工作的对接。

默认状况下,kube-queue-controller 中会通过 oversellrate 参数设置超卖比为 2,此时队列会可能出队配置资源两倍资源量的工作,能够在 Deployment 的编辑页面中将超卖比设置为 1。

若需实现两个 Job 之间的排队,首先须要提交一个申明队列的 ElasticQuotaTree。该 ElasticQuotaTree 申明了一个最多能够应用 1 核 CPU 和 1Gi 内存资源的队列,并将 default 命名空间挂载在该队列下。

apiVersion: scheduling.sigs.k8s.io/v1beta1
kind: ElasticQuotaTree
metadata:
  name: elasticquotatree
  namespace: kube-system # 只有 kube-system 下才会失效
spec:
  root:
    name: root # Root 节点的 Max 等于 Min
    max:
      cpu: 1
      memory: 1Gi
    min:
      cpu: 1
      memory: 1Gi
    children:
    - name: child-1
      max:
        cpu: 1
        memory: 1Gi
      namespaces: # 配置对应的 Namespace
        - default

之后,咱们提交两个 Kubernetes Job,提交时须要将 Job 设置为 Suspend 状态,行将 Job 的 .spec.suspend 字段设置为 true。

apiVersion: batch/v1
kind: Job
metadata:
  generateName: pi-
spec:
  suspend: true
  completions: 1
  parallelism: 1
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["sleep",  "1m"]
        resources:
          requests:
            cpu: 1
          limits:
            cpu: 1
      restartPolicy: Never

提交之后,查看工作状态,能够看到两个工作中仅有一个工作开始执行,另一个工作进入期待状态。

在前一个工作执行实现后,后续工作主动开始执行,实现工作执行的自动控制。

What’s Next

在本篇文章中,咱们探讨了云原生时代下,工作队列零碎的重要性以及必要性,并具体介绍了阿里云容器服务 ACK 的 Kube Queue 如何在以后的 Kubernetes 生态中,明确本身的角色定位与价值奉献。在后续的文章中,咱们将进一步探讨,如何利用容器服务 ACK 的 Kube Queue 以及高效的调度机制,疾速构建一个可能满足企业需要、基于 ElasticQuotaTree 的工作管理系统。

相干链接:

[1] 如何装置及应用工作队列 ack-kube-queue

https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/…

作者:吴昆

原文链接

本文为阿里云原创内容,未经容许不得转载。

退出移动版