Kubernetes v1.31 [稳定](默认启用)本文档向您展示如何结合默认的 Pod 回退失败策略使用 Pod 失败策略,以改进对 Job 中容器或 Pod 级别故障的处理控制。
定义 Pod 失败策略有助于您:
您应该已经熟悉 Job 的基本用法。
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个节点的集群上运行本教程,且这些节点不能作为控制平面主机。如果你还没有集群,可以通过 minikube 创建一个,或者使用以下 Kubernetes 演练场之一。
您的 Kubernetes 服务器版本必须在 v1.25 或更高版本。要检查版本,请输入 kubectl version。
考虑以下定义了 Pod 失败策略的 Job 使用场景:
通过以下示例,您可以了解当 Pod 故障指示不可重试的软件错误时,如何使用 Pod 失败策略避免不必要的 Pod 重启。
查看以下清单
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-failjob
spec:
completions: 8
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"]
args:
- -c
- echo "Hello world! I'm going to exit with 42 to simulate a software bug." && sleep 30 && exit 42
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onExitCodes:
containerName: main
operator: In
values: [42]
应用清单
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-failjob.yaml
大约 30 秒后,整个 Job 应终止。通过运行以下命令检查 Job 的状态
kubectl get jobs -l job-name=job-pod-failure-policy-failjob -o yaml
在 Job 状态中,会显示以下条件
FailureTarget 条件:具有一个设置为 PodFailurePolicy 的 reason 字段,以及一个包含关于终止的更多信息的 message 字段,例如 Container main for pod default/job-pod-failure-policy-failjob-8ckj8 failed with exit code 42 matching FailJob rule at index 0。一旦 Job 被视为失败,Job 控制器就会添加此条件。有关详细信息,请参阅 Job Pod 的终止。Failed 条件:与 FailureTarget 条件具有相同的 reason 和 message。Job 控制器在 Job 的所有 Pod 终止后添加此条件。作为对比,如果禁用了 Pod 失败策略,Job 将重试直到达到 backoffLimit(6 次失败)。由于重试使用指数回退,并且在 parallelism: 2 的情况下,故障成对发生,尝试之间的延迟会随着每次重试而增加。因此,在这个示例中,Job 在失败前至少需要 9 分钟。
删除您创建的 Job
kubectl delete jobs/job-pod-failure-policy-failjob
集群会自动清理 Pod。
通过以下示例,您可以了解如何使用 Pod 失败策略来忽略 Pod 中断,防止其增加 Pod 重试计数器(直至达到 .spec.backoffLimit 限制)。
查看以下清单
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-ignore
spec:
completions: 4
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"]
args:
- -c
- echo "Hello world! I'm going to exit with 0 (success)." && sleep 90 && exit 0
backoffLimit: 0
podFailurePolicy:
rules:
- action: Ignore
onPodConditions:
- type: DisruptionTarget
应用清单
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-ignore.yaml
运行此命令检查 Pod 调度到的 nodeName
nodeName=$(kubectl get pods -l job-name=job-pod-failure-policy-ignore -o jsonpath='{.items[0].spec.nodeName}')
排空节点以在 Pod 完成前驱逐它(90 秒内)
kubectl drain nodes/$nodeName --ignore-daemonsets --grace-period=0
检查 .status.failed 以确认 Job 的计数器未增加
kubectl get jobs -l job-name=job-pod-failure-policy-ignore -o yaml
取消清空节点
kubectl uncordon nodes/$nodeName
Job 恢复并成功完成。
作为对比,如果禁用了 Pod 失败策略,Pod 中断将导致整个 Job 终止(因为 .spec.backoffLimit 设置为 0)。
删除您创建的 Job
kubectl delete jobs/job-pod-failure-policy-ignore
集群会自动清理 Pod。
通过以下示例,您可以了解如何使用 Pod 失败策略基于自定义 Pod 条件避免不必要的 Pod 重启。
查看以下清单
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-config-issue
spec:
completions: 8
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: "non-existing-repo/non-existing-image:example"
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onPodConditions:
- type: ConfigIssue
应用清单
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-config-issue.yaml
请注意,镜像是错误配置的,因为它不存在。
运行以下命令检查 Job 的 Pod 状态
kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o yaml
您将看到类似于以下的输出
containerStatuses:
- image: non-existing-repo/non-existing-image:example
...
state:
waiting:
message: Back-off pulling image "non-existing-repo/non-existing-image:example"
reason: ImagePullBackOff
...
phase: Pending
注意,Pod 保持在 Pending 阶段,因为它无法拉取错误配置的镜像。原则上,这可能是一个瞬时问题,镜像可能会被拉取。然而在这种情况下,镜像不存在,因此我们通过自定义条件来指明这一事实。
添加自定义条件。首先通过运行以下命令准备补丁
cat <<EOF > patch.yaml
status:
conditions:
- type: ConfigIssue
status: "True"
reason: "NonExistingImage"
lastTransitionTime: "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
EOF
其次,通过运行以下命令选择一个由 Job 创建的 Pod
podName=$(kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o jsonpath='{.items[0].metadata.name}')
然后,通过运行以下命令在其中一个 Pod 上应用补丁
kubectl patch pod $podName --subresource=status --patch-file=patch.yaml
如果应用成功,您将收到如下通知
pod/job-pod-failure-policy-config-issue-k6pvp patched
通过运行以下命令删除 Pod,使其转换为 Failed 阶段
kubectl delete pods/$podName
通过运行以下命令检查 Job 的状态
kubectl get jobs -l job-name=job-pod-failure-policy-config-issue -o yaml
在 Job 状态中,查看 Job 的 Failed 条件,其 reason 字段等于 PodFailurePolicy。此外,message 字段包含关于 Job 终止的更详细信息,例如:Pod default/job-pod-failure-policy-config-issue-k6pvp has condition ConfigIssue matching FailJob rule at index 0。
删除您创建的 Job
kubectl delete jobs/job-pod-failure-policy-config-issue
集群会自动清理 Pod。
为了按索引避免不必要的 Pod 重启,您可以使用“Pod 失败策略”和“每个索引的回退限制”特性。本页的这一节展示如何同时使用这些特性。
查看以下清单
apiVersion: batch/v1
kind: Job
metadata:
name: job-backoff-limit-per-index-failindex
spec:
completions: 4
parallelism: 2
completionMode: Indexed
backoffLimitPerIndex: 1
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/python:3
command:
# The script:
# - fails the Pod with index 0 with exit code 1, which results in one retry;
# - fails the Pod with index 1 with exit code 42 which results
# in failing the index without retry.
# - succeeds Pods with any other index.
- python3
- -c
- |
import os, sys
index = int(os.environ.get("JOB_COMPLETION_INDEX"))
if index == 0:
sys.exit(1)
elif index == 1:
sys.exit(42)
else:
sys.exit(0)
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailIndex
onExitCodes:
containerName: main
operator: In
values: [42]
应用清单
kubectl create -f https://k8s.io/examples/controllers/job-backoff-limit-per-index-failindex.yaml
大约 15 秒后,检查 Job 的 Pod 状态。您可以通过运行以下命令来执行此操作
kubectl get pods -l job-name=job-backoff-limit-per-index-failindex -o yaml
您将看到类似于以下的输出
NAME READY STATUS RESTARTS AGE
job-backoff-limit-per-index-failindex-0-4g4cm 0/1 Error 0 4s
job-backoff-limit-per-index-failindex-0-fkdzq 0/1 Error 0 15s
job-backoff-limit-per-index-failindex-1-2bgdj 0/1 Error 0 15s
job-backoff-limit-per-index-failindex-2-vs6lt 0/1 Completed 0 11s
job-backoff-limit-per-index-failindex-3-s7s47 0/1 Completed 0 6s
注意,输出显示了以下内容
FailIndex 操作的 Pod 失败策略。通过运行以下命令检查 Job 的状态
kubectl get jobs -l job-name=job-backoff-limit-per-index-failindex -o yaml
在 Job 状态中,看到 failedIndexes 字段显示 "0,1",因为两个索引都失败了。由于索引 1 没有被重试,失败的 Pod 数量(由状态字段 "failed" 指示)等于 3。
删除您创建的 Job
kubectl delete jobs/job-backoff-limit-per-index-failindex
集群会自动清理 Pod。
您可能仅依赖 Pod 回退失败策略,通过指定 Job 的 .spec.backoffLimit 字段来实现。然而,在许多情况下,在设置较低的 .spec.backoffLimit 值以避免不必要的 Pod 重试,与设置足够高以确保 Job 不会被 Pod 中断终止之间找到平衡是困难的。