Подождите, пока задание kubernetes завершится в случае неудачи или успеха с помощью командной строки

Как лучше всего дождаться завершения работы kubernetes? Я заметил много предложений по использованию:

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

но я думаю, что это работает, только если работа успешна. если это не удается, я должен сделать что-то вроде:

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

есть ли способ ожидания обоих условий с помощью wait? если нет, то как лучше всего дождаться, пока работа будет успешной или неудачной?

5 ответов

Решение

kubectl wait --for=condition=<condition name ждет определенного условия, поэтому в afaik он не может указать несколько условий в данный момент.

Мой обходной путь использует oc get --wait, --wait закрывается команда, если целевой ресурс обновлен. Я буду следить status раздел работы с использованием oc get --wait до тех пор status обновляется. Обновление status раздел означает, что задание завершено с некоторыми условиями статуса.

Если работа выполнена успешно, то status.conditions.type обновляется сразу как Complete, Но если работа не удалась, модуль будет автоматически перезапущен независимо от того, restartPolicy является OnFailure или же Never, Но мы можем считать, что работа Failed статус, если не обновлен как Complete после первого обновления.

Посмотрите мои тестовые данные следующим образом.

  • Задание yaml для успешного тестирования завершено
    # vim job.yml
    apiVersion: партия /v1
    вид: работа
    метаданные:
      имя: пи
    спецификация:
      параллелизм: 1
      доработок: 1
      шаблон:
        метаданные:
          имя: пи
        спецификация:
          контейнеры:
          - имя: пи
            изображение: perl
            команда: ["perl",  "-wle", "exit 0"]
          restartPolicy: никогда
  • Это покажет вам 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" 

    job.batch/pi создан
    карта [время начала:2019-03-09T12:30:16Z активна:1] Завершено
  • Задание yaml для тестирования не выполнено
    # vim job.yml
    apiVersion: партия /v1
    вид: работа
    метаданные:
      имя: пи
    спецификация:
      параллелизм: 1
      доработок: 1
      шаблон:
        метаданные:
          имя: пи
        спецификация:
          контейнеры:
          - имя: пи
            изображение: perl
            команда: ["perl",  "-wle", "exit 1"]
          restartPolicy: никогда
  • Это покажет вам Failed если первое обновление вакансии не Complete, Проверьте, если после удаления существующего ресурса задания.
    # oc удалить задание pi
    job.batch "пи" удален

    # 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" 

    job.batch/pi создан
    map[active:1 startTime:2019-03-09T12:31:05Z] Не удалось

Я надеюсь, что это поможет вам.:)

Выполните первое условие ожидания как подпроцесс и запишите его 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

Вы можете использовать поведение, когда --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

В 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"

Вы можете добавить тайм-аут, чтобы избежать бесконечного цикла, в зависимости от вашей ситуации.

Вы можете использовать следующий обходной путь, используяkubectl logs --follow:

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

Он завершится, когда ваша работа завершится, с любым статусом.

Другие вопросы по тегам