Job
Завдання (Job) створює один або кілька Podʼів і буде продовжувати повторювати виконання Podʼів, доки не буде досягнуто вказану кількість успішних завершень. При успішному завершенні Podʼів завдання відстежує ці успішні завершення. Коли досягнута вказана кількість успішних завершень, завдання (тобто Job) завершується. Видалення завдання буде видаляти Podʼи, які воно створило. При призупиненні завдання буде видаляти активні Podʼи, доки завдання знову не буде відновлене.
У простому випадку можна створити один обʼєкт Job для надійного запуску одного Podʼа до завершення. Обʼєкт Job буде запускати новий Pod, якщо перший Pod зазнає невдачі або видаляється (наприклад, через відмову апаратного забезпечення вузла або перезавантаження вузла).
Також можна використовувати Job для запуску кількох Podʼів паралельно.
Якщо ви хочете запустити завдання (або одне завдання, або декілька паралельно) за розкладом, див. CronJob.
Запуск прикладу Job
Ось конфігурація прикладу Job. Тут обчислюється число π з точністю до 2000 знаків і виконується його вивід. Виконання зазвичай займає близько 10 секунд.
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
Ви можете запустити цей приклад за допомогою наступної команди:
kubectl apply -f https://kubernetes.io/examples/controllers/job.yaml
Вивід буде схожим на це:
job.batch/pi created
Перевірте статус Job за допомогою kubectl
:
Name: pi
Namespace: default
Selector: batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
Labels: batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
batch.kubernetes.io/job-name=pi
...
Annotations: batch.kubernetes.io/job-tracking: ""
Parallelism: 1
Completions: 1
Start Time: Mon, 02 Dec 2019 15:20:11 +0200
Completed At: Mon, 02 Dec 2019 15:21:16 +0200
Duration: 65s
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
Pod Template:
Labels: batch.kubernetes.io/controller-uid=c9948307-e56d-4b5d-8302-ae2d7b7da67c
batch.kubernetes.io/job-name=pi
Containers:
pi:
Image: perl:5.34.0
Port: <none>
Host Port: <none>
Command:
perl
-Mbignum=bpi
-wle
print bpi(2000)
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 21s job-controller Created pod: pi-xf9p4
Normal Completed 18s job-controller Job completed
apiVersion: batch/v1
kind: Job
metadata:
annotations: batch.kubernetes.io/job-tracking: ""
...
creationTimestamp: "2022-11-10T17:53:53Z"
generation: 1
labels:
batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
batch.kubernetes.io/job-name: pi
name: pi
namespace: default
resourceVersion: "4751"
uid: 204fb678-040b-497f-9266-35ffa8716d14
spec:
backoffLimit: 4
completionMode: NonIndexed
completions: 1
parallelism: 1
selector:
matchLabels:
batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
suspend: false
template:
metadata:
creationTimestamp: null
labels:
batch.kubernetes.io/controller-uid: 863452e6-270d-420e-9b94-53a54146c223
batch.kubernetes.io/job-name: pi
spec:
containers:
- command:
- perl
- -Mbignum=bpi
- -wle
- print bpi(2000)
image: perl:5.34.0
imagePullPolicy: IfNotPresent
name: pi
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
active: 1
ready: 0
startTime: "2022-11-10T17:53:57Z"
uncountedTerminatedPods: {}
Щоб переглянути завершені Podʼи Job, використовуйте kubectl get pods
.
Щоб вивести всі Podʼи, які належать Job у машинночитаній формі, ви можете використовувати таку команду:
pods=$(kubectl get pods --selector=batch.kubernetes.io/job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods
Вивід буде схожим на це:
pi-5rwd7
Тут, селектор збігається з селектором, який використовується в Job. Параметр --output=jsonpath
зазначає вираз з назвою з кожного Pod зі списку.
kubectl logs $pods
Іншим варіантом є використання kubectl logs
для виводу логів з кожного Pod.
kubectl logs job/pi
Вивід буде схожим на це:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
Створення опису Job
Як і з будь-якою іншою конфігурацією Kubernetes, у Job мають бути вказані поля apiVersion
, kind
та metadata
.
При створенні панеллю управління нових Podʼів для Job, поле .metadata.name
Job є частиною основи для надання імен цим Podʼам. Імʼя Job повинно бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності імʼя повинно відповідати більш обмеженим правилам для DNS-мітки. Навіть якщо імʼя є DNS-піддоменом, імʼя повинно бути не довше 63 символів.
Також у Job повинен бути розділ .spec
.
Мітки для Job
Мітки Job повинні мати префікс batch.kubernetes.io/
для job-name
та controller-uid
.
Шаблон Podʼа
.spec.template
— єдине обовʼязкове поле .spec
.
.spec.template
— це шаблон Podʼа. Він має точно таку ж схему, як Pod, окрім того, що він вкладений і не має apiVersion
чи kind
.
Окрім обовʼязкових полів для Podʼа , шаблон Podʼа в Job повинен вказати відповідні мітки (див. селектор Podʼа) та відповідну політику перезапуску.
Дозволяється лише RestartPolicy
, рівний Never
або OnFailure
.
Селектор Podʼа
Поле .spec.selector
є необовʼязковим. У майже всіх випадках ви не повинні його вказувати. Дивіться розділ вказування вашого власного селектора Podʼа.
Паралельне виконання для Jobs
Існують три основних типи завдань, які підходять для виконання в якості Job:
Непаралельні Jobs
- зазвичай запускається лише один Pod, якщо Pod не вдається.
- Job завершується, як тільки його Pod завершується успішно.
Паралельні Jobs із фіксованою кількістю завершень
- вкажіть ненульове позитивне значення для
.spec.completions
. - Job являє собою загальне завдання і завершується, коли є
.spec.completions
успішних Podʼів. - при використанні
.spec.completionMode="Indexed"
, кожен Pod отримує різний індекс у діапазоні від 0 до.spec.completions-1
.
- вкажіть ненульове позитивне значення для
Паралельні Jobs із чергою завдань
- не вказуйте
.spec.completions
, типово встановлюється.spec.parallelism
. - Podʼи повинні координувати серед себе або зовнішній сервіс для визначення над чим кожен з них має працювати. Наприклад, Pod може отримати набір з N елементів з черги завдань.
- кожен Pod може незалежно визначити, чи завершилися всі його партнери, і, таким чином, що весь Job завершений.
- коли будь-який Pod з Job завершується успішно, нові Podʼи не створюються.
- як тільки хоча б один Pod завершився успішно і всі Podʼи завершені, тоді Job завершується успішно.
- як тільки будь-який Pod завершився успішно, жоден інший Pod не повинен виконувати роботу для цього завдання чи записувати будь-який вивід. Вони всі мають бути в процесі завершення.
- не вказуйте
Для непаралельного Job ви можете залишити як .spec.completions
, так і .spec.parallelism
не встановленими. Коли обидва не встановлені, обидва типово встановлюються на 1.
Для Job із фіксованою кількістю завершень вам слід встановити .spec.completions
на кількість необхідних завершень. Ви можете встановити .spec.parallelism
чи залишити його не встановленим, і він буде встановлено типово на 1.
Для Job із чергою завдань ви повинні залишити .spec.completions
не встановленим і встановити .spec.parallelism
на не відʼємне ціле число.
За докладною інформацією про використання різних типів Job, див. розділ патерни Job.
Контроль паралелізму
Запитаний паралелізм (.spec.parallelism
) може бути встановлений на будь-яке не відʼємне значення. Якщо значення не вказано, стандартно воно дорівнює 1. Якщо вказано як 0, то Job ефективно призупинено до тих пір, поки воно не буде збільшене.
Фактична паралельність (кількість Podʼів, які працюють в будь-який момент) може бути більше чи менше, ніж запитаний паралелізм, з різних причин:
- Для Job із фіксованою кількістю завершень, фактична кількість Podʼів, які працюють паралельно, не буде перевищувати кількість залишених завершень. Значення
.spec.parallelism
більше чи менше ігнорується. - Для Job із чергою завдань, жоден новий Pod не запускається після успішного завершення будь-якого Podʼа — залишені Podʼи мають право завершити роботу.
- Якщо у контролера Job не було часу відреагувати.
- Якщо контролер Job не зміг створити Podʼи з будь-якої причини (нестача
ResourceQuota
, відсутність дозволу і т.д.), тоді може бути менше Podʼів, ніж запитано. - Контролер Job може обмежувати створення нових Podʼів через ексцесивні попередні відмови Podʼів у цьому ж Job.
- Коли Pod завершується відповідним чином, на його зупинку потрібен час.
Режим завершення
Kubernetes v1.24 [stable]
Для завдань з фіксованою кількістю завершень — тобто завдань, які мають не нульове .spec.completions
— може бути встановлено режим завершення, який вказується в .spec.completionMode
:
NonIndexed
(стандартно): завдання вважається завершеним, коли є.spec.completions
успішно завершених Podʼів. Іншими словами, завершення кожного Podʼа гомологічне одне одному. Зверніть увагу, що завдання, у яких.spec.completions
дорівнює null, неявно єNonIndexed
.Indexed
: Podʼи завдання отримують асоційований індекс завершення від 0 до.spec.completions-1
. Індекс доступний через чотири механізми:- Анотація Podʼа
batch.kubernetes.io/job-completion-index
. - Мітка Podʼа
batch.kubernetes.io/job-completion-index
(для v1.28 і новіших). Зверніть увагу, що для використання цієї мітки механізм feature gatePodIndexLabel
повинен бути увімкнений, і він є типово увімкненим. - Як частина імені хоста Podʼа, за шаблоном
$(job-name)-$(index)
. Коли ви використовуєте Індексоване Завдання у поєднанні з Service, Podʼи всередині завдання можуть використовувати детерміністичні імена хостів для адресації одне одного через DNS. Докладні відомості щодо того, як налаштувати це, див. Завдання з комунікацією від Podʼа до Podʼа. - З контейнера завдання, в змінній середовища
JOB_COMPLETION_INDEX
.
Завдання вважається завершеним, коли є успішно завершений Pod для кожного індексу. Докладні відомості щодо того, як використовувати цей режим, див. Індексоване завдання для паралельної обробки зі статичним призначенням роботи.
- Анотація Podʼа
Примітка:
Хоча це і рідко, може бути запущено більше одного Podʼа для одного і того ж індексу (з різних причин, таких як відмови вузла, перезапуски kubelet чи виселення Podʼа). У цьому випадку лише перший успішно завершений Pod буде враховуватися при підрахунку кількості завершень та оновленні статусу завдання. Інші Podʼи, які працюють чи завершили роботу для того ж самого індексу, будуть видалені контролером завдання, як тільки він їх виявлять.Обробка відмов Podʼа та контейнера
Контейнер у Podʼі може вийти з ладу з ряду причин, таких як завершення процесу з ненульовим кодом виходу або примусове припинення роботи контейнера через перевищення ліміту памʼяті та таке інше. Якщо це стається і .spec.template.spec.restartPolicy = "OnFailure"
, тоді Pod залишається на вузлі, але контейнер перезапускається. Отже, ваш застосунок повинен обробляти випадок, коли він
перезапускається локально, або вказувати .spec.template.spec.restartPolicy = "Never"
. Докладні відомості про restartPolicy
див. в розділі життєвий цикл Podʼа.
Весь Pod також може вийти з ладу з ряду причин, таких як коли Pod видаляється з вузла (вузол оновлюється, перезавантажується, видаляється тощо), або якщо контейнер Podʼа виходить з ладу і .spec.template.spec.restartPolicy = "Never"
. Коли Pod виходить з ладу, контролер завдання запускає новий Pod. Це означає, що ваш застосунок повинен обробляти випадок, коли він перезапускається у новому
Podʼі. Зокрема, він повинен обробляти тимчасові файли, блокування, неповний вивід та інше, викликане попередніми запусками.
Типово кожна відмова Podʼа враховується в ліміті .spec.backoffLimit
, див. політика відмови Podʼа. Однак ви можете налаштовувати обробку відмов Podʼа, встановлюючи [політику відмови Podʼа] (#pod-failure-policy) для завдання.
Додатково ви можете вирішити враховувати відмови Podʼа незалежно для кожного індексу в Індексованому Завданні, встановлюючи поле .spec.backoffLimitPerIndex
(докладні відомості див. ліміт затримки на індекс).
Зверніть увагу, що навіть якщо ви вказали .spec.parallelism = 1
і .spec.completions = 1
і .spec.template.spec.restartPolicy = "Never"
, той самий програмний код може іноді бути запущений двічі.
Якщо ви вказали як .spec.parallelism
, так і .spec.completions
більше ніж 1, то може бути запущено кілька Podʼів одночасно. Таким чином, ваші Podʼи також повинні бути стійкими до конкурентності.
Якщо ви вказуєте поле .spec.podFailurePolicy
, контролер Job не вважає Pod, який перебуває у стані завершення (Pod з встановленим полем .metadata.deletionTimestamp
), за помилку до того, як Pod стане термінальним (його .status.phase
є Failed
або Succeeded
). Однак контролер Job створює замінний Pod, як тільки стає очевидним, що Pod перебуває в процесі завершення. Після того як Pod завершиться, контролер Job оцінює .backoffLimit
і .podFailurePolicy
для відповідного Job, враховуючи тепер уже завершений Pod.
Якщо хоча б одна з цих вимог не виконана, контролер завдання рахує завершення Podʼа негайною відмовою, навіть якщо цей Pod пізніше завершить фазою "Succeeded"
.
Політика backoff відмови Podʼа
Є ситуації, коли ви хочете щоб завдання зазнало збою після певної кількості спроб
через логічну помилку в конфігурації тощо. Для цього встановіть .spec.backoffLimit
, щоб вказати кількість спроб перед тим, як вважати завдання таким, що не вдалось. Ліміт затримки стандартно встановлено на рівні 6. Помилкові Podʼи, повʼязані з завданням, відновлюються контролером завдань з експоненційною затримкою (10 с, 20 с, 40 с …) з верхнім обмеженням у шість хвилин.
Кількість спроб обчислюється двома способами:
- Кількість Podʼів з
.status.phase = "Failed"
. - При використанні
restartPolicy = "OnFailure"
кількість спроб у всіх контейнерах Podʼів з.status.phase
, що дорівнюєPending
абоRunning
.
Якщо хоча б один із розрахунків досягне значення .spec.backoffLimit
, завдання вважається невдалим.
Примітка:
Якщо ваше завдання маєrestartPolicy = "OnFailure"
, майте на увазі, що Pod, який виконує завдання, буде припинений, як тільки ліміт затримки завдання буде досягнуто. Це може ускладнити налагодження виконуваного завдання. Ми радимо встановлювати restartPolicy = "Never"
під час налагодження завдання або використовувати систему логування, щоб забезпечити, що вивід з невдалого завдання не буде втрачено випадково.Ліміт затримки для кожного індексу
Kubernetes v1.29 [beta]
Примітка:
Ви можете налаштувати ліміт затримки для кожного індексу для завдання з індексацією, якщо у вас увімкнено функціональну можливістьJobBackoffLimitPerIndex
в вашому кластері.Коли ви запускаєте індексоване Завдання, ви можете вибрати обробку спроб для відмов Podʼа незалежно для кожного індексу. Для цього встановіть
.spec.backoffLimitPerIndex
, щоб вказати максимальну кількість невдалих спроб Podʼа
для кожного індексу.
Коли ліміт затримки для кожного індексу перевищується для певного індексу, Kubernetes вважає цей індекс невдалим і додає його до поля .status.failedIndexes
. Індекси, які виконались успішно, реєструються в полі .status.completedIndexes
, незалежно від того, чи ви встановили поле backoffLimitPerIndex
.
Зауважте, що невдалий індекс не перериває виконання інших індексів. Щойно всі індекси завершаться для завдання, в якому ви вказали ліміт затримки для кожного індексу, якщо хоча б один з цих індексів виявився невдалим, контролер завдань позначає загальне завдання як невдале, встановлюючи умову Failed
в статусі. Завдання отримує позначку "невдало", навіть якщо деякі, можливо, усі індекси були
оброблені успішно.
Ви також можете обмежити максимальну кількість позначених невдалих індексів, встановивши поле .spec.maxFailedIndexes
. Коли кількість невдалих індексів перевищує значення поля maxFailedIndexes
, контролер завдань запускає завершення всіх залишаються запущеними Podʼами для цього завдання. Щойно всі Podʼи будуть завершені, контролер завдань позначає все Завдання як невдале, встановлюючи умову Failed
в статусі Завдання.
Ось приклад маніфесту для завдання, яке визначає backoffLimitPerIndex
:
apiVersion: batch/v1
kind: Job
metadata:
name: job-backoff-limit-per-index-example
spec:
completions: 10
parallelism: 3
completionMode: Indexed # обов'язково для функціоналу
backoffLimitPerIndex: 1 # максимальна кількість невдач на один індекс
maxFailedIndexes: 5 # максимальна кількість невдалих індексів перед припиненням виконання Job
template:
spec:
restartPolicy: Never # обов'язково для функціоналу
containers:
- name: example
image: python
command: # Робота завершується невдачею, оскільки є принаймні один невдалий індекс
# (всі парні індекси невдаються), але всі індекси виконуються,
# оскільки не перевищено максимальну кількість невдалих індексів.
- python3
- -c
- |
import os, sys
print("Привіт, світ")
if int(os.environ.get("JOB_COMPLETION_INDEX")) % 2 == 0:
sys.exit(1)
У вищенаведеному прикладі контролер завдань дозволяє один перезапуск для кожного з індексів. Коли загальна кількість невдалих індексів перевищує 5, тоді все завдання припиняються.
Після завершення роботи стан завдання виглядає наступним чином:
kubectl get -o yaml job job-backoff-limit-per-index-example
status:
completedIndexes: 1,3,5,7,9
failedIndexes: 0,2,4,6,8
succeeded: 5 # 1 succeeded pod for each of 5 succeeded indexes
failed: 10 # 2 failed pods (1 retry) for each of 5 failed indexes
conditions:
- message: Job has failed indexes
reason: FailedIndexes
status: "True"
type: FailureTarget
- message: Job has failed indexes
reason: FailedIndexes
status: "True"
type: Failed
Контролер Job додає умову FailureTarget
до Job для запуску завершення та очищення Job. Коли всі Podʼи Job завершуються, контролер Job додає умову Failed
з тими ж значеннями для reason
і message
, що й у умови FailureTarget
. Для деталей дивіться Завершення Podʼів завдання.
Додатково ви можете використовувати ліміт затримки для кожного індексу разом з
політикою збоїв Podʼа. Коли використовується ліміт затримки для кожного індексу, доступний новій дії FailIndex
, який дозволяє вам уникати непотрібних повторів всередині індексу.
Політика збою Podʼа
Kubernetes v1.31 [stable]
(стандартно увімкнено: true)Політика збою Podʼа, визначена за допомогою поля .spec.podFailurePolicy
, дозволяє вашому кластеру обробляти відмови Podʼа на основі кодів виходу контейнера та умов Podʼа.
У деяких ситуаціях вам може знадобитися кращий контроль обробки відмов Podʼа, ніж контроль, який надає політика відмови Podʼа за допомогою затримки збою Podʼа, яка базується на .spec.backoffLimit
завдання. Ось деякі приклади використання:
- Для оптимізації витрат на виконання завдань, уникнення непотрібних перезапусків Podʼа, ви можете завершити завдання, як тільки один із його Podʼів відмовить із кодом виходу, що вказує на помилку програмного забезпечення.
- Щоб гарантувати, що ваше завдання завершиться, навіть якщо є розлади, ви можете ігнорувати відмови Podʼа, спричинені розладами (такими як випередження, виселення, ініційоване API або виселення на підставі маркування), щоб вони не враховувалися при досягненні
.spec.backoffLimit
ліміту спроб.
Ви можете налаштувати політику збою Podʼа в полі .spec.podFailurePolicy
, щоб відповідати вищенаведеним використанням. Ця політика може обробляти відмови Podʼа на основі кодів виходу контейнера та умов Podʼа.
Ось маніфест для завдання, яке визначає podFailurePolicy
:
apiVersion: batch/v1
kind: Job
metadata:
name: job-pod-failure-policy-example
spec:
completions: 12
parallelism: 3
template:
spec:
restartPolicy: Never
containers:
- name: main
image: docker.io/library/bash:5
command: ["bash"] # приклад команди, що емулює помилку, яка запускає дію FailJob
args:
- -c
- echo "Hello world!" && sleep 5 && exit 42
backoffLimit: 6
podFailurePolicy:
rules:
- action: FailJob
onExitCodes:
containerName: main # опціонально
operator: In # одне з: In, NotIn
values: [42]
- action: Ignore # одне з: Ignore, FailJob, Count
onPodConditions:
- type: DisruptionTarget # вказує на порушення роботи Podʼу
У вищенаведеному прикладі перше правило політики збою Podʼа вказує, що завдання слід позначити як невдале, якщо контейнер main
завершиться кодом виходу 42. Наступні правила стосуються саме контейнера main
:
- код виходу 0 означає, що контейнер виконався успішно
- код виходу 42 означає, що все завдання виконалося невдало
- будь-який інший код виходу вказує, що контейнер виконався невдало, і, отже, весь Pod буде створений заново, якщо загальна кількість перезапусків менше
backoffLimit
. ЯкщоbackoffLimit
досягнуте, все завдання виконалося невдало.
Примітка:
Оскільки в шаблоні Podʼа вказаноrestartPolicy: Never
, kubelet не перезапускає контейнер main
в тому конкретному Podʼі.Друге правило політики збою Podʼа, що вказує дію Ignore
для невдалих Podʼів з умовою DisruptionTarget
, виключає Podʼи, які взяли участь в розладах, з хунок ліміту спроб .spec.backoffLimit
.
Примітка:
Якщо завдання виявилося невдалим, будь-то через політику збою Podʼа, чи через політику затримки збою Podʼа, і завдання виконується декількома Podʼами, Kubernetes завершує всі Podʼи в цьому завданні, які все ще перебувають у статусах Pending або Running.Ось деякі вимоги та семантика API:
- якщо ви хочете використовувати поле
.spec.podFailurePolicy
для завдання Job, вам також слід визначити шаблон Podʼа цього завдання з.spec.restartPolicy
, встановленим наNever
. - правила політики збою Podʼа, які ви визначаєте у
spec.podFailurePolicy.rules
, оцінюються послідовно. Якщо одне з правил відповідає збою Podʼа, інші правила ігноруються. Якщо жодне правило не відповідає збою Podʼа, застосовується типова обробка. - ви можете бажати обмежити правило певним контейнером, вказавши його імʼя у
spec.podFailurePolicy.rules[*].onExitCodes.containerName
. Якщо не вказано, правило застосовується до всіх контейнерів. Якщо вказано, воно повинно відповідати імені одного з контейнерів абоinitContainer
у шаблоні Podʼа. - ви можете вказати дію, вживану при відповідності політиці збою Podʼа, у
spec.podFailurePolicy.rules[*].action
. Можливі значення:FailJob
: використовуйте це, щоб вказати, що завдання Podʼа має бути позначено як Failed та всі запущені Podʼи повинні бути завершені.Ignore
: використовуйте це, щоб вказати, що лічильник до.spec.backoffLimit
не повинен збільшуватися, і повинен бути створений замінюючий Pod.Count
: використовуйте це, щоб вказати, що Pod повинен бути оброблений типовим способом. Лічильник до.spec.backoffLimit
повинен збільшитися.FailIndex
: використовуйте цю дію разом із лімітом затримки на кожен індекс для уникнення непотрібних повторних спроб в межах індексу невдалого Podʼа.
Примітка:
Коли використовуєтьсяpodFailurePolicy
, контролер завдань враховує лише Podʼи у фазі Failed
. Podʼи з відміткою про видалення, які не знаходяться в термінальній фазі (Failed
чи Succeeded
), вважаються таким що примусово припиняють свою роботу. Це означає, що такі Podʼи зберігають завершувачі відстеження доки не досягнуть термінальної фази. З Kubernetes 1.27 Kubelet переводить видалені Podʼи в термінальну фазу (див.: Фаза Podʼа). Це забезпечує видалення завершувачів контролером Job.Примітка:
Починаючи з Kubernetes v1.28, коли використовується політика збою Podʼа, контролер Job відтворює Podʼи, що припиняються примусово, лише тоді, коли ці Podʼи досягли термінальної фазиFailed
. Це подібно до політики заміщення Podʼа: podReplacementPolicy: Failed
. Для отримання додаткової інформації див. Політика заміщення Podʼа.Коли ви використовуєте podFailurePolicy
, і Job зазнає невдачі через Pod, що відповідає правилу з дією FailJob
, контролер Job запускає процес завершення Job, додаючи умову FailureTarget
. Для деталей дивіться Завершення та очищення Job.
Політика успіху
Kubernetes v1.31 [beta]
(стандартно увімкнено: true)Примітка:
Ви можете налаштувати політику успіху лише для Індексованого Завдання, якщо у вас увімкнено функціональну можливістьJobSuccessPolicy
у вашому кластері.При створенні Індексованого Завдання ви можете визначити, коли завдання може бути визнане успішним за допомогою .spec.successPolicy
, на основі успішних Podʼів.
Типово завдання вважається успішним, коли кількість успішних Podʼів дорівнює .spec.completions
. Існують ситуації, коли вам може знадобитися додатковий контроль для визначення завдання успішним:
- Під час виконання симуляцій з різними параметрами, вам можуть не знадобитися всі симуляції для успішного завершення загального завдання.
- При використанні шаблону лідер-робітник, успіх лідера визначає успіх чи невдачу завдання. Прикладами цього є фреймворки, такі як MPI та PyTorch тощо.
Ви можете налаштувати політику успіху у полі .spec.successPolicy
, щоб задовольнити вищезазначені випадки використання. Ця політика може керувати успіхом завдання на основі успішних Podʼів. Після того, як завдання відповідає політиці успіху, контролер завдань завершує залишкові Podʼи. Політика успіху визначається правилами. Кожне правило може мати одну з наступних форм:
- Коли ви вказуєте лише
succeededIndexes
, одразу після успішного завершення всіх індексів, вказаних уsucceededIndexes
, контролер завдань позначає завдання як успішне.succeededIndexes
повинен бути списком інтервалів між 0 і.spec.completions-1
. - Коли ви вказуєте лише
succeededCount
, як тільки кількість успішних індексів досягнеsucceededCount
, контролер завдань позначає завдання як успішне. - Коли ви вказуєте як
succeededIndexes
, так іsucceededCount
, як тільки кількість успішних індексів з підмножини індексів, вказаних уsucceededIndexes
, досягнеsucceededCount
, контролер завдань позначає завдання як успішне.
Зверніть увагу, що коли ви вказуєте кілька правил у .spec.successPolicy.rules
, контролер завдань оцінює правила послідовно. Після того, як завдання задовольняє правило, контролер завдань ігнорує решту правил.
Ось приклад маніфеста для завдання із successPolicy
:
apiVersion: batch/v1
kind: Job
metadata:
name: job-success
spec:
parallelism: 10
completions: 10
completionMode: Indexed # Обовʼязково для іспішної політики
successPolicy:
rules:
- succeededIndexes: 0,2-3
succeededCount: 1
template:
spec:
containers:
- name: main
image: python
command: # З урахуванням того, що принаймні один із Podʼів з індексами 0, 2 та 3 успішно завершився,
# загальна задача вважатиметься успішною.
- python3
- -c
- |
import os, sys
if os.environ.get("JOB_COMPLETION_INDEX") == "2":
sys.exit(0)
else:
sys.exit(1)
restartPolicy: Never
У вищенаведеному прикладі були вказані як succeededIndexes
, так і succeededCount
. Тому контролер завдань позначить завдання як успішне і завершить залишкові Podʼи після успіху будь-яких зазначених індексів, 0, 2 або 3. Завдання, яке відповідає політиці успіху, отримує умову SuccessCriteriaMet
з причиною SuccessPolicy
. Після видалення залишкових Podʼів, завдання отримує стан Complete
.
Зверніть увагу, що succeededIndexes
представлено як інтервали, розділені дефісом. Номери перераховані у вигляді першого та останнього елементів серії, розділених дефісом.
Примітка:
Коли ви вказуєте як політику успіху, так і деякі політики завершення, такі як.spec.backoffLimit
і .spec.podFailurePolicy
, одного разу, коли завдання задовольняє будь-яку політику, контролер завдань дотримується політики завершення і ігнорує політику успіху.Завершення завдання та очищення
Коли завдання завершується, Podʼи більше не створюються, але Podʼи зазвичай також не видаляються. Тримання їх допомагає переглядати логи завершених Podʼів для перевірки наявності помилок, попереджень чи іншого діагностичного виводу. Обʼєкт завдання також залишається після завершення, щоб ви могли переглядати його статус. Користувачу слід видаляти старі завдання після перегляду їх статусу. Видаліть завдання за допомогою kubectl
(наприклад, kubectl delete jobs/pi
або kubectl delete -f ./job.yaml
). Коли ви видаляєте завдання за допомогою kubectl
, всі його створені Podʼи також видаляються.
Стандартно завдання буде виконуватися без перерви, поки Pod не вийде з ладу (restartPolicy=Never
) або контейнер не вийде з ладу з помилкою (restartPolicy=OnFailure
), після чого завдання дотримується .spec.backoffLimit
, описаного вище. Як тільки досягнуто .spec.backoffLimit
, завдання буде позначене як невдале, і будь-які запущені Podʼи будуть завершені.
Іншим способом завершити завдання є встановлення граничного терміну виконання. Це робиться шляхом встановлення поля .spec.activeDeadlineSeconds
завдання кількості секунд. activeDeadlineSeconds
застосовується до тривалості завдання, незалежно від кількості створених Podʼів. Як тільки Job досягає activeDeadlineSeconds
, всі його запущені Podʼи завершуються, і статус завдання стане type: Failed
з reason: DeadlineExceeded
.
Зауважте, що .spec.activeDeadlineSeconds
Job має пріоритет перед його .spec.backoffLimit
. Отже, завдання, яке повторює один або кілька невдал х Podʼів, не розпочне розгортання додаткових Podʼів, якщо activeDeadlineSeconds
вже досягнуто, навіть якщо backoffLimit
не досягнуто. Приклад:
apiVersion: batch/v1 kind: Job
metadata:
name: pi-with-timeout
Стандартноimit: 5
activeDeadlineSeconds: 100
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Зверніть увагу, що як саме специфікація Job, так і специфікація шаблону Pod у межах завдання мають поле activeDeadlineSeconds
. Переконайтеся, що ви встановлюєте це поле на відповідному рівні.
Памʼятайте, що restartPolicy
застосовується до Podʼа, а не до самого завдання: автоматичного перезапуску завдання не відбудеться, якщо статус завдання type: Failed
. Іншими словами, механізми завершення завдання, активовані за допомогою .spec.activeDeadlineSeconds
і .spec.backoffLimit
, призводять до постійної невдачі завдання, що вимагає ручного втручання для вирішення.
Умови термінального завдання
Job має два можливих термінальних стани, кожен з яких має відповідну умову завдання:
- Успішне виконання: умова завдання
Complete
- Невдача: умова завдання
Failed
Завдання зазнають невдачі з наступних причин:
- Кількість невдач Podʼа перевищила вказане
.spec.backoffLimit
у специфікації завдання. Для деталей див. Політика відмови Podʼа. - Час виконання завдання перевищив вказане
.spec.activeDeadlineSeconds
. - Індексуєме завдання, яке використовує
.spec.backoffLimitPerIndex
, має невдалі індекси. Для деталей див. Ліміт затримки на індекс. - Кількість невдалих індексів у завданні перевищила вказане
spec.maxFailedIndexes
. Для деталей див. Ліміт затримки на індекс. - Невдалий Pod відповідає правилу у
.spec.podFailurePolicy
, яке має діюFailJob
. Для деталей про те, як правила політики невдач Podʼа можуть вплинути на оцінку невдачі, див. Політика невдач Podʼа.
Завдання успішні з наступних причин:
- Кількість успішних Podʼів досягла вказаного
.spec.completions
. - Виконані критерії, зазначені у
.spec.successPolicy
. Для деталей див. Політика успіху.
У Kubernetes v1.31 та пізніших версіях контролер завдань затримує додавання термінальних умов, Failed
або Complete
, поки всі Podʼи завдання не будуть завершені.
У Kubernetes v1.30 та раніших версіях контролер завдань додавав термінальні умови Complete
або Failed
відразу після того, як був запущений процес завершення завдання та всі завершувачі Podʼа були видалені. Однак деякі Podʼи все ще могли працювати або завершуватися в момент додавання термінальної умови.
У Kubernetes v1.31 та пізніших версіях контролер додає термінальні умови завдання лише після завершення всіх Podʼів. Ви можете увімкнути цю поведінку, використовуючи функціональні можливості JobManagedBy
або JobPodReplacementPolicy
(стандартно увімкнено).
Завершення Podʼів завдання
Контролер Job додає умову FailureTarget
або умову SuccessCriteriaMet
до завдання, щоб запустити завершення Pod після того, як завдання відповідає критеріям успіху або невдачі.
Фактори, такі як terminationGracePeriodSeconds
, можуть збільшити час від моменту додавання контролером завдання умови FailureTarget
або умови SuccessCriteriaMet
до моменту, коли всі Pod завдання завершаться і контролер Job додасть термінальну умову (Failed
або Complete
).
Ви можете використовувати умову FailureTarget
або умову SuccessCriteriaMet
, щоб оцінити, чи завдання зазнало невдачі чи досягло успіху, без необхідності чекати, поки контролер додасть термінальну умову.
Наприклад, ви можете захотіти вирішити, коли створити замінний Job, що замінює невдалий. Якщо ви заміните невдале завдання, коли з’являється умова FailureTarget
, ваше замінне завдання запуститься раніше, але це може призвести до того, що Podʼи з невдалого та замінного завдання будуть працювати одночасно, використовуючи додаткові обчислювальні ресурси.
Альтернативно, якщо ваш кластер має обмежену ресурсну ємність, ви можете вибрати чекати, поки з’явиться умова Failed
на завданні, що затримає ваше замінне завдання, але забезпечить збереження ресурсів, чекаючи, поки всі невдалі Podʼи не будуть видалені.
Автоматичне очищення завершених завдань
Зазвичай завершені завданя вже не потрібні в системі. Зберігання їх в системі може створювати тиск на сервер API. Якщо завдання керується безпосередньо контролером вищого рівня, таким як CronJobs, завдання можна очищати за допомогою CronJobs на основі визначеної політики очищення з урахуванням місткості.
Механізм TTL для завершених завдань
Kubernetes v1.23 [stable]
Ще один спосіб автоматично очищати завершені завдання (якщо вони Complete
або Failed
) — це використовувати механізм TTL, наданий
контролером TTL для завершених ресурсів, вказуючи поле .spec.ttlSecondsAfterFinished
у Job.
Коли контролер TTL очищує Job, він каскадно видаляє Job, тобто видаляє його залежні обʼєкти, такі як Podʼи, разом з Job. Зверніть увагу що при видаленні Job будуть дотримані гарантії його життєвого циклу, такі як завершувачі.
Наприклад:
apiVersion: batch/v1
kind: Job
metadata:
name: pi-with-ttl
spec:
ttlSecondsAfterFinished: 100
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
Job pi-with-ttl
буде призначено для автоматичного видалення через 100
секунд після завершення.
Якщо поле встановлено в 0
, Job буде призначено для автоматичного видалення негайно після завершення. Якщо поле не вказане, це Job не буде очищено контролером TTL після завершення.
Примітка:
Рекомендується встановлювати поле ttlSecondsAfterFinished
, оскільки завдання без нагляду (завдання, які ви створили безпосередньо, а не опосередковано через інші API робочого навантаження такі як CronJob) мають станадартну політику видалення orphanDependents
, що призводить до того, що Podʼи, створені некерованим Job, залишаються після того, як Job повністю видалено. Навіть якщо панель управління в кінцевому рахунку збирає сміття Podʼів з видаленого Job після того, як вони або не вдались, або завершились, іноді ці залишки Podʼів можуть призводити до погіршання продуктивності кластера або в найгіршому випадку можуть спричинити відключення кластера через це погіршення.
Ви можете використовувати LimitRanges та ResourceQuotas щоб обмежити кількість ресурсів, які певний простір імен може споживати.
Патерни використання завдань (Job)
Обʼєкт завдання (Job) може використовуватися для обробки набору незалежних, але повʼязаних робочих одиниць. Це можуть бути електронні листи для надсилання, кадри для відтворення, файли для транскодування, діапазони ключів у базі даних NoSQL для сканування і так далі.
У складній системі може бути кілька різних наборів робочих одиниць. Тут ми розглядаємо лише один набір робочих одиниць, якими користувач хоче управляти разом — пакетне завдання.
Існує кілька різних патернів для паралельних обчислень, кожен з власними перевагами та недоліками. Компроміси:
- Один обʼєкт Job для кожної робочої одиниці або один обʼєкт Job для всіх робочих одиниць. Один Job на кожну робочу одиницю створює деяку накладну роботу для користувача та системи при управлінні великою кількістю обʼєктів Job. Один Job для всіх робочих одиниць підходить краще для великої кількості одиниць.
- Кількість створених Podʼів дорівнює кількості робочих одиниць або кожен Pod може обробляти кілька робочих одиниць. Коли кількість Podʼів дорівнює кількості робочих одиниць, Podʼи зазвичай вимагають менше змін у наявному коді та контейнерах. Кожен Pod, що обробляє кілька робочих одиниць, підходить краще для великої кількості одиниць.
- Декілька підходів використовують робочу чергу. Це вимагає запуску служби черги та модифікацій існуючої програми чи контейнера, щоб зробити його сумісним із чергою роботи. Інші підходи легше адаптувати до наявного контейнеризованого застосунку.
- Коли Job повʼязаний із headless Service, ви можете дозволити Podʼам у межах Job спілкуватися один з одним для спільної обчислень.
Переваги та недоліки узагальнено у таблиці нижче, де стовпці з 2 по 4 відповідають зазначеним вище питанням. Імена патернів також є посиланнями на приклади та більш детальний опис.
Патерн | Один обʼєкт Job | Кількість Pods менше за робочі одиниці? | Використовувати застосунок без модифікацій? |
---|---|---|---|
Черга з Pod на робочу одиницю | ✓ | іноді | |
Черга змінної кількості Pod | ✓ | ✓ | |
Індексоване Завдання із статичним призначенням роботи | ✓ | ✓ | |
Завдання із спілкуванням від Pod до Pod | ✓ | іноді | іноді |
Розширення шаблону Job | ✓ |
Коли ви вказуєте завершення з .spec.completions
, кожний Pod, створений контролером Job, має ідентичний spec
. Це означає, що всі Podʼи для завдання матимуть однакову командну строку та один і той же шаблон, та (майже) ті ж самі змінні середовища. Ці патерни — це різні способи організації Podʼів для роботи над різними завданнями.
Ця таблиця показує обовʼязкові налаштування для .spec.parallelism
та .spec.completions
для кожного з патернів. Тут W
— це кількість робочих одиниць.
Патерн | .spec.completions | .spec.parallelism |
---|---|---|
Черга з Pod на робочу одиницю | W | будь-яка |
Черга змінної кількості Pod | null | будь-яка |
Індексоване Завдання із статичним призначенням роботи | W | будь-яка |
Завдання із спілкуванням від Pod до Pod | W | W |
Розширення шаблону Job | 1 | повинно бути 1 |
Розширене використання завдань (Job)
Відкладення завдання
Kubernetes v1.24 [stable]
Коли створюється Job, контролер Job негайно починає створювати Podʼи, щоб відповісти вимогам Job і продовжує це робити, доки Job не завершиться. Однак іноді ви можете хотіти тимчасово призупинити виконання Job та відновити його пізніше, або створити Jobs у призупиненому стані та мати власний контролер, який вирішить, коли їх запустити.
Щоб призупинити Job, ви можете оновити поле .spec.suspend
Job на значення true; пізніше, коли ви захочете відновити його, оновіть його на значення false. Створення Job з .spec.suspend
встановленим в true створить його в призупиненому стані.
При відновленні Job з призупинення йому буде встановлено час початку .status.startTime
в поточний час. Це означає, що таймер .spec.activeDeadlineSeconds
буде зупинений і перезапущений, коли Job буде призупинено та відновлено.
Коли ви призупиняєте Job, будь-які запущені Podʼи, які не мають статусу Completed
, будуть завершені з сигналом SIGTERM. Буде дотримано період відповідного завершення ваших Podʼів, і вашим Podʼам слід обробити цей сигнал протягом цього періоду. Це може включати в себе збереження прогресу для майбутнього або скасування змін. Podʼи, завершені цим чином, не враховуватимуться при підрахунку completions
Job.
Приклад визначення Job в призупиненому стані може виглядати так:
kubectl get job myjob -o yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
suspend: true
parallelism: 1
completions: 5
template:
spec:
...
Ви також можете перемикати призупинення Job, використовуючи командний рядок.
Призупиніть активний Job:
kubectl patch job/myjob --type=strategic --patch '{"spec":{"suspend":true}}'
Відновіть призупинений Job:
kubectl patch job/myjob --type=strategic --patch '{"spec":{"suspend":false}}'
Статус Job може бути використаний для визначення того, чи Job призупинено чи його було зупинено раніше:
kubectl get jobs/myjob -o yaml
apiVersion: batch/v1
kind: Job
# .metadata and .spec пропущено
status:
conditions:
- lastProbeTime: "2021-02-05T13:14:33Z"
lastTransitionTime: "2021-02-05T13:14:33Z"
status: "True"
type: Suspended
startTime: "2021-02-05T13:13:48Z"
Умова Job типу "Suspended" зі статусом "True" означає, що Job призупинено; поле lastTransitionTime
може бути використане для визначення того, як довго Job було призупинено. Якщо статус цієї умови є "False", то Job було раніше призупинено і зараз працює. Якщо такої умови не існує в статусі Job, то Job ніколи не був зупинений.
Також створюються події, коли Job призупинено та відновлено:
kubectl describe jobs/myjob
Name: myjob
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 12m job-controller Created pod: myjob-hlrpl
Normal SuccessfulDelete 11m job-controller Deleted pod: myjob-hlrpl
Normal Suspended 11m job-controller Job suspended
Normal SuccessfulCreate 3s job-controller Created pod: myjob-jvb44
Normal Resumed 3s job-controller Job resumed
Останні чотири події, зокрема події "Suspended" та "Resumed", є прямим наслідком перемикання поля .spec.suspend
. Протягом цього часу ми бачимо, що жоден Pods не був створений, але створення Pod розпочалося знову, як тільки Job було відновлено.
Змінні директиви планування
Kubernetes v1.27 [stable]
У більшості випадків, паралелльні завдання вимагатимуть щоб їхні Podʼи запускались з певними обмеженнями, типу "всі в одній зоні" або "всі на GPU моделі x або y", але не комбінація обох.
Поле призупинення є першим кроком для досягнення цих семантик. Призупинення дозволяє власному контролеру черги вирішити, коли повинне початися завдання; Однак після того, як завдання престає бути призупиненим, власний контролер черги не впливає на те, де насправді буде розташований Pod завдання.
Ця функція дозволяє оновлювати директиви планування Job до запуску, що дає власному контролеру черги змогу впливати на розташування Podʼів, а в той самий час здійснювати власне призначення Podʼів вузлам в kube-scheduler. Це дозволяється тільки для призупинених Завдань, які ніколи не переставали бути призупиненими раніше.
Поля в шаблоні Podʼа Job, які можна оновити, це приналежність до вузла, селектор вузла, толерантності, мітки, анотації та вікно планування.
Вказування власного селектора Podʼа
Зазвичай, коли ви створюєте обʼєкт Job, ви не вказуєте .spec.selector
. Логіка системного визначення типових значень додає це поле під час створення Завдання. Вона обирає значення селектора, яке не буде перекриватися з будь-яким іншим завданням.
Однак у деяких випадках вам може знадобитися перевизначити цей автоматично встановлений селектор. Для цього ви можете вказати .spec.selector
Job.
Будьте дуже уважні при цьому. Якщо ви вказуєте селектор міток, який не є унікальним для Podʼів цього Завдання, і який відповідає неповʼязаним Podʼам, то Podʼи з неповʼязаним Завданням можуть бути видалені, або це Завдання може вважати інші Podʼи завершеними, або одне чи обидва Завдання можуть відмовитися від створення Podʼів або виконуватись до завершення роботи. Якщо вибираєте неунікальний селектор, то інші контролери (наприклад, ReplicationController) та їхні Podʼи можуть проявляти непередбачувану поведінку також. Kubernetes не зупинить вас від того, що ви можете зробити помилку при зазначені .spec.selector
.
Ось приклад ситуації, коли вам може знадобитися використовувати цю функцію.
Скажімо, Завдання old
вже запущене. Ви хочете, щоб наявні Podʼи продовжували працювати, але ви хочете, щоб решта Podʼів, які воно створює, використовували інший шаблон Pod і щоб у Завдання було нове імʼя. Ви не можете оновити Завдання, оскільки ці поля не можна оновлювати. Отже, ви видаляєте Завдання old
, але залишаєте її Podʼи запущеними, використовуючи kubectl delete jobs/old --cascade=orphan
. Перед видаленням ви робите помітку, який селектор використовувати:
kubectl get job old -o yaml
Виввід схожий на цей:
kind: Job
metadata:
name: old
...
spec:
selector:
matchLabels:
batch.kubernetes.io/controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
...
Потім ви створюєте нове Завдання з імʼям new
і явно вказуєте той самий селектор. Оскільки існуючі Podʼи мають мітку batch.kubernetes.io/controller-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002
, вони також контролюються Завданням new
.
Вам потрібно вказати manualSelector: true
в новому Завданні, оскільки ви не використовуєте селектор, який система зазвичай генерує автоматично.
kind: Job
metadata:
name: new
...
spec:
manualSelector: true
selector:
matchLabels:
batch.kubernetes.io/controller-uid: a8f3d00d-c6d2-11e5-9f87-42010af00002
...
Саме нове Завдання матиме інший uid від a8f3d00d-c6d2-11e5-9f87-42010af00002
. Встановлення manualSelector: true
говорить системі, що ви розумієте, що робите, і дозволяє це неспівпадіння.
Відстеження Завдання за допомогою завершувачів
Kubernetes v1.26 [stable]
Панель управління стежить за Podʼами, які належать будь-якого Завдання, і виявляє, чи Pod був видалений з сервера API. Для цього контролер Job створює Podʼи з завершувачем batch.kubernetes.io/job-tracking
. Контролер видаляє завершувач тільки після того, як Pod був врахований в стані Завдання, що дозволяє видалити Pod іншими контролерами або користувачами.
Примітка:
Див. Мій Pod залишається в стані завершення, якщо ви спостерігаєте, що Podʼи з Завдання залишаються з завершувачем відстеження.Еластичні Індексовані Завдання
Kubernetes v1.31 [stable]
(стандартно увімкнено: true)Ви можете масштабувати Indexed Job вгору або вниз, змінюючи як .spec.parallelism
, так і .spec.completions
разом, так щоб .spec.parallelism == .spec.completions
. При масштабуванні вниз Kubernetes видаляє Podʼи з вищими індексами.
Сценарії використання для еластичних Індексованих Завдань включають пакетні робочі навантаження, які вимагають масштабування Індексованого Завдання, такі як MPI, Horovod, Ray, та PyTorch.
Відкладене створення замінних Podʼів
Kubernetes v1.29 [beta]
Примітка:
Ви можете встановитиpodReplacementPolicy
для Завдань тільки у випадку, якщо увімкнуто функціональну можливість JobPodReplacementPolicy
(стандартно увімкнено).Типово контролер Job створює Podʼи якнайшвидше, якщо вони або зазнають невдачі, або знаходяться в стані завершення (мають відмітку видалення). Це означає, що в певний момент часу, коли деякі з Podʼів знаходяться в стані завершення, кількість робочих Podʼів для Завдання може бути більшою, ніж parallelism
або більше, ніж один Pod на індекс (якщо ви використовуєте Індексоване Завданя).
Ви можете вибрати створення замінних Podʼів лише тоді, коли Podʼи, які знаходиться в стані завершення, повністю завершені (мають status.phase: Failed
). Для цього встановіть .spec.podReplacementPolicy: Failed
. Типова політика заміщення залежить від того, чи Завдання має встановлену політику відмови Podʼів. Якщо для Завдання не визначено політику відмови Podʼів, відсутність поля podReplacementPolicy
вибирає політику заміщення TerminatingOrFailed
: панель управління створює Podʼи заміни негайно після видалення Podʼів (як тільки панель управління бачить, що Pod для цього Завдання має встановлене значення deletionTimestamp
). Для Завдань із встановленою політикою відмови Podʼів стандартне значення podReplacementPolicy
— це Failed
, інших значень не передбачено. Докладніше про політики відмови Podʼів для Завдань можна дізнатися у розділі Політика відмови Podʼів.
kind: Job
metadata:
name: new
...
spec:
podReplacementPolicy: Failed
...
При увімкненому feature gate у вашому кластері ви можете перевірити поле .status.terminating
Завдання. Значення цього поля — це кількість Podʼів, якими володіє Завдання, які зараз перебувають у стані завершення.
kubectl get jobs/myjob -o yaml
apiVersion: batch/v1
kind: Job
# .metadata and .spec omitted
status:
terminating: 3 # три Podʼи, які перебувають у стані завершення і ще не досягли стану Failed
Делегування управління обʼєктом Job зовнішньому контролеру
Kubernetes v1.30 [alpha]
(стандартно увімкнено: false)Примітка:
Ви можете встановити полеmanagedBy
для Job лише в разі увімкнення функціональної можливості JobManagedBy
(типово вимкнено).Ця функція дозволяє вам вимкнути вбудований контролер Job для конкретного Завдання і делегувати узгодження цього Завдання зовнішньому контролеру.
Ви вказуєте контролер, який узгоджує Завдання, встановлюючи власне значення для поля spec.managedBy
— будь-яке значення окрім kubernetes.io/job-controller
. Значення поля є незмінним.
Примітка:
При використанні цієї функції переконайтеся, що контролер, вказаний у полі, встановлено, інакше Завдання може не бути узгоджене взагалі.Примітка:
При розробці зовнішнього контролера Job, будьте уважні: ваш контролер повинен працювати відповідно до визначень специфікації API та полів статусу обʼєкта Job.
Докладно ознайомтесь з ними в API Job. Ми також рекомендуємо запустити тести сумісності e2e для обʼєкта Job, щоб перевірити вашу реалізацію.
Нарешті, при розробці зовнішнього контролера Job переконайтеся, що він не використовує завершувач batch.kubernetes.io/job-tracking
, зарезервований для вбудованого контролера.
Попередження:
Якщо ви думаєте про вимкенняJobManagedBy
, або зниження версії кластера до версії без увімкненого feature gate, перевірте, чи є у вас завдання з власним значенням поля spec.managedBy
. Якщо такі завдання існують, існує ризик
того, що після виконання операції вони можуть бути узгоджені двома контролерами: вбудованим контролером Job і зовнішнім контролером, вказаним значенням поля.Альтернативи
Тільки Podʼи
Коли вузол, на якому працює Pod, перезавантажується або виходить з ладу, Pod завершується і не буде перезапущений. Однак Завдання створить нові Podʼи для заміщення завершених. З цієї причини ми рекомендуємо використовувати Завдання замість тільки Podʼів, навіть якщо ваш застосунок вимагає тільки одного Podʼа.
Контролер реплікації
Завдання є компліментарними до контролера реплікації. Контролер реплікації керує Podʼами, які не повинні завершуватися (наприклад, вебсервери), а Завдання керує Podʼами, які очікують завершення (наприклад, пакетні задачі).
Якщо врахувати життєвий цикл Podʼа, Job
лише придатний для Podʼів з RestartPolicy
, рівним OnFailure
або Never
. (Примітка: Якщо RestartPolicy
не встановлено, стандартне значення — Always
.)
Один Job запускає контролер Podʼів
Ще один підхід — це те, що одне Завдання створює Podʼи, які своєю чергою створюють інші Podʼи, виступаючи як свого роду власний контролер для цих Podʼів. Це дає найбільшу гнучкість, але може бути дещо складним для початку використання та пропонує меншу інтеграцію з Kubernetes.
Один приклад такого підходу — це Завдання, яке створює Podʼи, яка виконує сценарій, який з свого боку запускає контролер Spark master (див. приклад Spark), запускає драйвер Spark, а потім робить очищення.
Перевагою цього підходу є те, що загальний процес отримує гарантію завершення обʼєкта Job, але при цьому повністю контролюється те, які Podʼи створюються і яке навантаження їм призначається.
Що далі
- Дізнайтеся про Podʼи.
- Дізнайтеся про різні способи запуску Завдань:
- Груба паралельна обробка за допомогою робочої черги
- Тонка паралельна обробка за допомогою робочої черги
- Використовуйте Індексовані Завдання для паралельної обробки із статичним призначенням навантаження
- Створіть кілька Завдань на основі шаблону: Паралельна обробка з використанням розширень
- Перейдіть за посиланням Автоматичне очищення завершених завдань, щоб дізнатися більше про те, як ваш кластер може очищати завершені та/або невдачливі завдання.
Job
є частиною REST API Kubernetes. Ознайомтесь з визначенням обʼєкта Job, щоб зрозуміти API для завдань.- Прочитайте про
CronJob
, який ви можете використовувати для визначення серії Завдань, які будуть виконуватися за розкладом, схожим на інструмент UNIXcron
. - Попрактикуйтесь в налаштувані обробки відмовних і невідмовних збоїв Podʼів за допомогою
podFailurePolicy
на основі покрокових прикладів.