RU localisation of concepts/workloads/controllers/cron-jobs.md

Co-Authored-By: Dmitry Shurupov <dmitry.shurupov@palark.com>
pull/44766/head
sergey gabrichidze 2024-01-16 16:30:58 +01:00
parent a66ab77922
commit 0b14d74113
1 changed files with 233 additions and 0 deletions

View File

@ -0,0 +1,233 @@
---
title: CronJob
content_type: concept
description: >-
CronJob запускает одноразовые задания по повторяющемуся расписанию
weight: 80
hide_summary: true # Listed separately in section index
---
<!-- overview -->
{{< 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 символа.
<!-- body -->
## Пример
Этот пример манифеста 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.