CronJob

CronJob

CronJob запускає одноразові Jobs за повторюваним розкладом.
СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.21

CronJob створює Jobs за повторюваним розкладом.

CronJob призначений для виконання регулярних запланованих дій, таких як резервне копіювання, генерація звітів та інше. Один обʼєкт CronJob подібний до одного рядка файлу crontab (таблиця cron) у системі Unix. Він запускає Job періодично за заданим розкладом, записаним у форматі Cron.

У CronJob є обмеження та особливості. Наприклад, за певних обставин один CronJob може створювати кілька одночасних Jobs. Див. обмеження нижче.

Коли панель управління створює нові Jobs і (опосередковано) Podʼи для CronJob, .metadata.name CronJob є частиною основи для назв цих Podʼів. Назва CronJob повинна бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності назва повинна відповідати суворішим правилам DNS-мітки. Навіть коли назва є DNS-піддоменом, вона не повинна бути довшою за 52 символи. Це тому, що контролер CronJob автоматично додає 11 символів до наданої вами назви, а довжина назви Job не повинна перевищувати 63 символи.

Приклад

Цей приклад маніфесту CronJob виводить поточний час та вітальне повідомлення щохвилини:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

(Виконання автоматизованих завдань за допомогою CronJob докладніше описує цей приклад).

Написання специфікації CronJob

Синтаксис розкладу

Поле .spec.schedule є обовʼязковим. Значення цього поля відповідає синтаксису Cron:

# ┌───────────── хвилина (0 - 59)
# │ ┌───────────── година (0 - 23)
# │ │ ┌───────────── день місяця (1 - 31)
# │ │ │ ┌───────────── місяць (1 - 12)
# │ │ │ │ ┌───────────── день тижня (0 - 6) (Неділя - Субота)
# │ │ │ │ │                                   АБО sun, mon, tue, wed, thu, fri, sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *

Наприклад, 0 3 * * 1 означає, що це завдання планується запускати щотижня в понеділок о 3 ранку.

Формат також включає розширені значення кроків "Vixie cron". Як пояснено в документації FreeBSD:

Значення кроків можна використовувати разом із діапазонами. Якщо після діапазону вказати /<number>, це задає крок із таким значенням у межах діапазону. Наприклад, 0-23/2 можна використовувати в полі годин для вказування виконання команди кожну другу годину (альтернативою в стандарті V7 є 0,2,4,6,8,10,12,14,16,18,20,22). Після зірочки також допускаються кроки, тому, якщо ви хочете сказати "кожні дві години", просто використовуйте */2.

Примітка:

Знак питання (?) у розкладі має той самий зміст, що й зірочка *, тобто позначає будь-яке доступне значення для даного поля.

Окрім стандартного синтаксису, також можна використовувати деякі макроси, такі як @monthly:

ЗаписОписЕквівалентно
@yearly (або @annually)Виконувати один раз на рік о півночі 1 січня0 0 1 1 *
@monthlyВиконувати один раз на місяць о півночі першого дня місяця0 0 1 * *
@weeklyВиконувати один раз на тиждень о півночі в неділю0 0 * * 0
@daily (або @midnight)Виконувати один раз на день о півночі0 0 * * *
@hourlyВиконувати один раз на годину на початку години0 * * * *

Для генерації виразів розкладу CronJob можна також використовувати вебінструменти, наприклад crontab.guru.

Шаблон Job

Поле .spec.jobTemplate визначає шаблон для Jobs, які створює CronJob, і воно обовʼязкове. Воно має точно таку саму схему, як Job, за винятком того, що воно вкладене і не має apiVersion або kind. Ви можете вказати спільні метадані для Jobs, створених за шаблоном, такі як мітки або анотації. Інформацію щодо написання .spec Job дивіться в розділі Написання специфікації Job.

Крайній термін для відкладеного запуску Job

Поле .spec.startingDeadlineSeconds є необовʼязковим. Це поле визначає крайній термін (у повних секундах) для запуску Job, якщо цей Job пропускає свій запланований час з будь-якої причини.

Після спливання крайнього терміну CronJob пропускає цей екземпляр Job (майбутні запуски все ще плануються). Наприклад, якщо у вас є Job резервного копіювання, який запускається двічі на день, ви можете дозволити йому запускатися із запізненням до 8 годин, але не пізніше, оскільки резервна копія, зроблена пізніше, не буде корисною: ви б натомість воліли дочекатися наступного запланованого запуску.

Jobs, які пропускають налаштований крайній термін, Kubernetes вважає невдалими. Якщо ви не вказали startingDeadlineSeconds для CronJob, екземпляри Job не мають крайнього терміну.

Якщо поле .spec.startingDeadlineSeconds встановлено (не є null), контролер CronJob вимірює час між тим, коли очікується створення Job, і поточним моментом. Якщо різниця перевищує цю межу, він пропускає це виконання.

Наприклад, якщо воно встановлене на 200, це дозволяє створити Job протягом 200 секунд після фактичного часу за розкладом.

Політика паралелізму

Поле .spec.concurrencyPolicy також є необовʼязковим. Воно визначає, як обробляти паралельні виконання Job, який створюється цим CronJob. Специфікація може вказувати лише одну з таких політик паралелізму:

  • Allow (стандартно): CronJob дозволяє паралельні запуски Jobs
  • Forbid: CronJob не дозволяє паралельні запуски; якщо настав час для нового запуску Job і попередній запуск Job ще не завершився, CronJob пропускає новий запуск Job. Також зауважте, що коли попередній запуск Job завершиться, .spec.startingDeadlineSeconds все одно враховується і може призвести до нового запуску Job.
  • Replace: Якщо настав час для нового запуску Job і попередній запуск Job ще не завершився, CronJob замінює поточний запуск Job новим запуском Job.

Зверніть увагу, що політика паралелізму застосовується лише до Jobs, створених тим самим CronJob. Якщо є кілька CronJobs, їхні відповідні Jobs завжди можуть виконуватися паралельно.

Призупинення розкладу

Ви можете призупинити виконання Jobs для CronJob, встановивши необовʼязкове поле .spec.suspend в значення true. Стандартно поле має значення false.

Це налаштування не впливає на Jobs, які CronJob вже розпочав.

Якщо ви встановите це поле в значення true, всі наступні виконання будуть призупинені (вони залишаються запланованими, але контролер CronJob не запускає Jobs для виконання задач), доки ви не скасуєте призупинення CronJob.

Увага:

Виконання, які призупинені під час запланованого часу, вважаються пропущеними Jobs. Коли .spec.suspend змінюється з true на false для наявного CronJob без крайнього терміну запуску, пропущені Jobs плануються негайно.

Обмеження історії Jobs

Поля .spec.successfulJobsHistoryLimit та .spec.failedJobsHistoryLimit вказують, скільки успішних та невдалих Jobs потрібно зберігати. Обидва поля є необовʼязковими.

  • .spec.successfulJobsHistoryLimit: Це поле вказує кількість успішно завершених Jobs, які слід зберігати. Стандартне значення — 3. Якщо встановити це поле в 0, успішні Jobs не зберігатимуться.

  • .spec.failedJobsHistoryLimit: Це поле вказує кількість невдало завершених Jobs, які слід зберігати. Стандартне значення — 1. Якщо встановити це поле в 0, невдалі Jobs не зберігатимуться.

Інший спосіб автоматичного очищення Jobs дивіться в розділі Автоматичне очищення завершених Jobs.

Часові пояси

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.27

Для CronJobs без вказаного часового поясу kube-controller-manager інтерпретує розклади відносно свого локального часового поясу.

Ви можете вказати часовий пояс для CronJob, встановивши .spec.timeZone на назву дійсного часового поясу. Наприклад, встановлення .spec.timeZone: "Etc/UTC" вказує Kubernetes інтерпретувати розклад відносно всесвітнього координованого часу.

База даних часових поясів зі стандартної бібліотеки Go включена до бінарних файлів і використовується як запасний варіант, якщо зовнішня база даних недоступна в системі.

Обмеження CronJob

Непідтримувані специфікації часових поясів

Зазначення часового поясу за допомогою змінних CRON_TZ або TZ всередині .spec.schedule офіційно не підтримується (і ніколи не підтримувалося). Якщо ви намагаєтеся встановити розклад, який включає вказування часового поясу TZ або CRON_TZ, Kubernetes не зможе створити чи оновити ресурс через помилку валідації. Натомість слід вказувати часові пояси, використовуючи поле часового поясу.

Зміна CronJob

За задумом CronJob містить шаблон для нових Jobs. Якщо ви змінюєте наявний CronJob, зміни застосовуватимуться до нових Jobs, які почнуть виконуватися після завершення вашої зміни. Jobs (та їхні Podʼи), які вже почали виконуватися, продовжують працювати без змін. Тобто CronJob не оновлює наявні Jobs, навіть якщо вони ще виконуються.

Створення Job

CronJob створює обʼєкт Job приблизно один раз за час виконання свого розкладу. Планування є приблизним, оскільки за певних обставин може бути створено два Jobs або жодного. Kubernetes намагається уникати таких ситуацій, але не повністю запобігає їм. Тому Jobs, які ви визначаєте, повинні бути ідемпотентними.

Починаючи з Kubernetes v1.32, CronJobs застосовують анотацію batch.kubernetes.io/cronjob-scheduled-timestamp до створених ними Jobs. Ця анотація вказує початковий запланований час створення Job і має формат RFC3339.

Якщо startingDeadlineSeconds встановлено на велике значення або залишено не встановленим (типово), і якщо concurrencyPolicy встановлено на Allow, Jobs завжди запускатимуться принаймні один раз.

Увага:

Якщо startingDeadlineSeconds встановлено у значення менше ніж 10 секунд, CronJob може не бути заплановано. Це повʼязано з тим, що контролер CronJob виконує перевірки кожні 10 секунд.

Для кожного CronJob контролер CronJob перевіряє, скільки розкладів він пропустив протягом часу від його останнього запланованого часу до теперішнього часу. Якщо пропущено понад 100 розкладів, то він не запускає Job і записує помилку в лог.

too many missed start times. Set or decrease .spec.startingDeadlineSeconds or check clock skew

Ця поведінка застосовується для планування наздоганяння і не означає, що CronJob припинить роботу.

Наприклад, під час використання concurrencyPolicy: Forbid довготривалі Jobs можуть призвести до пропуску запланованих часів, але новий Job може бути створений після завершення попереднього Job.

Важливо відзначити, що якщо поле startingDeadlineSeconds встановлено (не є nil), контролер підраховує, скільки пропущених Jobs сталося від значення startingDeadlineSeconds до теперішнього часу, а не від останнього запланованого часу до теперішнього часу. Наприклад, якщо startingDeadlineSeconds дорівнює 200, контролер підраховує, скільки Jobs було пропущено за останні 200 секунд.

CronJob вважається пропущеним, якщо не вдалося створити Job в запланований час. Наприклад, якщо concurrencyPolicy встановлено на Forbid і CronJob було спробовано запланувати, коли попередній Job все ще працював, то це враховуватиметься як пропуск.

Наприклад, припустимо, що CronJob встановлено для запуску нового Job кожну хвилину, починаючи з 08:30:00, і його поле startingDeadlineSeconds не встановлено. Якщо контролер CronJob виявиться недоступним з 08:29:00 по 10:21:00, Job не буде запущено, оскільки кількість пропущених Jobs, які пропустили свій розклад, понад 100.

Щоб краще проілюструвати цю концепцію, припустимо, що CronJob встановлено для запуску нового Job кожну хвилину, починаючи з 08:30:00, і його поле startingDeadlineSeconds встановлено на 200 секунд. Якщо контролер CronJob виявиться недоступним протягом того самого періоду, що й у попередньому прикладі (08:29:00 до 10:21:00), Job все одно запуститься о 10:22:00. Це трапляється тому, що тепер контролер перевіряє, скільки пропущених розкладів сталося за останні 200 секунд (тобто 3 пропущені розклади), а не від останнього запланованого часу до теперішнього часу.

CronJob відповідає лише за створення Job, які відповідають його розкладу, а Job, зі свого боку, відповідає за керування Podʼами, які він представляє.

Що далі

Змінено October 31, 2026 at 1:50 PM PST: [uk] Add workloads/controllers: cron-jobs, daemonset (8378abbc8e)