Kubernetes CronJob: чому завдання не запускаються за розкладом
CronJob виглядає найпростішою сутністю в кластері: розклад, образ, команда — далі середовище саме підіймає завдання.
Саме тому збій розкладу помічають із затримкою, коли у звітах спливає пропущений запуск завдання або дублювання регламентних задач: те саме вивантаження, звірка чи розсилка відпрацьовує двічі.
Планувальник не будить завдання точно за розкладом — він звіряє час у циклі. Якщо керівний контур перезапускався, вузол був недоступний або розклад задано частіше за крок звірки, вікно запуску проходить повз.
Параметр startingDeadlineSeconds вирішує, скільки запізнення ще припустиме, а concurrencyPolicy: Forbid не дає новому екземпляру стартувати поверх працюючого.
Дублювання найчастіше походить від політики Allow та довгого завдання: наступний запуск настає, коли попередній ще пише в ту саму таблицю. Той самий ефект дають кілька реплік керівного контуру без обраного лідера та ручні «надолуження» після інциденту.
Завислі процеси в кластері — окремий клас. Без activeDeadlineSeconds та ліміту повторів завдання може висіти добами: екземпляр не виходить із Pending через квоти, не підіймається образ, контейнер не завершується за сигналом. Такий процес тримає ресурси й блокує наступний за політикою заборони.
Нарешті, втрачені результати: успішний екземпляр видаляється, логи йдуть разом із ним, а історія зберігає лише кілька останніх запусків. Звідси картина «завдання пройшло, але результату немає». Розбираємо, як кожен клас збоїв закривається конфігурацією, а не чергуванням.
Керовані завдання за розкладом: ефект для команди
Регламентні завдання перестають бути точкою ризику, коли розклад, ліміти та політика перезапуску описані в маніфестах Kubernetes, а не відновлюються вручну після кожного збою. Ефект вимірний: частка втрачених запусків, час відновлення та кількість ручних втручань чергового.
Скорочення ручних перезапусків
Обмеження часу виконання та політика повторів не дають завданню зависнути й заблокувати наступне вікно. Причину падіння видно в історії запусків, тому типовий збій закривається правкою маніфесту, а не перезапуском «навмання». Кількість ручних розборів скорочується з кількох на тиждень до поодиноких на квартал.
Передбачуване навантаження на кластер
Розклади розведені за часом, для завдань задані запити та ліміти ресурсів, паралельні запуски обмежені. Піки перестають припадати на робочі години: нічні завдання не конкурують із сервісами, і кластер не йде в чергу на обслуговування.
Швидке відновлення після збою
Повернення до роботи — відкат маніфесту та повторний прогін пропущеного вікна, а не відновлення з резервної копії. Час відновлення падає з десятків хвилин до одиниць: порядок дій відомий заздалегідь і не залежить від того, хто на чергуванні.
Пропущене вікно перестає бути непомітним — розходження видно в моніторингу того самого дня. Розклад стає відтворюваним артефактом: його можна передати іншій команді або розгорнути в новому середовищі без усних інструкцій.
Kubernetes CronJob: варіанти запуску та їхні обмеження
Регламентна задача в кластері рідко буває одна: вивантаження звіту, ротація ключів, чищення застарілих записів, перерахунок агрегатів.
CronJob закриває розклад, але не відповідає на два питання — скільки копій завдання припустимо одночасно і що робити, якщо попередній прохід ще не завершився. Звідси чотири режими, між якими реально вибирають.
Річ не в тому, «який інструмент кращий», а в тому, де живе блокування і хто відповідає за пропущений запуск. Межі застосовності кожного варіанта:
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Одиничний запуск — завдання із забороною паралельних копій | Ідемпотентне завдання, вкладається в інтервал розкладу | Довгий прохід витісняє наступний; пропущений слот не переноситься |
| Розподілений запуск із блокуванням | Кілька реплік або кластерів претендують на одну роботу | Потрібен зовнішній координатор та оренда блокування з таймаутом, інакше при відмові власника завдання стає |
| Запуск поза кластером | Важке завдання з довгим вікном і доступом до зовнішніх систем | Немає історії запусків і повторів засобами кластера; моніторинг і секрети збираються окремо |
| Штатний планувальник без блокування | Легкі періодичні завдання всередині кластера | Роздільність розкладу — хвилини; пропуски відсікаються за startingDeadlineSeconds, часовий пояс задається явно |
На практиці режими змішують: розклад і запуск залишають планувальнику, а блокування та захист від накладання виносять у сам обробник — тоді перенесення завдання за межі кластера не ламає логіку.
Стежити варто не за фактом «под відпрацював», а за результатом: метрикою успішних проходів, часом останнього завершення та кількістю пропущених слотів.
Порядок впровадження: від аудиту розкладів до передачі
Впровадження починається не з маніфестів, а з інвентаризації: cron на серверах, таймери, планувальник у системі збирання та вже наявні завдання в кластері. Уже тут видно, які з них конкурують за ресурси, де розклади перекриваються за часом і які падіння ніхто не помічав місяцями.
- Аудит поточних розкладів. Зводимо завдання в таблицю: періодичність, фактична тривалість, залежності за даними, власник. Позначаємо дублі та ті, що запускаються частіше, ніж потрібно.
- Схема запуску завдань. Для кожного фіксуємо політику паралелізму, граничний час виконання, ліміти ресурсів і глибину зберігання історії завершених запусків.
- Налаштування повторних спроб. Задаємо кількість повторів, затримку між ними та політику перезапуску контейнера; окремо вирішуємо, що робити із завданням, яке не вклалося у відведене вікно.
- Перевірка відмовостійкості. Валимо pod, вимикаємо зовнішню залежність, навантажуємо вузол — завдання має перезапуститися, не створити дублів і не заблокувати наступне за розкладом.
- Спостережуваність. Налаштовуємо метрики успішних і невдалих запусків, оповіщення про пропущене вікно та журнал, за яким причина збою видна без ручного розбору.
- Передача супроводу. Віддаємо схему розкладів, конфігурації, інструкції щодо типових збоїв і порядок внесення змін.
Кожен етап закінчується перевірюваним артефактом: оновленим розкладом, конфігурацією, звітом про прогін перевірок на відмову. Так знімається головний ризик — коли завдання живуть самі по собі і про збій дізнаєшся від суміжної команди, а не від оповіщення.
Комплект артефактів: маніфести, політики, регламенти
Роботи закінчуються не «налаштованим кластером», а комплектом, який можна передати іншій команді та відтворити з нуля.
Усе лежить у репозиторії з історією змін: маніфести застосовуються декларативно, відмінності між контурами описані явно, а не правляться вручну на робочому середовищі.
- Опис конфігурації завдань — маніфести з явними
concurrencyPolicy,backoffLimit, лімітами ресурсів і політикою зберігання завершених подів; окремо зафіксовано, чому вибрано саме такі значення. - Політики доступу та ролі — сервісні облікові записи під кожне завдання, права в межах простору імен, мережеві політики, секрети із зовнішнього сховища замість значень у маніфестах.
- Схема середовищ — розділення контурів розробки, передпродакшену та робочого, перевизначення значень за середовищем, порядок просування змін і відкату.
- Моніторинг і оповіщення — метрики запусків та їхньої тривалості, правила оповіщення про пропущений розклад, повторні відмови та завислі завдання.
- Регламент обробки збоїв — що робить черговий при падінні завдання, як призупинити розклад через
suspendі перезапустити пропущений запуск без дублів. - Документація супроводу — призначення кожного розкладу, залежності від зовнішніх систем, типові операції та точки, де потрібне втручання людини.
Комплект передаємо разом із розбором: інженер замовника проходить по ньому і повторює розгортання на тестовому контурі, після чого супровід можна вести власними силами.
Практика: як скоротили частку втрачених запусків
Клієнт прийшов із платформною командою, у якої за розкладом працювало близько 120 задач: нічні вивантаження, звірки залишків, перерахунок умов, розсилки. Частина запусків пропадала — і дізнавалися про це зі скарг бізнесу, а не із сигналу моніторингу.
Що показували метрики до
Частка втрачених запусків трималася на рівні 8–9% на добу. Приблизно половина з них — тихі пропуски: задача не стартувала або не завершилася, але жоден алерт не спрацював.
Середній час реакції на збій становив кілька годин, бо єдиним сигналом був дзвінок із відділу, який чекав звіту.
Що змінили
Звели розклади в один контур управління на Kubernetes: задали startingDeadlineSeconds, щоб надто пізно піднята задача не накладалася на наступне вікно, concurrencyPolicy: Forbid для пересічних завдань і backoffLimit з activeDeadlineSeconds замість нескінченних повторів.
Алерт поставили не на падіння, а на відсутність успішного завершення за вікно, плюс TTL для історії завершених завдань. Самі задачі зробили ідемпотентними — повтор після збою більше не дублював списання та відправлення.
Що стало
Частка втрачених запусків знизилася з 8–9% до 0,2–0,4%, час реакції на збій — з кількох годин до 1–2 хвилин. Клас відмов «пропущений запуск, про який ніхто не дізнався» закрито: сам пропуск вікна став подією контролю виконання завдань.
Чим завдання за розкладом відрізняються від робочих черг?
Межа проходить за джерелом істини. Завдання за розкладом запускає час: планувальник сам вирішує, що момент настав, і стартує процес, не перевіряючи, чи є для нього робота. Черга запускає подію: поки нова задача не прийшла, обробник чекає і не займає ресурси.
Звідси й різні класи відмов. У розкладу — перекриття та пропуски: два запуски одного перерахунку накладаються один на одного, довгий прогін з'їдає наступний, а зупинка планувальника залишається непоміченою.
Закривається це політикою одночасності, припустимим вікном запізнення та зберіганням історії запусків, за якою видно і успіх, і падіння. У черги — повторна доставка та «завислі» задачі, які впали й не повернулися в роботу без окремої перевірки.
І там, і там обов'язкова ідемпотентність операцій.
Повторний нічний перерахунок або повторно доставлена подія не повинні списати двічі, надіслати другий лист або створити дубль замовлення — ключ ідемпотентності та звірка з поточним станом у базі вирішують це незалежно від способу запуску.
Вибір простий: регламент без зовнішнього тригера — звіти, синхронізація довідників, чищення та архівація — іде за розкладом. Потік подій — замовлення, вебхуки, файли — іде через чергу, де кількість обробників зростає разом із довжиною черги.
Робочий компроміс — гібрид: завдання в Kubernetes не виконує роботу саме, а лише наповнює чергу, а обробку та повтори ведуть окремі виконавці.
Технічні питання, які задають перед стартом
Перед стартом майже завжди спливають ті самі сумніви: як розклад переживе оновлення кластера, що робити із затяжним завданням і звідки беруться подвійні запуски. Нижче — чотири питання, які найчастіше впливають на схему розміщення.
Завдання може запуститися двічі — як це виключити?
Дублі з'являються, коли попередній запуск не встиг закінчитися до наступного. Поведінку задає політика одночасності: Forbid пропускає новий запуск, Replace зупиняє поточний і стартує свіжий. Для вивантажень і запису в одну таблицю ставимо Forbid.
Що робити, якщо завдання зависло?
Зависання ловимо таймаутом самого завдання: activeDeadlineSeconds знімає под примусово, backoffLimit обмежує повтори, ttlSecondsAfterFinished прибирає відпрацьовані об'єкти. Додатково стежимо за часом останнього успішного запуску — воно зростає раніше, ніж спрацює таймаут.
Чи переживе завдання оновлення кластера?
При оновленні вузли виводяться з роботи і под переривається. Короткі задачі переживають це завдяки повторам, довгі переносимо у вікна, вільні від обслуговування, і робимо ідемпотентними, щоб повтор не псував дані. Опис завдання тримаємо в актуальній версії — інакше оновлений кластер його не прийме.
Як обмежити час виконання?
Обмеження за часом не дає задачі висіти вічно й накладатися на наступний запуск. Якщо робота не вкладається в інтервал розкладу, виносимо її в окремий контур або подовжуємо період — інакше частина запусків буде пропускатися.
Обговоримо задачу: розберемо розклади та точки відмови
Щоб повернутися з оцінкою та планом робіт за розкладами, нам потрібен зріз середовища, а не формулювання «періодичні задачі іноді не спрацьовують». Опишіть задачу — звіримо її зі схемою та запропонуємо конфігурацію, яку можна впроваджувати без зупинки сервісів.
Що надіслати як ввідні для оцінки:
- схему поточного середовища: кластери та контури, чим відрізняються параметри запуску між ними;
- перелік періодичних задач: розклад, типова тривалість, залежності між кроками, припустиме вікно затримки;
- як запуск влаштований зараз: планувальник усередині застосунку, системний таймер або ручний скрипт;
- вимоги до поведінки після збою: що станеться при подвійному виконанні тієї самої задачі;
- скільки зберігати історію успішних і неуспішних спроб і чи потрібен відкат на попереднє збирання;
- чинні правила оповіщення та відомі точки відмови: куди приходять сигнали і хто читає їх поза робочим часом;
- обмеження контуру: мережеві політики, доступи до зовнішніх ресурсів, вікна обслуговування.
На виході ви отримаєте карту задач з оцінкою ризику, план робіт за розкладами за етапами та набір перевірок, що доводять, що запуск дійсно пройшов і результат записано. Надішліть ввідні — повернемося з оцінкою та планом.







