diff --git a/content/ru/docs/concepts/workloads/controllers/cron-jobs.md b/content/ru/docs/concepts/workloads/controllers/cron-jobs.md new file mode 100644 index 0000000000..346cf6c7ce --- /dev/null +++ b/content/ru/docs/concepts/workloads/controllers/cron-jobs.md @@ -0,0 +1,233 @@ +--- +title: CronJob +content_type: concept +description: >- + CronJob запускает одноразовые задания по повторяющемуся расписанию +weight: 80 +hide_summary: true # Listed separately in section index +--- + + + +{{< feature-state for_k8s_version="v1.21" state="stable" >}} + +_CronJob_ создает {{< glossary_tooltip term_id="job" text="задания (Jobs)" >}}, которые повторяются по расписанию. + +CronJob предназначен для выполнения регулярных заданий по расписанию, таких как резервное копирование, создание отчетов, +и так далее. Один CronJob объект — это как одна строка файла _crontab_ (cron table) в Unix-системе. +Он периодически запускает задание по заданному расписанию, составленному в формате формате +[Cron](https://ru.wikipedia.org/wiki/Cron). + +У CronJob'a есть свои ограничения и особенности. +Например, при определенных обстоятельствах один CronJob может создавать несколько параллельных заданий. См. раздел [Ограничения](#cron-job-limitations) ниже. + +Когда управляющий слой _(control plane)_ создает новые задания и (косвенно) поды для CronJob'а, поле `.metadata.name` в CronJob +является частью основы для наименования этих подов. Имя CronJob должно быть действительным +значением [поддомена DNS](/ru/docs/concepts/overview/working-with-objects/names#имена-поддоменов-dns), но это может привести к неожиданным результатам для имен хостов подов. Для наилучшей совместимости имя должно соответствовать более строгим правилам +[имен меток DNS](/ru/docs/concepts/overview/working-with-objects/names#имена-меток-dns). +Даже если имя является поддоменом DNS, оно не должно превышать 52 символов. Это связано с тем, что контроллер CronJob автоматически добавляет +11 символов к указанному вами имени и существует ограничение на то, что +длина имени задания (Job) не должна превышать 63 символа. + + +## Пример + +Этот пример манифеста CronJob печатает текущее время и сообщение hello каждую минуту: + +{{% code_sample file="application/job/cronjob.yaml" %}} + +([Выполнение автоматических заданий с помощью CronJob](/docs/tasks/job/automated-tasks-with-cron-jobs/) +более подробно рассматривает этот пример.) + +## Написание спецификации CronJob'a +### Синтаксис расписания +Поле `.spec.schedule` является обязательным. Значение этого поля соответствует синтаксису [Cron](https://ru.wikipedia.org/wiki/Cron): + +``` +# ┌───────────── минута (0 - 59) +# │ ┌───────────── час (0 - 23) +# │ │ ┌───────────── день месяца (1 - 31) +# │ │ │ ┌───────────── месяц (1 - 12) +# │ │ │ │ ┌───────────── день недели (0 - 6) (воскресенье - суббота) +# │ │ │ │ │ ИЛИ sun, mon, tue, wed, thu, fri, sat +# │ │ │ │ │ +# * * * * * +``` + +Например, `0 0 13 * 5` указывает, что задание должно запускаться каждую пятницу в полночь, а также 13 числа каждого месяца в полночь. + +Формат также включает расширенные значения шагов "Vixie cron". Как объясняется в +[инструкции для FreeBSD](https://www.freebsd.org/cgi/man.cgi?crontab%285%29): + +> Значения шагов можно использовать в сочетании с диапазонами. Если после диапазона указать `/<число>`, то это означает +> пропуск значения числа в диапазоне. Например, `0-23/2` можно использовать, чтобы указать выполнение команды +> каждый второй час (альтернативой в стандарте V7 является +> `0,2,4,6,8,10,12,14,16,18,20,22`). Шаги также разрешены после звездочки, так что если +> нужно указать "каждые два часа", можно использовать `*/2`. + +{{< note >}} +Вопросительный знак (`?`) в расписании обозначает то же, что и звездочка `*`, то есть любое из доступных значений для данного поля. +{{< /note >}} + +Помимо стандартного синтаксиса можно также использовать макросы вроде `@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](https://crontab.guru/). + +### Шаблон задания + +Поле `.spec.jobTemplate` определяет шаблон для заданий, которые создает CronJob, и является обязательным. +Он имеет точно такой же вид, как и [Job](/docs/concepts/workloads/controllers/job/), за исключением того, +что является вложенным и не имеет полей `apiVersion` и `kind`. +Можно указать типичные метаданные для шаблонных заданий (Jobs), такие как +{{< glossary_tooltip text="метки" term_id="label" >}} или +{{< glossary_tooltip text="аннотации" term_id="annotation" >}}. +О том, как написать `.spec` для Job, см. [Написание спецификации Job](/docs/concepts/workloads/controllers/job/#writing-a-job-spec). + +### Дедлайн задержки начала задания {#starting-deadline} + +Поле `.spec.startingDeadlineSeconds` является необязательным. +В этом поле задается крайний срок (в целых секундах) для запуска задания (Job), если оно по какой-либо причине +не успевает к назначенному времени. + +Если дедлайн пропущен, CronJob пропускает этот вызов задания (последующие выполнения по-прежнему запланированы). +Например, если задание резервного копирования выполняется дважды в день, можно разрешить ему +запускаться с опозданием до 8 часов, но не позже, поскольку резервная копия, +сделанная позже, не будет полезной: лучше дождаться следующего запуска по расписанию. + +Задания, которые не успели выполниться в установленный срок, Kubernetes рассматривает как неудачные. +Если не указать `startingDeadlineSeconds` для CronJob, то задания не будут иметь дедлайн. + +Если поле `.spec.startingDeadlineSeconds` установлено (не является нулевым), контроллер CronJob +измеряет время между моментом, когда задание должно быть создано, и реальным временем. +Если разница превышает указанный предел, он пропустит этот вызов задания. + +Например, если установлено значение `200`, задание может быть создано в период до 200 секунд позже фактического расписания. + +### Политика параллелизма (concurrency policy) + +Поле `.spec.concurrencyPolicy` также является необязательным. +Оно определяет, как обращаться с одновременным выполнением заданий, созданных этим CronJob. +В этой спецификации может быть указана только одна из следующих политик параллелизма: + +* `Allow` (по умолчанию): CronJob разрешает одновременное выполнение заданий. +* `Forbid`: CronJob не разрешает одновременное выполнение заданий; если пришло время для выполнения нового задания, + а предыдущее еще не завершилось, CronJob пропускает новое задание. +* `Replace`: Если пришло время для выполнения нового задания, а предыдущее еще не завершилось, + CronJob заменит текущее задание на новое. + +Заметьте, что принцип параллелизма применяется только к заданиям, созданным одним и тем же Cronjob'ом. +Если есть несколько CronJob'ов, их соответствующие задания всегда могут выполняться одновременно. + +### Остановка выполнения заданий по расписанию + +Можно приостановить выполнение CronJob-заданий, присвоив необязательному полю `.spec.suspend` значение true. +По умолчанию это поле имеет значение false. + +Эта настройка _не_ влияет на задания, которые уже были запущены CronJob'ом. + +Если установить это поле как true, все последующие выполнения будут приостановлены +(они остаются запланированными, но CronJob-контроллер не запускает задания для выполнения), +пока вы не отмените приостановку CronJob'a. + +{{< caution >}} +Работы, приостановленные во время запланированного выполнения, считаются пропущенными. +Когда `.spec.suspend` изменяется с `true` на `false` для существующего CronJob'a без +[дедлайна задержки начала задания](#starting-deadline), пропущенные задания планируются немедленно. +{{< /caution >}} + +### Лимиты на историю заданий + +Поля `.spec.successfulJobsHistoryLimit` и `.spec.failedJobsHistoryLimit` являются необязательными. +В этих полях указывается, сколько завершенных и неудачных заданий должно быть сохранено в истории. +По умолчанию они установлены на 3 и 1 соответственно. Установка предела в `0` будет означать, +что никакие задания соответствующего типа не сохранятся после их завершения. + +Другой способ автоматической очистки заданий см. в разделе [Автоматическая очистка завершенных заданий](/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically). + +### Часовые пояса + +{{< feature-state for_k8s_version="v1.27" state="stable" >}} + +Для CronJob'a, в которых не указан часовой пояс, {{< glossary_tooltip term_id="kube-controller-manager" text="kube-controller-manager" >}} +интерпретирует расписания относительно своего локального часового пояса. + +Можно указать часовой пояс для CronJob'a, присвоив `.spec.timeZone` имя действительного +[часового пояса](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). +Например, установка `.spec.timeZone: "Etc/UTC"` инструктирует Kubernetes интерпретировать расписание +относительно всемирного координированного времени. + +База данных часовых поясов из стандартной библиотеки Go включена в бинарные файлы и используется в качестве запасного варианта на случай, если внешняя база данных недоступна в системе. + +## Ограничения CronJob {#cron-job-limitations} + +### Неподдерживаемая спецификация TimeZone + +Установка часового пояса с помощью переменных `CRON_TZ` или `TZ` в `.spec.schedule` +**не поддерживается официально** (и никогда не поддерживалась). + +Начиная с Kubernetes 1.29, если попытаться задать расписание, +включающее спецификацию часового пояса `TZ` или `CRON_TZ`, +Kubernetes не сможет создать ресурс, выдав ошибку валидации. +Обновления для CronJobs, уже использующих `TZ` или `CRON_TZ`, будут продолжать выдавать +[предупреждение](/blog/2020/09/03/warnings/) клиенту. + +### Модификация задания CronJob + +По своей структуре CronJob содержит шаблон для _новых_ заданий. +Если изменить существующее задание CronJob, внесенные изменения будут +применены к новым заданиям, которые начнут выполняться после завершения +модификации. Задания (и их поды), которые уже были запущены, продолжат выполняться без изменений. +То есть CronJob _не_ обновляет существующие задания, даже если они остаются запущенными. + +### Создание заданий + +CronJob создает объект задания (Job) примерно один раз за время выполнения своего расписания. +Расписание является приблизительным, поскольку есть определенные обстоятельства, +при которых могут быть созданы два задания или не создано ни одного. +Kubernetes старается избегать таких ситуаций, но не может полностью предотвратить их. Поэтому +задания, которые вы определяете, должны быть _идемпотентными_. + +Если в поле `startingDeadlineSeconds` задано большое значение или оно не определено (по умолчанию), +а также при условии, что `concurrencyPolicy` имеет значение `Allow`, задания всегда будут выполняться по крайней мере один раз. + +{{< caution >}} +Если `startingDeadlineSeconds` имеет значение меньше 10 секунд, задание CronJob, возможно, не будет запланировано. Это происходит потому, что CronJob выполняет проверку каждые 10 секунд. +{{< /caution >}} + + +Для каждого задания CronJob {{< glossary_tooltip term_id="controller" text="контроллер" >}} проверяет, сколько расписаний он пропустил за время, прошедшее с последнего расписания до настоящего момента. Если пропущено более 100 расписаний, то задание не запускается и фиксируется ошибка. + +``` +Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew. +``` + +Важно отметить, что если поле `startingDeadlineSeconds` установлено (не равно `nil`), контроллер считает, сколько пропущенных заданий произошло с момента значения `startingDeadlineSeconds` до настоящего момента, а не с момента последнего запланированного задания до настоящего момента. Например, если `startingDeadlineSeconds` равно `200`, контроллер подсчитывает, сколько пропущенных заданий произошло за последние 200 секунд. + +Задание CronJob считается пропущенным, если оно не было создано в запланированное время. Например, если для `concurrencyPolicy` установлено значение `Forbid`, и CronJob пытался быть запланирован, когда предыдущее расписание еще выполнялось, то он будет считаться пропущенным. + +Например, предположим, что задание CronJob настроено на планирование нового задания каждую минуту, начиная с `08:30:00`, а его поле поле `startingDeadlineSeconds` не установлено. +Если контроллер CronJob не функционирует с `08:29:00` до `10:21:00`, задание не будет запущено, так как количество пропущенных заданий, которые не успели выполнить свое расписание, больше 100. + +Чтобы подробнее проиллюстрировать эту концепцию, предположим, что задание CronJob настроено на планирование нового задания каждую одну минуту, начиная с `08:30:00`, и его параметр `startingDeadlineSeconds` установлен на 200 секунд. Если контроллер CronJob вдруг не функционирует в течение того же периода, что и в предыдущем примере (с `08:29:00` по `10:21:00`), задание все равно начнется в 10:22:00. Это происходит потому, что контроллер в данном случае проверяет, сколько пропущенных запланированных заданий было за последние 200 секунд (т. е. 3 пропущенных расписания), а не с момента последнего запланированного времени до настоящего момента. + +CronJob отвечает только за создание заданий (Jobs), соответствующих его расписанию, а задание, в свою очередь, отвечает за управление подами, которые оно представляет. + +## {{% heading "whatsnext" %}} + +* Ознакомьтесь с [Подами](/docs/concepts/workloads/pods/) и + [Заданиями](/docs/concepts/workloads/controllers/job/) — двумя концепциями, на которые опираются CronJobs. +* Ознакомьтесь с подробным [форматом](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-CRON_Expression_Format) + полей CronJob `.spec.schedule`. +* Для инструкции по созданию и работе с CronJob, а также для примера + CronJob-манифеста см. раздел [Выполнение автоматизированных задач с помощью CronJob](/docs/tasks/job/automated-tasks-with-cron-jobs/). +* `CronJob` является частью Kubernetes REST API. + Для получения более подробной информации прочтите справочник по {{< api-reference page="workload-resources/cron-job-v1" >}} API. +