Kubernetes 1.28:改进了作业的故障处理

Kubernetes 1.28 实用新功能

Kubernetes 1.28:改进了作业的故障处理

作者:Kevin Hannon (G-Research), Michał Woźniak (Google)

本篇文章讨论了 Kubernetes 1.28 版本中为了改进批量用户的作业而引入的两个新功能:Pod 替换策略和每个索引的退避限制。这些功能延续了由 Pod 失败策略发起的努力,以改进作业中 Pod 故障的处理。


Pod 替换策略

默认情况下,当一个 Pod 进入终止状态(例如由于抢占或驱逐),Kubernetes 会立即创建一个替代的 Pod。因此,这两个 Pod 同时运行。从 API 的角度来看,当一个 Pod 拥有 .deletionTimestampPendingRunning 时,它被认为是处于终止状态。对于一些流行的机器学习框架(例如 TensorFlow 和 JAX),在同一时刻最多只允许一个特定索引的 Pod 运行,这种情况会带来问题。如果同一索引有两个 Pod 在运行,TensorFlow 将会报错如下:

/job:worker/task:4: Duplicate task registration with task_name=/job:worker/replica:0/task:4

在前一个 Pod 完全终止之前创建替代 Pod 也可能会在资源稀缺或预算紧张的集群中引发问题,例如:

1. 集群资源可能难以获取,因为待调度的 Pod 可能需要很长时间才能找到可用的节点,直到现有的 Pod 完全终止。

2. 如果启用了集群自动缩放器,替代的 Pod 可能会导致不必要的扩容。


如何使用这些功能呢?

这是一个 alpha 功能,您可以通过在集群中启用功能开关 JobPodReplacementPolicy 来开启。一旦在您的集群中启用了该功能,您可以通过创建一个新的 Job,并指定一个字段,如下所示,来使用它:podReplacementPolicy


kind: Job
metadata:
  name: new
  ...
spec:
  podReplacementPolicy: Failed
  ...

在该作业中,只有当 Pod 达到阶段时才会进行替换,而不是在其处于终止状态时进行替换。此外,您可以检查作业的一个字段。该字段的值是由该作业拥有且当前正在终止的 Pod 数量。.status.terminating

kubectl get jobs/myjob -o=jsonpath='{.items[*].status.terminating}'
3 # three Pods are terminating and have not yet reached the Failed phase

对于外部排队控制器(如 Kueue),此功能可能特别有用,它会追踪作业中运行的 Pod 的配额,直到资源从当前正在终止的作业中回收。请注意,当使用自定义的 Pod 失败策略时,默认为 podReplacementPolicy: Failed。


索引的重试限制

默认情况下,对于索引作业的 Pod 失败会计入全局的重试限制,由 .spec.backoffLimit 表示。这意味着,如果某个索引持续失败,它会被重复重新启动,直到达到限制。一旦达到限制,整个作业将被标记为失败,某些索引可能甚至永远不会启动。

对于需要独立处理每个索引的 Pod 失败的用例,这是有问题的。例如,如果您使用索引作业来运行集成测试,其中每个索引对应一个测试套件。在这种情况下,您可能希望考虑可能出现的测试不稳定性,每个套件允许重试 1 次或 2 次。可能会有一些有问题的套件,导致相应的索引始终失败。在这种情况下,您可能更喜欢限制有问题的套件的重试次数,但允许其他套件完成。

此功能允许您:

  • 尽管某些索引失败,但完成所有索引的执行。
  • 通过避免不必要的持续失败索引重试,更有效地利用计算资源。 

如何使用这个功能?

这是一个alpha版功能,您可以通过在集群中打开功能开关 JobBackoffLimitPerIndex 来启用它。一旦在您的集群中启用了该功能,您可以创建一个带有指定字段的索引作业.spec.backoffLimitPerIndex


示例

以下示例演示了如何使用此功能来确保作业执行所有索引(前提是没有其他导致作业提前终止的原因,比如达到超时时间,或被用户手动删除),并且每个索引的失败次数受到.activeDeadlineSeconds控制。


apiVersion: batch/v1
kind: Job
metadata:
  name: job-backoff-limit-per-index-execute-all
spec:
  completions: 8
  parallelism: 2
  completionMode: Indexed
  backoffLimitPerIndex: 1
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: example # this example container returns an error, and fails,
                      # when it is run as the second or third index in any Job
                      # (even after a retry)        
        image: python
        command:
        - python3
        - -c
        - |
          import os, sys, time
          id = int(os.environ.get("JOB_COMPLETION_INDEX"))
          if id == 1 or id == 2:
            sys.exit(1)
          time.sleep(1)          

