Модуль 2.4: Jobs та CronJobs
Складність:
[QUICK]— Прості пакетні робочі навантаженняЧас на проходження: 30-40 хвилин
Передумови: Модуль 2.1 (Поди)
Що ви зможете робити
Розділ «Що ви зможете робити»Після цього модуля ви зможете:
- Створити Jobs та CronJobs з відповідним паралелізмом, кількістю завершень та лімітами повторних спроб
- Дебажити невдалі Jobs, перевіряючи логи подів, коди виходу та політики перезапуску
- Налаштувати політики конкурентності CronJob та ліміти історії для продуктивного використання
- Пояснити, коли використовувати Jobs замість Deployments та наслідки кожного варіанта для пакетних навантажень
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Не всі робочі навантаження працюють безперервно. Деякі виконуються один раз і завершуються:
- Міграції баз даних
- Пакетна обробка
- Генерація звітів
- Операції резервного копіювання
Jobs обробляють одноразові завдання. CronJobs обробляють заплановані, повторювані завдання. Іспит CKA перевіряє створення Jobs із конкретними вимогами до завершення та пошук несправностей у невдалих Jobs.
Аналогія з менеджером завдань
Уявіть Jobs як завдання у списку справ. Job — це одне завдання: «Згенерувати щомісячний звіт». Коли виконано — ви відмічаєте його. CronJob — це повторюване завдання: «Генерувати щомісячний звіт 1-го числа кожного місяця». Менеджер завдань (Kubernetes) гарантує, що завдання виконається, повторить спробу у разі невдачі та відстежить завершення.
Що ви дізнаєтесь
Розділ «Що ви дізнаєтесь»До кінця цього модуля ви зможете:
- Створювати Jobs для одноразових завдань
- Налаштовувати паралелізм та кількість завершень
- Обробляти збої та повторні спроби Jobs
- Створювати CronJobs для запланованих завдань
- Виконувати налагодження невдалих Jobs
Частина 1: Jobs
Розділ «Частина 1: Jobs»1.1 Що таке Job?
Розділ «1.1 Що таке Job?»Job створює Поди, які працюють до завершення. На відміну від Deployments (які підтримують Поди працюючими постійно), Jobs очікують, що Поди успішно завершаться.
┌────────────────────────────────────────────────────────────────┐│ Життєвий цикл Job ││ ││ Job створено ││ │ ││ ▼ ││ Під створено ──────────────────────────────────────────┐ ││ │ │ ││ ▼ │ ││ Під працює │ ││ │ │ ││ ├───► Exit 0 (Успіх) ──► Job завершено │ ││ │ │ ││ └───► Exit ≠ 0 (Збій) ──► Повторити? ─────────────►┘ ││ (залежно від backoffLimit) ││ │└────────────────────────────────────────────────────────────────┘1.2 Створення Job
Розділ «1.2 Створення Job»apiVersion: batch/v1kind: Jobmetadata: name: pi-calculationspec: template: spec: containers: - name: pi image: perl command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] restartPolicy: Never # Обов'язково для Jobs backoffLimit: 4 # Повторити до 4 разів у разі збою# Створити job імперативноkubectl create job pi --image=perl -- perl -Mbignum=bpi -wle "print bpi(100)"
# Згенерувати YAMLkubectl create job pi --image=perl --dry-run=client -o yaml -- perl -Mbignum=bpi -wle "print bpi(100)"1.3 Команди для Job
Розділ «1.3 Команди для Job»# Список jobskubectl get jobs
# Спостерігати за прогресом jobkubectl get jobs -w
# Опис jobkubectl describe job pi-calculation
# Отримати логи jobkubectl logs job/pi-calculation
# Видалити job (також видаляє Поди)kubectl delete job pi-calculation1.4 Політика перезапуску
Розділ «1.4 Політика перезапуску»Jobs потребують або Never, або OnFailure:
| Політика | Поведінка |
|---|---|
Never | Створити новий Під у разі збою |
OnFailure | Перезапустити контейнер у тому самому Поді у разі збою |
spec: template: spec: restartPolicy: Never # Новий Під на кожен збій # restartPolicy: OnFailure # Перезапуск того самого ПодуЧи знали ви?
З
restartPolicy: Neverневдалі спроби створюють нові Поди. З backoffLimit рівним 4, ви можете побачити 5 Подів (1 оригінальний + 4 повторні спроби). ЗOnFailureви бачите менше Подів, оскільки контейнери перезапускаються на місці.
Частина 2: Завершення та паралелізм Jobs
Розділ «Частина 2: Завершення та паралелізм Jobs»2.1 Запуск з кількома завершеннями
Розділ «2.1 Запуск з кількома завершеннями»apiVersion: batch/v1kind: Jobmetadata: name: batch-jobspec: completions: 5 # Job вважається успішним, коли 5 Подів завершаться успішно parallelism: 2 # Запускати 2 Поди одночасно template: spec: containers: - name: worker image: busybox command: ["sh", "-c", "echo Processing item; sleep 5"] restartPolicy: Never2.2 Шаблони паралелізму
Розділ «2.2 Шаблони паралелізму»| Шаблон | completions | parallelism | Поведінка |
|---|---|---|---|
| Один Під | 1 (за замовчуванням) | 1 (за замовчуванням) | Один Під працює до завершення |
| Фіксовані завершення | N | M | M Подів працюють паралельно, поки N не завершаться успішно |
| Черга роботи | не задано | N | N Подів працюють, поки один не завершиться успішно |
┌────────────────────────────────────────────────────────────────┐│ Completions=5, Parallelism=2 ││ ││ Час ──────────────────────────────────────────────────► ││ ││ Слот 1: [Під 1 ✓] [Під 3 ✓] [Під 5 ✓] ││ Слот 2: [Під 2 ✓] [Під 4 ✓] ││ ││ 2 Поди працюють одночасно, поки не досягнуто 5 завершень ││ │└────────────────────────────────────────────────────────────────┘2.3 Приклади
Розділ «2.3 Приклади»# Запустити 10 завдань, 3 одночасноkubectl create job batch --image=busybox -- sh -c "echo done; sleep 2"kubectl patch job batch -p '{"spec":{"completions":10,"parallelism":3}}'
# Або створити з YAMLcat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: parallel-jobspec: completions: 10 parallelism: 3 template: spec: containers: - name: worker image: busybox command: ["sh", "-c", "echo Task complete; sleep 2"] restartPolicy: NeverEOF
# Спостерігати за прогресомkubectl get jobs parallel-job -wЧастина 3: Обробка збоїв Job
Розділ «Частина 3: Обробка збоїв Job»3.1 backoffLimit
Розділ «3.1 backoffLimit»Контролює кількість повторних спроб:
apiVersion: batch/v1kind: Jobmetadata: name: failing-jobspec: backoffLimit: 3 # Повторити 3 рази, потім — збій template: spec: containers: - name: fail image: busybox command: ["sh", "-c", "exit 1"] # Завжди завершується збоєм restartPolicy: Never3.2 activeDeadlineSeconds
Розділ «3.2 activeDeadlineSeconds»Максимальний час виконання job:
apiVersion: batch/v1kind: Jobmetadata: name: timeout-jobspec: activeDeadlineSeconds: 60 # Зупинити job через 60 секунд template: spec: containers: - name: long-task image: busybox command: ["sleep", "120"] # Намагається працювати 2 хвилини restartPolicy: Never3.3 Перевірка статусу Job
Розділ «3.3 Перевірка статусу Job»# Статус jobkubectl get job myjob# NAME COMPLETIONS DURATION AGE# myjob 3/5 2m 5m
# Детальний статусkubectl describe job myjob | grep -A5 "Pods Statuses"
# Перевірити невдалі Подиkubectl get pods -l job-name=myjob --field-selector=status.phase=FailedЧастина 4: CronJobs
Розділ «Частина 4: CronJobs»4.1 Що таке CronJob?
Розділ «4.1 Що таке CronJob?»CronJob створює Jobs за розкладом, подібно до cron у Linux.
┌────────────────────────────────────────────────────────────────┐│ CronJob ││ ││ Розклад: "0 * * * *" (щогодини) ││ ││ 1:00 ──► Створює Job ──► Створює Під ──► Завершено ││ 2:00 ──► Створює Job ──► Створює Під ──► Завершено ││ 3:00 ──► Створює Job ──► Створює Під ──► Завершено ││ ... ││ │└────────────────────────────────────────────────────────────────┘4.2 Синтаксис розкладу cron
Розділ «4.2 Синтаксис розкладу cron»┌───────────── хвилина (0 - 59)│ ┌───────────── година (0 - 23)│ │ ┌───────────── день місяця (1 - 31)│ │ │ ┌───────────── місяць (1 - 12)│ │ │ │ ┌───────────── день тижня (0 - 6) (Неділя = 0)│ │ │ │ │* * * * *| Розклад | Опис |
|---|---|
* * * * * | Щохвилини |
0 * * * * | Щогодини |
0 0 * * * | Щодня опівночі |
0 0 * * 0 | Щонеділі опівночі |
*/5 * * * * | Кожні 5 хвилин |
0 9-17 * * 1-5 | Щогодини з 9 до 17, Пн-Пт |
4.3 Створення CronJob
Розділ «4.3 Створення CronJob»apiVersion: batch/v1kind: CronJobmetadata: name: backupspec: schedule: "0 2 * * *" # Щодня о 2:00 jobTemplate: spec: template: spec: containers: - name: backup image: busybox command: ["sh", "-c", "echo Backup started; sleep 10; echo Backup done"] restartPolicy: OnFailure successfulJobsHistoryLimit: 3 # Зберігати 3 записи успішних jobs failedJobsHistoryLimit: 1 # Зберігати 1 запис невдалого job# Створити CronJob імперативноkubectl create cronjob backup --image=busybox --schedule="0 2 * * *" -- sh -c "echo Backup done"
# Згенерувати YAMLkubectl create cronjob backup --image=busybox --schedule="*/5 * * * *" --dry-run=client -o yaml -- echo "hello"4.4 Команди для CronJob
Розділ «4.4 Команди для CronJob»# Список CronJobskubectl get cronjobskubectl get cj # Скорочена форма
# Описkubectl describe cronjob backup
# Вручну запустити job з CronJobkubectl create job --from=cronjob/backup backup-manual
# Призупинити CronJobkubectl patch cronjob backup -p '{"spec":{"suspend":true}}'
# Відновити CronJobkubectl patch cronjob backup -p '{"spec":{"suspend":false}}'
# Видалити CronJob (також видаляє створені Jobs)kubectl delete cronjob backup4.5 Політика паралельності CronJob
Розділ «4.5 Політика паралельності CronJob»spec: concurrencyPolicy: Allow # За замовчуванням — дозволити одночасні jobs # concurrencyPolicy: Forbid # Пропустити, якщо попередній ще працює # concurrencyPolicy: Replace # Зупинити попередній, запустити новий| Політика | Поведінка |
|---|---|
Allow | Кілька Jobs можуть працювати одночасно |
Forbid | Пропустити новий Job, якщо попередній ще працює |
Replace | Зупинити поточний Job, запустити новий |
Порада до іспиту
Для запланованих завдань резервного копіювання використовуйте
concurrencyPolicy: Forbid, щоб запобігти перекриттю запусків. Для швидких завдань, які не повинні перекриватися,Replaceможе бути кращим варіантом.
Частина 5: Налагодження Jobs
Розділ «Частина 5: Налагодження Jobs»5.1 Типові проблеми з Jobs
Розділ «5.1 Типові проблеми з Jobs»| Проблема | Симптом | Команда для діагностики |
|---|---|---|
| Помилка завантаження образу | Під у стані ImagePullBackOff | kubectl describe pod <pod> |
| Збій команди | Job не завершується | kubectl logs job/<job-name> |
| Тайм-аут | Job зупинено | Перевірте activeDeadlineSeconds |
| Забагато повторних спроб | Кілька невдалих Подів | Перевірте backoffLimit |
5.2 Робочий процес налагодження
Розділ «5.2 Робочий процес налагодження»# 1. Перевірити статус jobkubectl get job myjobkubectl describe job myjob
# 2. Знайти Поди, створені jobkubectl get pods -l job-name=myjob
# 3. Перевірити логи Подівkubectl logs <pod-name>kubectl logs job/myjob # Автоматично обирає Під
# 4. Якщо ще працює, зайти в Підkubectl exec -it <pod-name> -- /bin/sh
# 5. Перевірити подіїkubectl get events --field-selector involvedObject.name=myjobЧи знали ви?
Розділ «Чи знали ви?»-
Jobs не видаляються автоматично за замовчуванням. Встановіть
ttlSecondsAfterFinishedдля автоматичного очищення завершених Jobs. -
Часовий пояс CronJob базується на часовому поясі controller-manager (зазвичай UTC). Плануйте розклади відповідно.
-
Поди Jobs залишаються після завершення для перевірки логів. Видаліть Job, щоб очистити Поди.
-
Indexed Jobs (Kubernetes 1.21+) призначають унікальні індекси Подам для шаблонів паралельної обробки.
Типові помилки
Розділ «Типові помилки»| Помилка | Проблема | Рішення |
|---|---|---|
Використання restartPolicy: Always | Job ніколи не завершується | Використовуйте Never або OnFailure |
| Відсутній backoffLimit | Нескінченні повторні спроби | Встановіть відповідний backoffLimit |
| Неправильний синтаксис cron | Job ніколи не запускається | Перевірте на crontab.guru |
| Не перевірено логи | Невідома причина збою | Завжди перевіряйте kubectl logs job/name |
| Перекриття CronJob | Конкуренція за ресурси | Встановіть concurrencyPolicy: Forbid |
Тест
Розділ «Тест»-
Які параметри restartPolicy допустимі для Jobs?
Відповідь
`Never` або `OnFailure`. `Always` недопустимий для Jobs, оскільки Jobs очікують, що Поди завершаться. -
Job має completions: 5 та parallelism: 2. Що відбувається?
Відповідь
Job запускає 2 Поди паралельно. Коли Поди успішно завершуються, запускаються нові Поди, поки не буде досягнуто 5 загальних успішних завершень. -
Як вручну запустити CronJob?
Відповідь
`kubectl create job --from=cronjob/` Це одразу створює Job із шаблону CronJob.
-
Що робить concurrencyPolicy: Forbid?
Відповідь
Якщо попередній Job від CronJob ще працює, коли настає час нового запланованого запуску, новий Job повністю пропускається.
Практична вправа
Розділ «Практична вправа»Завдання: Створити Jobs та CronJobs, обробити збої.
Кроки:
- Створити простий Job:
kubectl create job hello --image=busybox -- echo "Hello from job"kubectl get jobskubectl logs job/hellokubectl delete job hello- Створити Job з кількома завершеннями:
cat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: batch-processorspec: completions: 5 parallelism: 2 template: spec: containers: - name: processor image: busybox command: ["sh", "-c", "echo Processing $(hostname); sleep 3"] restartPolicy: NeverEOF
kubectl get jobs batch-processor -w # Спостерігати за завершеннямиkubectl get pods -l job-name=batch-processorkubectl delete job batch-processor- Створити Job, що завершується збоєм:
cat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: failing-jobspec: backoffLimit: 2 template: spec: containers: - name: fail image: busybox command: ["sh", "-c", "echo 'About to fail'; exit 1"] restartPolicy: NeverEOF
kubectl get jobs failing-job -wkubectl get pods -l job-name=failing-job # Кілька невдалих Подівkubectl logs job/failing-jobkubectl delete job failing-job- Створити CronJob:
kubectl create cronjob minute-job --image=busybox --schedule="*/1 * * * *" -- date
# Зачекати, поки виконаєтьсяsleep 70kubectl get cronjobskubectl get jobskubectl logs job/<job-name> # Використайте фактичну назву job
kubectl delete cronjob minute-job- Вручну запустити CronJob:
kubectl create cronjob backup --image=busybox --schedule="0 0 * * *" -- echo "backup"
# Запустити вручнуkubectl create job --from=cronjob/backup backup-nowkubectl get jobskubectl logs job/backup-now
kubectl delete cronjob backupkubectl delete job backup-nowКритерії успіху:
- Вмієте створювати Jobs імперативно та декларативно
- Розумієте completions та parallelism
- Вмієте налагоджувати невдалі Jobs
- Вмієте створювати CronJobs
- Вмієте вручну запускати CronJobs
Практичні вправи
Розділ «Практичні вправи»Вправа 1: Швидкісний тест створення Job (Ціль: 2 хвилини)
Розділ «Вправа 1: Швидкісний тест створення Job (Ціль: 2 хвилини)»# Створити jobkubectl create job quick --image=busybox -- echo "done"
# Зачекати завершенняkubectl wait --for=condition=complete job/quick --timeout=60s
# Перевірити логиkubectl logs job/quick
# Очищенняkubectl delete job quickВправа 2: Паралельний Job (Ціль: 3 хвилини)
Розділ «Вправа 2: Паралельний Job (Ціль: 3 хвилини)»cat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: parallelspec: completions: 6 parallelism: 3 template: spec: containers: - name: worker image: busybox command: ["sh", "-c", "echo Pod: $HOSTNAME; sleep 5"] restartPolicy: NeverEOF
# Спостерігатиkubectl get pods -l job-name=parallel -w &kubectl get job parallel -w &sleep 30kill %1 %2 2>/dev/null
# Очищенняkubectl delete job parallelВправа 3: Job із тайм-аутом (Ціль: 3 хвилини)
Розділ «Вправа 3: Job із тайм-аутом (Ціль: 3 хвилини)»cat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: timeout-testspec: activeDeadlineSeconds: 10 template: spec: containers: - name: long-task image: busybox command: ["sleep", "60"] restartPolicy: NeverEOF
# Спостерігати за тайм-аутом jobkubectl get job timeout-test -w &sleep 15kill %1 2>/dev/null
# Перевірити статусkubectl describe job timeout-test | grep -A3 "Conditions"
# Очищенняkubectl delete job timeout-testВправа 4: Створення CronJob (Ціль: 2 хвилини)
Розділ «Вправа 4: Створення CronJob (Ціль: 2 хвилини)»# Створити CronJobkubectl create cronjob every-minute --image=busybox --schedule="*/1 * * * *" -- date
# Перевіритиkubectl get cronjob every-minute
# Зачекати першого запускуsleep 70
# Перевірити створені jobskubectl get jobs -l job-name
# Очищенняkubectl delete cronjob every-minuteВправа 5: Ручний запуск CronJob (Ціль: 2 хвилини)
Розділ «Вправа 5: Ручний запуск CronJob (Ціль: 2 хвилини)»# Створити CronJob (не запуститься найближчим часом)kubectl create cronjob daily --image=busybox --schedule="0 0 * * *" -- echo "daily task"
# Запустити вручнуkubectl create job --from=cronjob/daily daily-manual-run
# Перевіритиkubectl get jobskubectl logs job/daily-manual-run
# Очищенняkubectl delete cronjob dailykubectl delete job daily-manual-runВправа 6: Пошук несправностей у невдалому Job (Ціль: 5 хвилин)
Розділ «Вправа 6: Пошук несправностей у невдалому Job (Ціль: 5 хвилин)»# Створити навмисно зламаний jobcat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: brokenspec: backoffLimit: 2 template: spec: containers: - name: app image: busybox command: ["sh", "-c", "cat /nonexistent/file"] restartPolicy: NeverEOF
# Діагностикаkubectl get job brokenkubectl get pods -l job-name=brokenkubectl describe job brokenkubectl logs job/broken
# Відповідь: Яка помилка? Як би ви її виправили?
# Очищенняkubectl delete job brokenВправа 7: Завдання — Повний робочий процес Job
Розділ «Вправа 7: Завдання — Повний робочий процес Job»Створіть Job, який:
- Виконує 4 завершення, 2 одночасно
- Кожен Під виводить своє ім’я хоста та чекає 3 секунди
- Має ліміт повторних спроб 2
- Автоматично видаляється через 60 секунд
# ВАШЕ ЗАВДАННЯ: Створіть цей JobВідповідь
cat << 'EOF' | kubectl apply -f -apiVersion: batch/v1kind: Jobmetadata: name: challenge-jobspec: completions: 4 parallelism: 2 backoffLimit: 2 ttlSecondsAfterFinished: 60 template: spec: containers: - name: worker image: busybox command: ["sh", "-c", "echo $HOSTNAME; sleep 3"] restartPolicy: NeverEOF
kubectl get job challenge-job -wНаступний модуль
Розділ «Наступний модуль»Модуль 2.5: Управління ресурсами — Requests, limits та класи QoS.