在 Azure Kubernetes 服务 (AKS) 上使用 Kueue 计划和部署批处理作业

本文介绍如何使用 Kueue 在 Azure Kubernetes 服务(AKS)上计划和部署示例批处理作业。 此外,本指南介绍如何安装 Kueue、配置 ResourceFlavors 和 ClusterQueues,以便进行精细的资源管理,以及通过 LocalQueues 提交作业。 你还了解如何使用 Kueue 对示例批处理作业进行排队,并跟踪“挂起”、“正在运行”和“完成”状态的结果。

重要

AKS 文档和示例中都提到了开源软件。 AKS 服务级别协议、有限保修和 Azure 支持不涵盖你部署的软件。 与 AKS 一起使用开源技术时,请查阅各社区和项目维护人员提供的支持选项,以制定计划。

例如,Ray GitHub 存储库描述了多个在响应时间、用途和支持级别方面各不相同的平台。

Microsoft 将负责生成我们在 AKS 上部署的开源包。 该责任包括拥有构建、扫描、签名、验证和快速修复流程的完整所有权,并掌控容器镜像中的二进制文件。 如需了解详细信息,请参阅 AKS 漏洞管理AKS 支持范围

若要详细了解 Kueue 以及批处理工作负荷管理员和用户的常见用例,请参阅 AKS 上的 Kueue 概述

先决条件

定义 ResourceFlavor 对象

在 Kueue 中,ResourceFlavors 通过将工作负荷与特定节点、污点、容忍或可用性区域相关联,从而实现精细的资源管理。 对于节点, ResourceFlavors 可以定义定价、可用性、品牌、模型和体系结构(即 x86 与 ARM CPU)等特征。 ClusterQueue 使用这些类型来管理工作负荷的配额和准入策略。

此配置定义 ResourceFlavor 不带任何标签或污点(称为空 ResourceFlavor)。 当不需要管理不同风格的配额时,此配置是完美的。

  1. 创建一个 ResourceFlavor 并保存在名为 resourceflavor-sample.yaml 的文件中,其中包含以下清单:

    cat << EOF > resourceflavor-sample.yaml
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
     name: on-demand
    EOF
    
  2. 应用

    kubectl apply -f resourceflavor-sample.yaml
    
  3. verify

    kubectl get resourceflavors
    

    示例输出

    NAME        AGE
    on-demand   5m32s
    

创建 ClusterQueue

ClusterQueue 是一种群集范围资源,用于管理资源池、定义使用限制和公平共享规则。 如果适用,公平共享规则允许 一队列中的另一个 ClusterQueue 为挂起的作业使用未使用的配额。 每个 ClusterQueue 指定它支持哪些规格以及每个规格的可用配额。

此示例 ClusterQueue 定义:

  • namespaceSelector: {}:指示sample-jobs接受来自任何通过ClusterQueue引用此LocalQueue的命名空间的工作负载(你可以使用标签选择器限制使用,例如,仅限团队 A 的命名空间)。
  • coveredResources: ["cpu", "memory"] in resourceGroups:定义由此 ClusterQueue管理的标准 CPU 和内存资源类型。
  • flavor on-demand 具有 4 CPU 和 8Gi 内存的节点:只有被安排在 on-demand 节点上的工作负荷才会使用此配额。 如果群集用完此配额,则不会接受任何使用此类型的其他工作负载(除非允许从cohort 借用)。
  1. 请在名称为ClusterQueue并包含以下清单的文件中创建和保存 Kueueclusterqueue-sample.yaml

    cat <<EOF > clusterqueue-sample.yaml
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
       name: sample-jobs
    spec:
       cohort: general
      namespaceSelector: {} # Accept workloads from any namespace
      resourceGroups:
       - coveredResources: ["cpu", "memory"]
         flavors:
           - name: on-demand
             resources:
               - name: "cpu"
                 nominalQuota: 4
               - name: "memory"
                 nominalQuota: 8Gi
    EOF
    
  2. ClusterQueue命令应用kubectl apply清单文件。

    kubectl apply -f clusterqueue-sample.yaml
    
  3. 验证 ClusterQueue 的清单文件是否已应用

    kubectl get clusterqueues
    

    示例输出

    NAME          COHORT    PENDING WORKLOADS
    sample-jobs   general   0
    

注释

在配置 ClusterQueue 对象之前,ResourceFlavor 尚未准备好使用。 如果创建一个 ClusterQueue,而没有任何现有的 ResourceFlavor,引用它的负载将被标记为 Inadmissible

创建“LocalQueue”

