作业故障排除

排查作业状态

此文档介绍如何排查待处理的 Kubernetes 作业,但大多数思路可以推断到其他 受支持的作业类型

请参阅 Kueue 概述,以了解协作运行作业的组件。

在此文档中,假设你的作业名为 my-job,位于 my-namespace 命名空间中。

识别作业的工作负载

对于每个作业,Kueue 会创建一个 工作负载 对象来保存有关作业准入的详细信息,无论是否准入。

要查找作业的工作负载,可以使用以下任何步骤

  • 可以通过运行以下命令从作业事件中获取工作负载名称

    kubectl describe job -n my-namespace my-job
    

    相关的事件将如下所示

      Normal  CreatedWorkload   24s   batch/job-kueue-controller  Created Workload: my-namespace/job-my-job-19797
    
  • Kueue 在标签 kueue.x-k8s.io/job-uid 中包含源作业的 UID。可以使用以下命令获取工作负载名称

    JOB_UID=$(kubectl get job -n my-namespace my-job -o jsonpath='{.metadata.uid}')
    kubectl get workloads -n my-namespace -l "kueue.x-k8s.io/job-uid=$JOB_UID"
    

    输出如下所示

    NAME               QUEUE         RESERVED IN   ADMITTED   AGE
    job-my-job-19797   user-queue    cluster-queue True       9m45s
    
  • 可以列出作业所在命名空间中的所有工作负载,并识别与格式 <api-name>-<job-name>-<hash> 匹配的工作负载。可以运行如下命令

    kubectl get workloads -n my-namespace | grep job-my-job
    

    输出如下所示

    NAME               QUEUE         RESERVED IN   ADMITTED   AGE
    job-my-job-19797   user-queue    cluster-queue True       9m45s
    

识别出工作负载的名称后,可以通过运行以下命令获取所有详细信息

kubectl describe workload -n my-namespace job-my-job-19797

我的作业是否已暂停?

要了解作业是否已暂停,请通过运行以下命令查找 .spec.suspend 字段的值

kubectl get job -n my-namespace my-job -o jsonpath='{.spec.suspend}'

当作业暂停时,Kubernetes 不会为作业创建任何 Pod。如果作业已经运行 Pod,Kubernetes 会终止并删除这些 Pod。

当 Kueue 尚未准入作业或当作业被抢占以容纳另一个作业时,作业将被暂停。要了解作业暂停的原因,请检查相应的 Workload 对象。

我的作业是否已准入?

如果作业未运行,请检查 Kueue 是否已准入工作负载。

了解作业是否已准入、正在处理还是尚未尝试准入的起点是查看工作负载状态。

运行以下命令以获取工作负载的完整状态

kubectl get workload -n my-namespace my-workload -o yaml

已准许的工作负载

如果你的作业已准许,工作负载应具有类似于以下内容的状态

apiVersion: kueue.x-k8s.io/v1beta1
kind: Workload
...
status:
  admission:
    clusterQueue: cluster-queue
    podSetAssignments:
    - count: 3
      flavors:
        cpu: default-flavor
        memory: default-flavor
      name: main
      resourceUsage:
        cpu: "3"
        memory: 600Mi
  conditions:
  - lastTransitionTime: "2024-03-19T20:49:17Z"
    message: Quota reserved in ClusterQueue cluster-queue
    reason: QuotaReserved
    status: "True"
    type: QuotaReserved
  - lastTransitionTime: "2024-03-19T20:49:17Z"
    message: The workload is admitted
    reason: Admitted
    status: "True"
    type: Admitted

待处理的工作负载

如果 Kueue 已尝试准许工作负载,但由于配额不足而失败,则工作负载应具有类似于以下内容的状态

status:
  conditions:
  - lastTransitionTime: "2024-03-21T13:43:00Z"
    message: 'couldn''t assign flavors to pod set main: insufficient quota for cpu
      in flavor default-flavor in ClusterQueue'
    reason: Pending
    status: "False"
    type: QuotaReserved

我的 ClusterQueue 是否具有作业所需的资源请求?

当你提交具有资源请求的作业时,例如

$ kubectl get jobs job-0-9-size-6 -o json | jq -r .spec.template.spec.containers[0].resources
{
  "limits": {
    "cpu": "2"
  },
  "requests": {
    "cpu": "2"
  }
}

如果你的 ClusterQueue 没有 requests 的定义,Kueue 无法准许该作业。对于上述作业,你应在 resourceGroups 下定义 cpu 配额。定义 cpu 配额的 ClusterQueue 如下所示

apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "cluster-queue"
spec:
  namespaceSelector: {}
  resourceGroups:
  - coveredResources: ["cpu"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 40

有关更多信息,请参阅 资源组

待处理准许检查

当 ClusterQueue 配置了 准许检查,例如 ProvisioningRequestMultiKueue 时,工作负载可能保持类似于以下内容的状态,直到准许检查通过

status:
  admission:
    clusterQueue: dws-cluster-queue
    podSetAssignments:
      ...
  admissionChecks:
  - lastTransitionTime: "2024-05-03T20:01:59Z"
    message: ""
    name: dws-prov
    state: Pending
  conditions:
  - lastTransitionTime: "2024-05-03T20:01:59Z"
    message: Quota reserved in ClusterQueue dws-cluster-queue
    reason: QuotaReserved
    status: "True"
    type: QuotaReserved

未尝试的工作负载

当使用具有 StrictFIFO queueingStrategyClusterQueue 时,Kueue 仅尝试允许每个 ClusterQueue 的头部。因此,如果 Kueue 未尝试允许工作负载,则工作负载状态可能不包含任何条件。

配置错误的 LocalQueues 或 ClusterQueues

如果你的作业引用了不存在的 LocalQueue,或者它引用的 LocalQueue 或 ClusterQueue 配置错误,则工作负载状态将如下所示

status:
  conditions:
  - lastTransitionTime: "2024-03-21T13:55:21Z"
    message: LocalQueue user-queue doesn't exist
    reason: Inadmissible
    status: "False"
    type: QuotaReserved

请参阅 排查队列问题 以了解 ClusterQueue 或 LocalQueue 为何处于非活动状态。

我的作业是否被抢占?

如果你的作业未运行,并且你的 ClusterQueues 已启用 抢占,则你应检查 Kueue 是否抢占了工作负载。

status:
  conditions:
  - lastTransitionTime: "2024-03-21T15:49:56Z"
    message: 'couldn''t assign flavors to pod set main: insufficient unused quota
      for cpu in flavor default-flavor, 9 more needed'
    reason: Pending
    status: "False"
    type: QuotaReserved
  - lastTransitionTime: "2024-03-21T15:49:55Z"
    message: Preempted to accommodate a higher priority Workload
    reason: Preempted
    status: "True"
    type: Evicted
  - lastTransitionTime: "2024-03-21T15:49:56Z"
    message: The workload has no reservation
    reason: NoReservation
    status: "False"
    type: Admitted

Evicted 条件表明工作负载已被抢占,而 QuotaReserved 条件(status: "True")表明 Kueue 已尝试再次允许它,但在此情况下未成功。

我的作业的 Pod 是否正在运行?

当作业未暂停时,Kubernetes 会为该作业创建 Pod。要检查其中有多少 Pod 已调度并正在运行,请检查作业状态。

运行以下命令以获取作业的完整状态

kubectl get job -n my-namespace my-job -o yaml

输出将类似于以下内容

...
status:
  active: 5
  ready: 4
  succeeded: 1
  ...

active 字段显示作业中有多少 Pod,而 ready 字段显示其中有多少正在运行。

要列出作业的所有 Pod,请运行以下命令

kubectl get pods -n my-namespace -l batch.kubernetes.io/job-name=my-job

输出将类似于以下内容

NAME             READY   STATUS    RESTARTS   AGE
my-job-0-nxmpx   1/1     Running   0          3m20s
my-job-1-vgms2   1/1     Running   0          3m20s
my-job-2-74gw7   1/1     Running   0          3m20s
my-job-3-d4559   1/1     Running   0          3m20s
my-job-4-pg75n   0/1     Pending   0          3m20s

如果 Pod 或 Pod 卡在 Pending 状态,请通过运行以下命令检查为 Pod 发出的最新事件

kubectl describe pod -n my-namespace my-job-0-pg75n

如果 Pod 无法调度,输出将类似于以下内容

Events:
  Type     Reason             Age                From                Message
  ----     ------             ----               ----                -------
  Warning  FailedScheduling   13s (x2 over 15s)  default-scheduler   0/9 nodes are available: 9 node(s) didn't match Pod's node affinity/selector. preemption: 0/9 nodes are available: 9 Preemption is not helpful for scheduling.
  Normal   NotTriggerScaleUp  13s                cluster-autoscaler  pod didn't trigger scale-up: