Очистка старых Jobs в Kubernetes: стратегии и практические рекомендации

Быстрые ссылки
CronJob History Retention Limits
Finished Job TTLs
Ручное удаление Jobs
Резюме
Введение
Kubernetes Jobs запускают Pod’ы пока не выполнится заданное количество успешных контейнеров. Jobs часто создаются автоматически через CronJob по расписанию. По умолчанию Kubernetes сохраняет объекты Jobs и их Pods после завершения, чтобы вы могли просмотреть статус и логи позже. Однако большое количество завершённых Jobs захламляет вывод kubectl и может привести к нагрузке на управляющие компоненты кластера.
В этой статье мы подробно рассмотрим основные способы очистки старых Jobs: встроенные механизмы CronJob, TTL для Job, ручные и пакетные удаления, а также практические советы по внедрению и отладке. Для каждого подхода приведены примеры команд, чеклисты и рекомендации по миграции.
Важно: автоматическое удаление освобождает пространство и упрощает наблюдение, но удалённые Jobs нельзя будет использовать для постфактумного анализа. Оцените потребности в логах и артефактах перед агрессивной очисткой.
CronJob: ограничения истории (History Retention Limits)
CronJob поддерживает автоматическое удаление Jobs, созданных самим CronJob. Это работает с Kubernetes начиная с v1.6 и позволяет настроить отдельные лимиты для успешных и неуспешных запусков.
Задайте поля
spec.successfulJobsHistoryLimitи
spec.failedJobsHistoryLimitв манифесте CronJob. Пример:
apiVersion: batch/v1
kind: CronJob
metadata:
name: demo-cron
spec:
schedule: "* * * * *"
successfulJobsHistoryLimit: 5
failedJobsHistoryLimit: 10
jobTemplate:
spec:
template:
spec:
containers:
- name: demo-cron
image: busybox:latest
command: ["/bin/sh", "-c", "Job complete!"]В примере выше CronJob будет сохранять 10 последних неуспешных и 5 последних успешных Job’ов — максимум 15 объектов одновременно. Job’ы удаляются только когда появляются более новые Job’ы с тем же статусом и превышается лимит.
По умолчанию (когда поля отсутствуют) Kubernetes обычно хранит 3 успешных Job’а и 1 неуспешный. Значение
0означает удалять Job сразу после завершения — не хранить историю.
Когда использовать
- Для регулярных Cron-рабочих нагрузок, где нужна только недавняя история запусков.
- Когда вы хотите разделять политику для успешных и неуспешных запусков.
Когда это не подойдёт
- Если Jobs создаются не через CronJob (например, ad-hoc Jobs), эти лимиты не применимы.
- Если требуется более гибкая логика удаления (по времени, по аннотациям, по внешним событиям).
TTL для завершённых Jobs (Finished Job TTLs)
Механизм TTL для Job стал стабильным в Kubernetes v1.23. TTL задаётся прямо на объекте Job и позволяет автоматически удалять Job и связанные Pods через фиксированное время после завершения.
Поле для настройки:
spec.ttlSecondsAfterFinishedПример Job с TTL 300 секунд (5 минут):
apiVersion: batch/v1
kind: Job
metadata:
name: demo-job
spec:
ttlSecondsAfterFinished: 300
template:
spec:
containers:
- name: demo-cron
image: busybox:latest
command: ["/bin/sh", "-c", "Job complete!"]Если Job определяется внутри CronJob, поле нужно вложить в jobTemplate:
apiVersion: batch/v1
kind: CronJob
metadata:
name: demo-cron
spec:
schedule: "* * * * *"
jobTemplate:
spec:
ttlSecondsAfterFinished: 300
template:
spec:
containers:
- name: demo-cron
image: busybox:latest
command: ["/bin/sh", "-c", "Job complete!"]Контроллер TTL в кластере отслеживает объекты Job, определяет истёкшее время и удаляет Job вместе с зависимыми ресурсами. Может быть небольшая задержка от истечения TTL до удаления.
Значение
0делает Job доступным для удаления сразу после завершения.
Поле mutable — его можно менять для уже созданных Job’ов, но изменения не гарантированно повлияют на ранее созданные исполнения, которые уже были помечены контроллером.
Преимущества и ограничения
- Преимущество: четкое поведение по времени, применимо ко всем Jobs независимо от источника (CronJob или ручной Job).
- Ограничение: удаление по TTL не даёт гибкости условной логики (например, очищать только если артефакты загружены в S3).
Ручное удаление Jobs
Вы всегда можете удалить Job вручную через kubectl.
Сначала получите список:
$ kubectl get jobsПример вывода:
NAME COMPLETIONS DURATION AGE
demo-cron-27549499 1/1 2s 36sЧтобы удалить конкретный Job:
$ kubectl delete job demo-cron-27549499Вы увидите:
job.batch "demo-cron-27549499" deletedЭто удалит Job и связанные Pods.
Пакетные удаления по полям
Можно удалять множество Job’ов одним вызовом, применяя fieldSelector. Например, удалить все успешные Job’ы в текущем namespace:
$ kubectl delete jobs --field-selector status.successful=1Удаление по меткам
Чтобы упростить удаление Job’ов, создаваемых конкретным CronJob, задайте метку в jobTemplate.metadata.labels:
apiVersion: batch/v1
kind: CronJob
metadata:
name: demo-cron
spec:
schedule: "* * * * *"
jobTemplate:
metadata:
labels:
cron-job: demo-cron
spec:
template:
spec:
containers:
- name: demo-cron
image: busybox:latest
command: ["/bin/sh", "-c", "Job complete!"]Затем удалить все Job’ы с этой меткой:
$ kubectl delete jobs -l cron-job=demo-cronМожно комбинировать метки и fieldSelector, чтобы, например, удалить только неуспешные Job’ы конкретного CronJob:
$ kubectl delete jobs -l cron-job=demo-cron --field-selector status.successful=0Стратегии автоматизации и скрипты
Если встроенные средства не покрывают ваши требования, используйте один из подходов:
- Лёгкий CronJob в Kubernetes, который периодически вызывает kubectl delete jobs по определённым селекторам.
- Kubernetes Operator, который реализует пользовательскую логику удаления (по аннотациям, по возрасту, по размеру логов и т.д.).
- CI/CD-пайплайн, который после успешной загрузки артефактов в хранилище пометит Job аннотацией и запустит его очистку.
Пример простого bash-скрипта для удаления Job’ов старше N дней (использует jq и kubectl):
#!/usr/bin/env bash
# Удалить Job'ы старше 7 дней
THRESHOLD_DAYS=7
kubectl get jobs -o json | jq -r '.items[] | select(.status.completionTime != null) | select((now - ((.status.completionTime|fromdateiso8601))) > (env.THRESHOLD_DAYS|tonumber*86400)) | .metadata.name' | xargs -r kubectl delete jobТакой скрипт можно упаковать в контейнер и запустить как CronJob в кластере.
Лучшие практики
- Предпочтительнее использовать TTL для Jobs там, где важен срок хранения. Это простая и надёжная политика.
- Для CronJob используйте successfulJobsHistoryLimit и failedJobsHistoryLimit для управления количеством сохранённых запусков.
- Если вам нужны логи длительное время — централизуйте логи (Fluentd/Logstash/Cloud Logging) и удаляйте Job’ы агрессивнее.
- Помечайте Jobs метками и аннотациями, чтобы потом удалять по селекторам.
- Не устанавливайте ttlSecondsAfterFinished=0 для важных задач, пока не уверены, что логи и артефакты доступны в другом месте.
Чеклист ролей
Администратор кластера:
- Внедрить политику по умолчанию для новых namespace (директивы, GitOps манифесты).
- Мониторить метрики контроллера API (latency, etcd size) для раннего обнаружения проблем с количеством объектов.
- Обеспечить систему централизованных логов и артефактов.
Разработчик / Владелец задания:
- Оценить, нужны ли логи Job’а после выполнения.
- Добавить ttlSecondsAfterFinished или установить историю в CronJob.
- Добавлять метки и аннотации, описывающие назначение и владельца.
SRE / Операции:
- Настроить мониторинг количества Job’ов и Pods, созданных Job’ами.
- Запланировать задачи по чистке для существующих исторических Job’ов.
- Тестировать восстановление сценариев, где истории нет (проверить, что логирование работает).
План миграции для существующих кластеров
- Инвентаризация: собрать список namespace и CronJob/Job с количеством завершённых Job’ов.
- Анализ: определить, какие Jobs критичны для отладки, какие можно удалить или сократить хранение.
- Внедрение: применить CronJob limits и/или добавить ttlSecondsAfterFinished в манифесты через GitOps.
- Очистка истории: запустить контролируемые пакетные удаления (kubectl delete jobs -l …) для старых записей.
- Мониторинг: наблюдать за влиянием на API-сервер, etсd и процессы отладки.
Критерии приёмки
- В каждом namespace применены политики хранения для >= 90% CronJob’ов.
- Общее число завершённых Jobs сократилось по сравнению с базовой линией на X% в течение 7 дней после внедрения (сравнение до/после).
- Сценарии отладки не нарушены: логи доступны либо в локальном хранилище, либо в централизованной системе.
Отладка и распространённые проблемы
Проблема: Jobs не удаляются после истечения TTL
- Проверьте, что контроллер TTL включён и работает (проверка логов контроллера kube-controller-manager или соответствующих Pod’ов контроллера).
- Убедитесь, что поле spec.ttlSecondsAfterFinished действительно задано и содержит корректное число.
- Есть небольшая задержка между истечением и удалением — подождите 30–60 секунд и проверьте снова.
Проблема: удаляются нужные для отладки Jobs
- Перед массовой очисткой убедитесь, что логи отправляются в централизованную систему.
- Используйте метки/аннотации, чтобы исключать критичные Jobs из автоматической очистки.
Проблема: слишком много объектов влияет на API-сервер
- Установите агрессивные лимиты хранения и/или TTL, чтобы уменьшить количество объектов.
- Рассмотрите shard-ирование CronJob’ов по namespace, чтобы избегать концентрации в одном namespace.
Набор тестов и критерии успеха
- Тест 1: Создать Job с ttlSecondsAfterFinished: 10 — убедиться, что Job и Pods удалены в течение 60 секунд после завершения.
- Тест 2: CronJob с successfulJobsHistoryLimit: 2 — запустить 4 успешных запуска и убедиться, что в списке сохраняются только 2 последних.
- Тест 3: Метки и пакетное удаление — пометить Job’ы и удалить их селектором, убедиться, что удалены только помеченные объекты.
Decision flowchart
flowchart TD
A[Начало: есть лишние Job'ы?] --> B{Job создаётся через CronJob?}
B -- Да --> C{Нужна история успешных запусков?}
C -- Да --> D[Настроить successfulJobsHistoryLimit]
C -- Нет --> E[Настроить ttlSecondsAfterFinished или successfulJobsHistoryLimit=0]
B -- Нет --> F{Нужно удалять по времени?}
F -- Да --> E
F -- Нет --> G[Добавить метки + ручная очистка или скрипт]
D --> H[Мониторинг и проверка]
E --> H
G --> H
H --> I[Готово]Сравнение подходов (кратко)
- CronJob history limits: просты в настройке, управляют количеством экземпляров, подходят только для CronJob.
- TTL (ttlSecondsAfterFinished): применим ко всем Jobs, детерминирован по времени, требует работающего контроллера.
- Ручные и скриптовые удаления: гибкость, но оперативная нагрузка и риск ошибок.
Безопасность и приватность
- Убедитесь, что централизованная система логирования защищена и соответствует требованиям приватности — удаление Job’ов не должно означать потерю критичных данных.
- При автоматической очистке используйте RBAC и ограничьте права на массовое удаление.
Резюме
Kubernetes по умолчанию сохраняет завершённые Jobs и их Pods, что упрощает отладку, но может привести к накоплению объектов и нагрузке на управляющие компоненты. Для управления хранением используйте:
- successfulJobsHistoryLimit и failedJobsHistoryLimit для CronJob’ов;
- spec.ttlSecondsAfterFinished для любых Job’ов;
- метки и пакетные удаления через kubectl для ручного контроля;
- автоматические скрипты, CronJob’ы или Operators для нестандартной логики.
Выберите стратегию в зависимости от требований к отладке, объёма логов и отношения к ретенции — и автоматизируйте этот процесс, чтобы поддерживать кластер в здравом состоянии.
Ключевые документы и команды
kubectl get jobs kubectl delete job
Шаблон SOP для включения TTL в GitOps
- Добавить поле spec.ttlSecondsAfterFinished во все Job- и CronJob-манифесты в репозитории.
- Открыть MR/PR с описанием влияния и тестовым планом.
- Применить в staging, запустить тесты по приёмке.
- Применить в production поэтапно.
Контрольный список после внедрения
- TTL/limits добавлены в репозитории
- Мониторинг количества Job’ов настроен
- Централизованная система логов проверена
- Документация для разработчиков обновлена
Похожие материалы
Chrome OS Flex на старом ПК — руководство
VIZ Manga: руководство по использованию
Чёрный экран в Steam — устранение и проверка
Изменить формат скриншотов в macOS
Параллакс-скроллинг в Arcade