LocalQueue 是命名空间范围内的资源,充当用户提交作业的网关。 将 LocalQueue 分配给 ClusterQueue,以提供资源来运行其工作负载。

此示例 LocalQueue 配置以下设置:

  • batch-jobs 中的命名空间用户能够将批处理任务提交到 Kueue。
  • 将批处理工作负荷路由到 sample-jobsClusterQueue的组件,该组件管理实际计算资源配额和调度策略。
  1. 使用命令创建名为 批处理作业kubectl create 命名空间。

    kubectl create ns batch-jobs
    
  2. 创建一个 LocalQueue 并保存到名为 localqueue-sample.yaml 的文件中,使用以下 YAML 清单:

    cat <<EOF > localqueue-sample.yaml
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      name: sample-queue
      namespace: batch-jobs
    spec:
      clusterQueue: sample-jobs
    EOF
    
  3. LocalQueue命令应用kubectl apply清单文件。

    kubectl apply -f localqueue-sample.yaml
    
  4. LocalQueue验证清单是否已应用

    kubectl get localqueues --all-namespaces
    

    示例输出

    NAMESPACE    NAME           CLUSTERQUEUE   PENDING WORKLOADS   ADMITTED WORKLOADS
    batch-jobs   sample-queue   sample-jobs    0                   0
    

创建 2 个批处理作业

此配置定义提交到批处理作业命名空间的两个 Kubernetes 批处理作业,并分配给 Kueue 管理的示例队列。 这两个作业都是单实例(并行度:1,完成数:1),并配置了 Never 重启策略。 字段 parallelismcompletions 控制运行的 Pod 数量以及作业完成的方式。 因此,当将 parallelismcompletions 设置为 1 时,这意味着每个批处理作业中只能同时运行一个 Pod,并且一旦某个 Pod 成功完成,该作业就会标记为“完成”。

  • 作业测试批处理-1:请求一个 CPU 和 500Mi 内存
  • 作业测试批处理-2:请求两个 CPU 和 1Gi 内存
  1. 使用以下名为 YAML 清单的批处理作业创建两个示例批处理作业,以在batch-workloads.yaml命名空间中部署:

    cat <<EOF > batch-workloads.yaml
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: test-batch-1
      namespace: batch-jobs
      labels:
        kueue.x-k8s.io/queue-name: sample-queue
    spec:
      parallelism: 1
      completions: 1
      template:
        spec:
          containers:
            - name: dummy-job
              image: registry.k8s.io/e2e-test-images/agnhost:2.53
              command: ["sh", "-c", "echo Running test-batch-1; sleep 60"]
              resources:
                requests:
                  cpu: "1"
                  memory: "500Mi"
                limits:
                  cpu: "1"
                  memory: "500Mi"
          restartPolicy: Never
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: test-batch-2
      namespace: batch-jobs
      labels:
        kueue.x-k8s.io/queue-name: sample-queue
    spec:
      parallelism: 1
      completions: 1
      template:
        spec:
          containers:
            - name: dummy-job
              image: registry.k8s.io/e2e-test-images/agnhost:2.53
              command: ["sh", "-c", "echo Waiting in queue for CPUs...; sleep 30"]
              resources:
                requests:
                  cpu: "2"
                  memory: "1Gi"
                limits:
                  cpu: "2"
                  memory: "1Gi"
          restartPolicy: Never
    EOF
    
  2. 使用 kubectl apply 命令为批处理作业应用清单。

    kubectl apply -f batch-workloads.yaml
    

验证批处理作业是否已提交到 LocalQueue

  1. 使用 kubectl get 命令查看批处理工作负荷的状态。

    kubectl get workloads --namespace batch-jobs
    

    示例输出

    NAME            ADMITTED    AGE
    test-batch-1    True        10s
    test-batch-2    False       5s
    
  2. test-batch-2Pending状态时运行以下命令

    kubectl get workloads test-batch-2 -o yaml
    

    预期输出

    ...
    ...
    Status:
      Conditions:
        Type:              Admitted
        Status:            False
        Reason:            QuotaUnavailable
        Message:           Insufficient quota in ClusterQueue sample-jobs 
        (flavor on-demand): requested 2 CPUs, available 1
    ...
    ...
    

    test-batch-1完成后,test-batch-2将被接受并运行。

    现在,输出应如以下示例输出所示:

    Status:
      Conditions:
        Type:              Admitted
        Status:            True
        Last Transition Time:  1234-56-78T00:00:00Z
      Admission:
        ClusterQueue:      sample-jobs
        PodSetAssignments:
          Name:            main
          Flavors:
            cpu:           on-demand
            memory:        on-demand
          ResourceUsage:
            cpu:           2
            memory:        1Gi
    
  3. 使用batch-jobs命令查看kubectl get命名空间的最终状态。

    kubectl get job,deploy,rs,pod,workload --namespace batch-jobs
    

    示例输出

    NAME                     STATUS     COMPLETIONS   DURATION   AGE
    job.batch/test-batch-1   Complete   1/1           97s        3m15s
    job.batch/test-batch-2   Complete   1/1           35s        3m15s
    
    NAME                     READY   STATUS      RESTARTS   AGE
    pod/test-batch-1-hb8zl   0/1     Completed   0          3m15s
    pod/test-batch-2-dx9hk   0/1     Completed   0          3m15s
    
    NAME                                             QUEUE          RESERVED IN   ADMITTED   FINISHED   AGE
    workload.kueue.x-k8s.io/job-test-batch-1-6fb85   sample-queue   sample-jobs   True       True       3m15s
    workload.kueue.x-k8s.io/job-test-batch-2-84f49   sample-queue   sample-jobs   True       True       3m15s
    

