This is a stable feature in Kubernetes, and has been since the 1.31 release. You can no longer toggle this feature (the associated feature gate has been removed).
У цьому документі показано, як використовувати політику збоїв Podʼа разом зі стандартною політикою backoff для збоїв Podʼа, щоб краще контролювати обробку збоїв на рівні контейнера або Podʼа в межах Job.
Визначення політики збоїв Podʼа може допомогти:
Ви вже маєте знати основи використання Job.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.25.Для перевірки версії введіть kubectl version.
Розгляньмо такі сценарії використання для Jobs, які визначають політику збоїв Podʼа:
У наведеному нижче прикладі ви дізнаєтеся, як використовувати політику збоїв Podʼа, щоб уникати непотрібних перезапусків Podʼів, коли збій Podʼа вказує на програмну помилку, яку неможливо усунути повторною спробою.
Перегляньте наведений нижче маніфест:
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-failjob
spec:
completions: 8
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"]
args:
- -c
- echo "Hello world! I'm going to exit with 42 to simulate a software bug." && sleep 30 && exit 42
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onExitCodes:
containerName: main
operator: In
values: [42]
Застосуйте маніфест:
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-failjob.yaml
Приблизно через 30 секунд весь Job має завершитися. Перевірте статус Job, виконавши команду:
kubectl get jobs -l job-name=job-pod-failure-policy-failjob -o yaml
У статусі Job відображаються такі стани:
FailureTarget: має поле reason зі значенням PodFailurePolicy і поле message з додатковою інформацією про завершення, наприклад Container main for pod default/job-pod-failure-policy-failjob-8ckj8 failed with exit code 42 matching FailJob rule at index 0. Контролер Job додає цей стан, щойно Job вважається невдалим. Докладніше дивіться Завершення Podʼів Job.Failed: ті самі reason і message, що й у стану FailureTarget. Контролер Job додає цей стан після завершення всіх Podʼів Job.Для порівняння: якби політику збоїв Podʼа було вимкнено, Job повторював би спроби до досягнення backoffLimit (6 збоїв). Оскільки повторні спроби використовують експоненційний backoff, а з parallelism: 2 збої відбуваються парами, затримка між спробами зростає з кожною спробою. У результаті в цьому прикладі мало б минути щонайменше 9 хвилин, перш ніж Job зазнає збою.
Видаліть створений Job:
kubectl delete jobs/job-pod-failure-policy-failjob
Кластер автоматично очищає Podʼи.
У наведеному нижче прикладі ви дізнаєтеся, як за допомогою політики збоїв Podʼа зробити так, щоб порушення роботи Podʼів не збільшували лічильник повторних спроб Podʼа в межах .spec.backoffLimit.
Перегляньте наведений нижче маніфест:
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-ignore
spec:
completions: 4
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"]
args:
- -c
- echo "Hello world! I'm going to exit with 0 (success)." && sleep 90 && exit 0
backoffLimit: 0
podFailurePolicy:
rules:
- action: Ignore
onPodConditions:
- type: DisruptionTarget
Застосуйте маніфест:
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-ignore.yaml
Виконайте цю команду, щоб перевірити nodeName, на який заплановано Pod:
nodeName=$(kubectl get pods -l job-name=job-pod-failure-policy-ignore -o jsonpath='{.items[0].spec.nodeName}')
Виконайте drain вузла, щоб виселити Pod до його завершення (протягом 90 секунд):
kubectl drain nodes/$nodeName --ignore-daemonsets --grace-period=0
Перевірте .status.failed, щоб переконатися, що лічильник для Job не збільшено:
kubectl get jobs -l job-name=job-pod-failure-policy-ignore -o yaml
Виконайте uncordon вузла:
kubectl uncordon nodes/$nodeName
Job відновлюється й завершується успішно.
Для порівняння: якби політику збоїв Podʼа було вимкнено, порушення роботи Podʼа призвело б до завершення всього Job (оскільки .spec.backoffLimit дорівнює 0).
Видаліть створений Job:
kubectl delete jobs/job-pod-failure-policy-ignore
Кластер автоматично очищає Podʼи.
У наведеному нижче прикладі ви дізнаєтеся, як використовувати політику збоїв Podʼа, щоб уникати непотрібних перезапусків Podʼів на основі власних станів Podʼа.
Pending до термінальної фази (дивіться Фаза Podʼа).Перегляньте наведений нижче маніфест:
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-config-issue
spec:
completions: 8
parallelism: 2
template:
spec:
restartPolicy: Never
containers:
- name: main
image: "non-existing-repo/non-existing-image:example"
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onPodConditions:
- type: ConfigIssue
Застосуйте маніфест:
kubectl create -f https://k8s.io/examples/controllers/job-pod-failure-policy-config-issue.yaml
Зверніть увагу, що образ налаштовано неправильно, оскільки його не існує.
Перевірте статус Podʼів Job, виконавши команду:
kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o yaml
Ви побачите вивід, подібний до такого:
containerStatuses:
- image: non-existing-repo/non-existing-image:example
...
state:
waiting:
message: Back-off pulling image "non-existing-repo/non-existing-image:example"
reason: ImagePullBackOff
...
phase: Pending
Зверніть увагу, що Pod лишається у фазі Pending, оскільки не може завантажити неправильно налаштований образ. Це, в принципі, могло б бути тимчасовою проблемою, і образ міг би завантажитися. Однак у цьому випадку образу не існує, тому ми вказуємо на це за допомогою власного стану.
Додайте власний стан. Спочатку підготуйте патч, виконавши команду:
cat <<EOF > patch.yaml
status:
conditions:
- type: ConfigIssue
status: "True"
reason: "NonExistingImage"
lastTransitionTime: "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
EOF
По-друге, виберіть один із Podʼів, створених Job, виконавши команду:
podName=$(kubectl get pods -l job-name=job-pod-failure-policy-config-issue -o jsonpath='{.items[0].metadata.name}')
Потім застосуйте патч до одного з Podʼів, виконавши таку команду:
kubectl patch pod $podName --subresource=status --patch-file=patch.yaml
Якщо патч успішно застосовано, ви отримаєте повідомлення такого типу:
pod/job-pod-failure-policy-config-issue-k6pvp patched
Видаліть Pod, щоб перевести його у фазу Failed, виконавши команду:
kubectl delete pods/$podName
Перевірте статус Job, виконавши:
kubectl get jobs -l job-name=job-pod-failure-policy-config-issue -o yaml
У статусі Job ви побачите стан Failed з полем reason, що дорівнює PodFailurePolicy. Крім того, поле message містить докладнішу інформацію про завершення Job, наприклад Pod default/job-pod-failure-policy-config-issue-k6pvp has condition ConfigIssue matching FailJob rule at index 0.
Видаліть створений Job:
kubectl delete jobs/job-pod-failure-policy-config-issue
Кластер автоматично очищає Podʼи.
Щоб уникнути непотрібних перезапусків Podʼів для кожного індексу, можна використовувати можливості політика збоїв Podʼа й обмеження backoff на індекс. У цьому розділі сторінки показано, як використовувати ці можливості разом.
Перегляньте наведений нижче маніфест:
apiVersion: batch/v1
kind: Job
metadata:
name: job-backoff-limit-per-index-failindex
spec:
completions: 4
parallelism: 2
completionMode: Indexed
backoffLimitPerIndex: 1
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/python:3
command:
# The script:
# - fails the Pod with index 0 with exit code 1, which results in one retry;
# - fails the Pod with index 1 with exit code 42 which results
# in failing the index without retry.
# - succeeds Pods with any other index.
- python3
- -c
- |
import os, sys
index = int(os.environ.get("JOB_COMPLETION_INDEX"))
if index == 0:
sys.exit(1)
elif index == 1:
sys.exit(42)
else:
sys.exit(0)
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailIndex
onExitCodes:
containerName: main
operator: In
values: [42]
Застосуйте маніфест:
kubectl create -f https://k8s.io/examples/controllers/job-backoff-limit-per-index-failindex.yaml
Приблизно через 15 секунд перевірте стан Podʼів для Job. Ви можете зробити це, виконавши команду:
kubectl get pods -l job-name=job-backoff-limit-per-index-failindex -o yaml
Ви побачите вивід, подібний до такого:
NAME READY STATUS RESTARTS AGE
job-backoff-limit-per-index-failindex-0-4g4cm 0/1 Error 0 4s
job-backoff-limit-per-index-failindex-0-fkdzq 0/1 Error 0 15s
job-backoff-limit-per-index-failindex-1-2bgdj 0/1 Error 0 15s
job-backoff-limit-per-index-failindex-2-vs6lt 0/1 Completed 0 11s
job-backoff-limit-per-index-failindex-3-s7s47 0/1 Completed 0 6s
Зверніть увагу, що вивід показує таке:
FailIndex.Перевірте статус Job, виконавши:
kubectl get jobs -l job-name=job-backoff-limit-per-index-failindex -o yaml
У статусі Job поле failedIndexes показує "0,1", оскільки обидва індекси зазнали збою. Оскільки індекс 1 не повторювався, кількість збійних Podʼів, вказана в полі статусу "failed", дорівнює 3.
Видаліть створений Job:
kubectl delete jobs/job-backoff-limit-per-index-failindex
Кластер автоматично очищає Podʼи.
Ви можете покладатися лише на політику backoff для збоїв Podʼа, вказавши поле .spec.backoffLimit у Job. Однак у багатьох ситуаціях важко знайти баланс: значення .spec.backoffLimit має бути достатньо низьким, щоб уникати непотрібних повторних спроб Podʼів, але достатньо високим, щоб Job не завершувався через порушення роботи Podʼів.