使用命令行等待kubernetes作业在失败/成功时完成

3qpi33ja  于 2022-11-02  发布在  Kubernetes
关注(0)|答案(5)|浏览(142)

等待kubernetes作业完成的最好方法是什么?我注意到很多建议可以用途:

kubectl wait --for=condition=complete job/myjob

不过,我认为只有在工作成功的情况下,才可以这样做;如果工作失败,我便要这样做:

kubectl wait --for=condition=failed job/myjob

是否有一种方法可以使用wait同时等待这两种情况?如果没有,等待作业成功或失败的最佳方法是什么?

e5nszbig

e5nszbig1#

将第一个等待条件作为子进程运行并捕获其PID。如果满足该条件,则此进程将退出,退出代码为0。

kubectl wait --for=condition=complete job/myjob &
completion_pid=$!

对失败等待条件执行同样的操作。这里的技巧是添加&& exit 1,以便当作业失败时,子进程返回一个非零的退出代码。

kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$!

然后使用内置的Bash wait -n $PID1 $PID2等待其中一个条件成功。该命令将捕获第一个要退出的进程的退出代码:
Mac用户!请注意wait -n [...PID]需要Bash 4.3或更高版本。由于许可证问题,MacOS永远停留在3.2版本。请参阅此Stackoverflow Post以了解如何安装最新版本。

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
w6mmgewl

w6mmgewl2#

--timeout=0时,您可以利用该行为。
在这种情况下,命令行会立即返回结果代码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=failedcondition=complete为真时,执行将退出while循环(retval_completeretval_failed将为0)。
接下来,您只需要检查并根据您希望的条件采取行动。在我的情况下,我希望快速失败,并在作业失败时停止执行。

9w11ddsr

9w11ddsr3#

wait -n方法对我不起作用,因为我需要它在Linux和Mac上都能工作。
我对克莱顿提供的答案做了一些改进,因为他的脚本在启用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"

您可能希望添加超时以避免无限循环,这取决于您的情况。

omtl5h9j

omtl5h9j4#

kubectl wait --for=condition=<condition name正在等待一个特定的条件,因此afaik此时不能指定多个条件。
我的解决方法是使用oc get --wait,如果更新了目标资源,--wait将关闭该命令。我将使用oc get --wait监视作业的status部分,直到更新了status。更新status部分意味着作业已完成,但存在一些状态条件。
如果作业成功完成,则status.conditions.type会立即更新为Complete。但如果作业失败,则无论restartPolicyOnFailure还是Never,作业Pod都会自动重新启动。但如果在第一次更新后未更新为Complete,则可以认为作业处于Failed状态。
看我的测试证据如下。

  • 成功完成测试的任务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

我希望这对你有帮助

prdp8dxp

prdp8dxp5#

您可以使用kubectl logs --follow使用下列解决方法:

kubectl wait --for=condition=ready pod --selector=job-name=YOUR_JOB_NAME --timeout=-1s
kubectl logs --follow job/YOUR_JOB_NAME

它将在作业终止时终止,无论状态如何。

相关问题