FAQ

问题 1:如何确认 Kueue 控制器是否可用并按预期运行?

  1. 使用 kubectl get 命令确认 Kueue 控制器管理器 Pod 正在运行。

    kubectl get pods --namespace kueue-system
    

    Kueue 控制器管理器 Pod 应处于 Running 状态,并且 1/1 个容器就绪,如以下示例输出中所示:

    NAME                                                 READY   STATUS      RESTARTS    AGE
    kueue-controller-manager-xxxxxxx    1/1        Running     0                  2m
    
  2. 如果Status显示CrashLoopBackOffPending,请使用kubectl logs命令检查部署日志。

    kubectl logs --namespace kueue-system deployment/kueue-controller-manager
    

问题 2:通过 Helm 安装时,一个或多个 Kueue 自定义资源(CRDs)不见了。 如何确保已安装所有的自定义资源定义(CRD)?

  1. 使用 AKS 指南上的 Kueue 概述安装 Kueue 后,请确认所有 CRD 都使用 kubectl get 命令安装。

    kubectl get crds | grep kueue
    

    应列出以下这些 CRD,如以下示例输出中所示:

    admissionchecks.kueue.x-k8s.io
    clusterqueues.kueue.x-k8s.io
    cohorts.kueue.x-k8s.io
    localqueues.kueue.x-k8s.io
    multikueueclusters.kueue.x-k8s.io
    multikueueconfigs.kueue.x-k8s.io
    provisioningrequestconfigs.kueue.x-k8s.io
    resourceflavors.kueue.x-k8s.io
    topologies.kueue.x-k8s.io
    workloadpriorityclasses.kueue.x-k8s.io
    workloads.kueue.x-k8s.io
    
  2. 如果缺少一个或多个 CRD,您可能会在控制器日志中看到错误、作业无法排队、CrashLoopBackOff 控制器的问题,或者无法接纳或调度工作负载。 在这种情况下,您可以使用命令 kubectl apply 手动重新安装 Kueue CRDs。

    kubectl apply -f https://github.com/kubernetes-sigs/kueue/releases/latest/download/kueue-crds.yaml
    

    注释

    请注意,如果手动安装 CRD,则需要在使用 kubectl delete 完命令后手动删除它们。

问题 3:LocalQueue 与 ClusterQueue 之间的区别

ClusterQueue 是一种群集范围的资源,用于定义和管理整个 Kubernetes 群集中的 CPU、内存、Pod 和加速器等计算资源的池。 LocalQueue 是一个命名空间范围的资源,作为用户在定义的 Kubernetes 集群中提交作业的网关。 这种分离允许对资源分配和多租户计划进行精细的控制,而无需直接向用户公开群集范围的配额。

它们如何协同工作:

  1. 用户将他们的命名空间中的任务提交到 LocalQueue。
  2. Kueue 将作业路由到引用的“ClusterQueue”。
  3. ClusterQueue 会检查资源可用性和配额限制。
  4. 如果承认,则作业未暂停并计划。

后续步骤

本文内容:

  • 在 Azure Kubernetes 服务 (AKS) 群集上使用 Helm 安装 Kueue,并验证了 CRD、控制器运行状况和命名空间的配置。
  • 配置 ClusterQueueLocalQueue 用于通用工作负载,其中包括资源配额和实例类型(如按需)。
  • 提交了两个批处理作业以演示队列机制:一个被立即接受,第二个由于配额限制被暂缓,然后在资源可用时被接受。
  • 监视的工作负荷状态和控制器日志,以确认计划行为和队列逻辑。

若要了解有关 Kueue 的详细信息,请访问以下资源: