使用命令行等待 kubernetes 作业在 failure/success 上完成
Wait for kubernetes job to complete on either failure/success using command line
等待 kubernetes 作业完成的最佳方法是什么?我注意到很多使用建议:
kubectl wait --for=condition=complete job/myjob
但我认为只有在工作成功时才有效。如果失败,我必须做类似的事情:
kubectl wait --for=condition=failure job/myjob
有没有办法使用 wait 来等待这两个条件?如果没有,等待工作成功或失败的最佳方式是什么?
kubectl wait --for=condition=<condition name
正在等待特定条件,所以 afaik 目前无法指定多个条件。
我的解决方法是使用 oc get --wait
,如果目标资源已更新,--wait
将关闭命令。我将使用 oc get --wait
监视作业的 status
部分,直到 status
更新。 status
部分的更新意味着作业已完成并具有某些状态条件。
如果作业成功完成,则 status.conditions.type
会立即更新为 Complete
。但是,如果作业失败,那么无论 restartPolicy
是 OnFailure
还是 Never
,作业 pod 都会自动重启。但是我们可以认为作业是 Failed
状态,如果在第一次更新后没有更新为 Complete
。
看我的测试证据如下
- 用于测试成功完成的作业 yaml
# vim job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 1
completions: 1
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-wle", "exit 0"]
restartPolicy: Never
- 如果它成功完成作业,它将显示
Complete
。
# oc create -f job.yml &&
oc get job/pi -o=jsonpath='{.status}' -w &&
oc get job/pi -o=jsonpath='{.status.conditions[*].type}' | grep -i -E 'failed|complete' || echo "Failed"
job.batch/pi created
map[startTime:2019-03-09T12:30:16Z active:1]Complete
- 用于测试的作业 yaml 未能完成
# vim job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 1
completions: 1
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-wle", "exit 1"]
restartPolicy: Never
- 如果第一个作业更新不是
Complete
,它将显示 Failed
。测试是否在删除现有作业资源后。
# oc delete job pi
job.batch "pi" deleted
# oc create -f job.yml &&
oc get job/pi -o=jsonpath='{.status}' -w &&
oc get job/pi -o=jsonpath='{.status.conditions[*].type}' | grep -i -E 'failed|complete' || echo "Failed"
job.batch/pi created
map[active:1 startTime:2019-03-09T12:31:05Z]Failed
希望对你有所帮助。 :)
运行 将第一个等待条件作为子进程并捕获其PID。如果满足条件,此进程将退出,退出代码为 0。
kubectl wait --for=condition=complete job/myjob &
completion_pid=$!
对失败等待条件做同样的事情。这里的技巧是添加 && exit 1
以便子进程 returns 作业失败时的非零退出代码。
kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$!
然后使用Bash内置函数wait -n $PID1 $PID2
等待其中一个条件成功。该命令将捕获第一个退出的进程的退出代码:
wait -n $completion_pid $failure_pid
最后,您可以检查 wait -n
的实际退出代码以查看作业是否失败:
exit_code=$?
if (( $exit_code == 0 )); then
echo "Job completed"
else
echo "Job failed with exit code ${exit_code}, exiting..."
fi
exit $exit_code
完整示例:
# wait for completion as background process - capture PID
kubectl wait --for=condition=complete job/myjob &
completion_pid=$!
# wait for failure as background process - capture PID
kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$!
# capture exit code of the first subprocess to exit
wait -n $completion_pid $failure_pid
# store exit code in variable
exit_code=$?
if (( $exit_code == 0 )); then
echo "Job completed"
else
echo "Job failed with exit code ${exit_code}, exiting..."
fi
exit $exit_code
您可以利用 --timeout=0
时的行为。
在这种情况下,命令行 returns 立即显示结果代码 0 或 1。这是一个示例:
retval_complete=1
retval_failed=1
while [[ $retval_complete -ne 0 ]] && [[ $retval_failed -ne 0 ]]; do
sleep 5
output=$(kubectl wait --for=condition=failed job/job-name --timeout=0 2>&1)
retval_failed=$?
output=$(kubectl wait --for=condition=complete job/job-name --timeout=0 2>&1)
retval_complete=$?
done
if [ $retval_failed -eq 0 ]; then
echo "Job failed. Please check logs."
exit 1
fi
因此,当 condition=failed
或 condition=complete
为真时,执行将退出 while 循环(retval_complete
或 retval_failed
将为 0
)。
接下来,您只需要检查并根据您想要的条件进行操作即可。就我而言,我想快速失败并在作业失败时停止执行。
wait -n
方法对我不起作用,因为我需要它同时适用于 Linux 和 Mac。
我对 Clayton 提供的答案做了一点改进,因为他的脚本在启用 set -e -E
的情况下无法运行。即使在这种情况下,以下内容也能正常工作。
while true; do
if kubectl wait --for=condition=complete --timeout=0 job/name 2>/dev/null; then
job_result=0
break
fi
if kubectl wait --for=condition=failed --timeout=0 job/name 2>/dev/null; then
job_result=1
break
fi
sleep 3
done
if [[ $job_result -eq 1 ]]; then
echo "Job failed!"
exit 1
fi
echo "Job succeeded"
您可能想要添加超时以避免无限循环,具体取决于您的情况。
等待 kubernetes 作业完成的最佳方法是什么?我注意到很多使用建议:
kubectl wait --for=condition=complete job/myjob
但我认为只有在工作成功时才有效。如果失败,我必须做类似的事情:
kubectl wait --for=condition=failure job/myjob
有没有办法使用 wait 来等待这两个条件?如果没有,等待工作成功或失败的最佳方式是什么?
kubectl wait --for=condition=<condition name
正在等待特定条件,所以 afaik 目前无法指定多个条件。
我的解决方法是使用 oc get --wait
,如果目标资源已更新,--wait
将关闭命令。我将使用 oc get --wait
监视作业的 status
部分,直到 status
更新。 status
部分的更新意味着作业已完成并具有某些状态条件。
如果作业成功完成,则 status.conditions.type
会立即更新为 Complete
。但是,如果作业失败,那么无论 restartPolicy
是 OnFailure
还是 Never
,作业 pod 都会自动重启。但是我们可以认为作业是 Failed
状态,如果在第一次更新后没有更新为 Complete
。
看我的测试证据如下
- 用于测试成功完成的作业 yaml
# vim job.yml apiVersion: batch/v1 kind: Job metadata: name: pi spec: parallelism: 1 completions: 1 template: metadata: name: pi spec: containers: - name: pi image: perl command: ["perl", "-wle", "exit 0"] restartPolicy: Never
- 如果它成功完成作业,它将显示
Complete
。
# oc create -f job.yml && oc get job/pi -o=jsonpath='{.status}' -w && oc get job/pi -o=jsonpath='{.status.conditions[*].type}' | grep -i -E 'failed|complete' || echo "Failed" job.batch/pi created map[startTime:2019-03-09T12:30:16Z active:1]Complete
- 用于测试的作业 yaml 未能完成
# vim job.yml apiVersion: batch/v1 kind: Job metadata: name: pi spec: parallelism: 1 completions: 1 template: metadata: name: pi spec: containers: - name: pi image: perl command: ["perl", "-wle", "exit 1"] restartPolicy: Never
- 如果第一个作业更新不是
Complete
,它将显示Failed
。测试是否在删除现有作业资源后。
# oc delete job pi job.batch "pi" deleted # oc create -f job.yml && oc get job/pi -o=jsonpath='{.status}' -w && oc get job/pi -o=jsonpath='{.status.conditions[*].type}' | grep -i -E 'failed|complete' || echo "Failed" job.batch/pi created map[active:1 startTime:2019-03-09T12:31:05Z]Failed
希望对你有所帮助。 :)
运行 将第一个等待条件作为子进程并捕获其PID。如果满足条件,此进程将退出,退出代码为 0。
kubectl wait --for=condition=complete job/myjob &
completion_pid=$!
对失败等待条件做同样的事情。这里的技巧是添加 && exit 1
以便子进程 returns 作业失败时的非零退出代码。
kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$!
然后使用Bash内置函数wait -n $PID1 $PID2
等待其中一个条件成功。该命令将捕获第一个退出的进程的退出代码:
wait -n $completion_pid $failure_pid
最后,您可以检查 wait -n
的实际退出代码以查看作业是否失败:
exit_code=$?
if (( $exit_code == 0 )); then
echo "Job completed"
else
echo "Job failed with exit code ${exit_code}, exiting..."
fi
exit $exit_code
完整示例:
# wait for completion as background process - capture PID
kubectl wait --for=condition=complete job/myjob &
completion_pid=$!
# wait for failure as background process - capture PID
kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$!
# capture exit code of the first subprocess to exit
wait -n $completion_pid $failure_pid
# store exit code in variable
exit_code=$?
if (( $exit_code == 0 )); then
echo "Job completed"
else
echo "Job failed with exit code ${exit_code}, exiting..."
fi
exit $exit_code
您可以利用 --timeout=0
时的行为。
在这种情况下,命令行 returns 立即显示结果代码 0 或 1。这是一个示例:
retval_complete=1
retval_failed=1
while [[ $retval_complete -ne 0 ]] && [[ $retval_failed -ne 0 ]]; do
sleep 5
output=$(kubectl wait --for=condition=failed job/job-name --timeout=0 2>&1)
retval_failed=$?
output=$(kubectl wait --for=condition=complete job/job-name --timeout=0 2>&1)
retval_complete=$?
done
if [ $retval_failed -eq 0 ]; then
echo "Job failed. Please check logs."
exit 1
fi
因此,当 condition=failed
或 condition=complete
为真时,执行将退出 while 循环(retval_complete
或 retval_failed
将为 0
)。
接下来,您只需要检查并根据您想要的条件进行操作即可。就我而言,我想快速失败并在作业失败时停止执行。
wait -n
方法对我不起作用,因为我需要它同时适用于 Linux 和 Mac。
我对 Clayton 提供的答案做了一点改进,因为他的脚本在启用 set -e -E
的情况下无法运行。即使在这种情况下,以下内容也能正常工作。
while true; do
if kubectl wait --for=condition=complete --timeout=0 job/name 2>/dev/null; then
job_result=0
break
fi
if kubectl wait --for=condition=failed --timeout=0 job/name 2>/dev/null; then
job_result=1
break
fi
sleep 3
done
if [[ $job_result -eq 1 ]]; then
echo "Job failed!"
exit 1
fi
echo "Job succeeded"
您可能想要添加超时以避免无限循环,具体取决于您的情况。