现在,在作业完成后检查Pod:

kubectl get pods -l job-name=job-backoff-limit-per-index-execute-all

返回类似以下的输出:

NAME                                              READY   STATUS      RESTARTS   AGE
job-backoff-limit-per-index-execute-all-0-b26vc   0/1     Completed   0          49s
job-backoff-limit-per-index-execute-all-1-6j5gd   0/1     Error       0          49s
job-backoff-limit-per-index-execute-all-1-6wd82   0/1     Error       0          37s
job-backoff-limit-per-index-execute-all-2-c66hg   0/1     Error       0          32s
job-backoff-limit-per-index-execute-all-2-nf982   0/1     Error       0          43s
job-backoff-limit-per-index-execute-all-3-cxmhf   0/1     Completed   0          33s
job-backoff-limit-per-index-execute-all-4-9q6kq   0/1     Completed   0          28s
job-backoff-limit-per-index-execute-all-5-z9hqf   0/1     Completed   0          28s
job-backoff-limit-per-index-execute-all-6-tbkr8   0/1     Completed   0          23s
job-backoff-limit-per-index-execute-all-7-hxjsq   0/1     Completed   0          22s

此外,您还可以查看该作业的状态:

kubectl get jobs job-backoff-limit-per-index-fail-index -o yaml

输出的末尾类似于:status

  status:
    completedIndexes: 0,3-7
    failedIndexes: 1,2
    succeeded: 6
    failed: 4
    conditions:
    - message: Job has failed indexes
      reason: FailedIndexes
      status: "True"
      type: Failed

在这里,索引都重新尝试了一次。在每个索引的第二次失败中,都超过了指定的 backoffLimitPerIndex,因此重试被停止。相比之下,如果禁用了每个索引的退避限制,那么有问题的索引会一直重试,直到全局 backoffLimit 被超过,然后整个作业会被标记为失败,而一些较高的索引在开始之前就会失败。


如何获取更多信息?

阅读有关 Pod 替换策略、每个索引的退避限制和 Pod 失败策略的用户文档。

阅读 Pod 替换策略、每个索引的退避限制和 Pod 失败策略的 KEP(Kubernetes Enhancement Proposal)。


参与其中

这些功能由 SIG Apps 赞助。批处理工作组正在为 Kubernetes 用户积极改进批处理用例。工作组是专注于特定目标的相对短期的倡议。批处理工作组的目标是改善批处理工作负载用户的体验,为批处理用例提供支持,并针对常见用例增强作业 API。如果您对此感兴趣,请通过订阅我们的邮件列表或在 Slack 上加入工作组。


致谢

与 Kubernetes 的任何功能一样,从测试、提交错误到审查代码,许多人都为完成这项工作做出了贡献。如果没有 Aldo Culquicondor(谷歌)在整个 Kubernetes 生态系统中提供的出色领域知识和专业知识,我们不可能实现这些功能。


本文翻译自Kubernetes.io

转载请注明出处:https://www.cloudnative-tech.com/technology/5965.html

(0)
上一篇 2023年8月31日 下午12:14
下一篇 2023年8月31日 下午1:58

相关推荐

  • Kubernetes安全机制详解

    本文将详细介绍Kubernetes的安全机制。在使用Kubernetes时,确保集群的安全性至关重要。文章将讨论Kubernetes的安全设计原则和机制,包括身份验证、授权、网络隔离、安全策略等,以帮助企业保护其应用程序和数据的安全。

    2023年5月26日
    0
  • K8s部署方案有哪几种?

    在Kubernetes上部署应用程序可以提高应用程序的可靠性和可伸缩性,同时简化应用程序的部署和管理。本文将介绍Kubernetes的几种部署方案。

    2023年6月6日
    0
  • Docker常用命令大全

    以下是Docker常用命令的大全,包括容器管理、镜像管理、网络管理和数据管理等方面。

    2023年5月23日
    0
  • kubernetes容器管理的优势和应用场景

    本文将介绍Kubernetes的容器管理功能,包括容器调度、资源管理、服务发现和负载均衡等方面,以及它对容器化应用程序的优势和应用场景。

    2023年5月19日
    0
  • 企业级容器云技术的命令

    企业级容器云技术中使用的命令涵盖了容器管理、集群管理、网络管理、存储管理、安全管理等方面。以下是一些常用的命令示例:

    2023年6月29日
    0