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

rua*_*zn2 9 jobs wait kubernetes kubectl kubernetes-jobs

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

kubectl wait --for=condition=complete job/myjob
Run Code Online (Sandbox Code Playgroud)

但我认为,只有工作成功,这才行。如果失败,我必须做类似的事情:

kubectl wait --for=condition=failure job/myjob
Run Code Online (Sandbox Code Playgroud)

有没有办法使用wait来等待两个条件?如果没有,等待工作成功或失败的最佳方法是什么?

Seb*_*n N 18

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

kubectl wait --for=condition=complete job/myjob &
completion_pid=$!
Run Code Online (Sandbox Code Playgroud)

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

kubectl wait --for=condition=failed job/myjob && exit 1 &
failure_pid=$! 
Run Code Online (Sandbox Code Playgroud)

然后使用内置的 Bashwait -n $PID1 $PID2等待条件之一成功。该命令将捕获第一个退出进程的退出代码:

wait -n $completion_pid $failure_pid
Run Code Online (Sandbox Code Playgroud)

最后,您可以检查实际退出代码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
Run Code Online (Sandbox Code Playgroud)

完整示例:

# 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
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用“if wait ...”而不是将退出代码存储在变量中。 (2认同)
  • 确保你没有打开“set -e”!否则,如果 failure_pid 获胜,“wait -n”命令将立即退出,并且您将无法获得漂亮的“if”语句日志记录。除此之外,这种方法非常有效 (2认同)

Mar*_*lka 9

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"
Run Code Online (Sandbox Code Playgroud)

您可能需要添加超时以避免无限循环,具体取决于您的情况。


Cla*_*ton 7

You can leverage the behaviour when --timeout=0.

In this scenario, the command line returns immediately with either result code 0 or 1. Here's an example:

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
Run Code Online (Sandbox Code Playgroud)

So when either condition=failed or condition=complete is true, execution will exit the while loop (retval_complete or retval_failed will be 0).

Next, you only need to check and act on the condition you want. In my case, I want to fail fast and stop execution when the job fails.


Dae*_*ark 4

kubectl wait --for=condition=<condition name正在等待特定条件,因此目前无法指定多个条件。

我的解决方法是使用oc get --wait,--wait如果目标资源已更新,则关闭该命令。我将使用直到更新为止来监视status工作的一部分。部分更新意味着作业已完成,但有一些状态条件。oc get --waitstatusstatus

如果作业成功完成,则status.conditions.type立即更新为Complete。但如果作业失败,则作业 pod 将自动重新启动,无论restartPolicyOnFailureNeverFailed但如果没有像第一次更新后那样更新,我们可以认为该作业是状态Complete

看我的测试证据如下。

  • 测试成功完成的作业 yaml
    # vim job.yml
    api版本:batch/v1
    种类:工作
    元数据:
      名称: pi
    规格:
      并行度:1
      完成次数:1
      模板:
        元数据:
          名称: pi
        规格:
          容器:
          - 名称: pi
            图片:perl
            命令:[“perl”,“-wle”,“退出0”]
          重启策略:从不
  • 它将向您显示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 '失败|完成' || 回显“失败”

    job.batch/pi 创建
    地图[开始时间:2019-03-09T12:30:16Z 活跃:1]完成
  • 用于测试的作业 yaml 未能完成
    # vim job.yml
    api版本:batch/v1
    种类:工作
    元数据:
      名称: pi
    规格:
      并行度:1
      完成次数:1
      模板:
        元数据:
          名称: pi
        规格:
          容器:
          - 名称: pi
            图片:perl
            命令:[“perl”、“-wle”、“退出 1”]
          重启策略:从不
  • 它会告诉您Failed第一个工作更新是否不是Complete。删除现有作业资源后测试是否。
    # oc 删除作业 pi
    job.batch“pi”已删除

    # 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 '失败|完成' || 回显“失败”

    job.batch/pi 创建
    地图[活动:1开始时间:2019-03-09T12:31:05Z]失败

我希望它对你有帮助。:)

  • 我最终只是制作了一个简单的脚本来检查您所显示的状态:`until [[ $SECONDS -gt $end ]] || [[ $(kubectl get jobs $job_name -o jsonpath='{.status.conditions[?(@.type=="Failed")].status}') == "True" ]] || [[ $(kubectl get jobs $job_name -o jsonpath='{.status.conditions[?(@.type=="Complete")].status}') == "True" ]]; 做` (5认同)