31

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

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

但我认为只有在工作成功的情况下才有效。如果失败,我必须执行以下操作:

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

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

4

4 回答 4

25

将第一个等待条件作为子进程运行并捕获其 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等待条件之一成功。该命令将捕获要退出的第一个进程的退出代码:

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
于 2020-02-18T17:35:57.543 回答
7

您可以在--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=failedorcondition=complete为真时,执行将退出 while 循环(retval_completeor retval_failedwill be 0)。

接下来,您只需要检查并根据您想要的条件采取行动。就我而言,我想快速失败并在作业失败时停止执行。

于 2020-08-28T11:24:11.143 回答
6

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"

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

于 2021-03-17T15:39:28.747 回答
3

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

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

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

看我的测试证据如下。

  • 用于测试成功完成的作业 yaml
    # vim 工作.yml
    api版本:批处理/v1
    种类:工作
    元数据:
      名称:pi
    规格:
      并行度:1
      完成:1
      模板:
        元数据:
          名称:pi
        规格:
          容器:
          - 名称:pi
            图片:perl
            命令:["perl", "-w​​le", "exit 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 创建
    map[startTime:2019-03-09T12:30:16Z active:1]完成
  • 用于测试的作业 yaml 失败完成
    # vim 工作.yml
    api版本:批处理/v1
    种类:工作
    元数据:
      名称:pi
    规格:
      并行度:1
      完成:1
      模板:
        元数据:
          名称:pi
        规格:
          容器:
          - 名称:pi
            图片:perl
            命令:["perl", "-w​​le", "exit 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]失败

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

于 2019-03-09T13:39:27.633 回答