Очистка хранилища S3
В хранилище S3, используемом системой TRON.ASOC, накапливаются данные сканирования, такие как необработанные результаты сканирования, отчеты, SBOM-файлы, файлы созданных полей и другие объекты. Для того, чтобы объем хранимых данных не увеличивался неконтролируемо, в системе реализованы следующие механизмы удаления данных из хранилища S3.
Механизмы очистки хранилища S3
Очистка хранилища основана на двух независимых механизмах:
- автоматическое удаление по сроку жизни (TTL) — этот механизм применяется к сгенерированным отчетам и необработанным результатам сканирования;
- каскадное удаление при удалении сущностей — необработанные результаты сканирования удаляются при удалении проверки безопасности, слоя или проекта, связанного с этими данными.
Физическое удаление данных из S3 выполняется асинхронно, через внутреннюю очередь задач. Такой способ удаления не влияет на скорость обработки пользовательских запросов и позволяет корректно обрабатывать временную недоступность хранилища.
Удаляемые файлы
Из хранилища удаляются файлы, представленные в таблице ниже.
| Тип файла | Бакет S3 | Название объекта | Удаление по TTL | Удаление вручную |
|---|---|---|---|---|
| Необработанные результаты сканирования | scan-results | <scan_result_id>.json | Да | При удалении проверки/слоя/проекта |
| ASOC-отчет | REPORT_BUCKET_NAME (по умолчанию reports) | Значения из report.result.files | Да | При удалении отчета через Reports API |
| SBOM | sbom | <sbom_id>.json | Нет | При замене SBOM |
| Файл созданного поля | custom-field-files | storage_path из БД | Нет | Через FileFieldService |
Автоматическая очистка по TTL не затрагивает SBOM и файлы созданных полей — они удаляются только вручную.
Настройка автоматической очистки (TTL)
Автоматическая очистка хранилища управляется переменной окружения STORAGE_CLEANUP_TTL_DAYS сервиса core.
Переменная может иметь следующие значения:
0— автоматическая очистка по TTL отключена, ручное удаление (при удалении сущностей) продолжает работать. Это значение устанавливается по умолчанию;N > 0— удаляются файлы старшеNдней;- отрицательное значение — автоматическая очистка по TTL отключена.
Изменение значения STORAGE_CLEANUP_TTL_DAYS применяется только после перезапуска сервиса core.
Перед включением TTL на большом объеме данных рекомендуется оценить количество кандидатов на удаление (dry-run), чтобы исключить непредвиденную нагрузку на воркер и S3.
Значение переменной STORAGE_CLEANUP_TTL_DAYS задается в манифестах развертывания, редактировать конфигурационные файлы внутри контейнера не требуется.
Чтобы настроить автоматическую очистку для TRON.ASOC, установленного с помощью Docker Compose, выполните следующие действия:
- Отредактируйте блок
environmentсервисаcore(файлdocker-compose.yaml):
services:
core:
environment:
- STORAGE_CLEANUP_TTL_DAYS=${STORAGE_CLEANUP_TTL_DAYS:-0}
- Примените новое значение переменной:
docker compose up -d core - Убедитесь, что значение переменной применено:
docker compose exec core printenv STORAGE_CLEANUP_TTL_DAYS
Чтобы настроить автоматическую очистку для TRON.ASOC, установленного с помощью Helm Chart выполните следующие действия:
- Отредактируйте файл
values.yaml:
component:
asoc-back:
container:
asoc-back:
env:
STORAGE_CLEANUP_TTL_DAYS: "30"
- Примените новое значение переменной:
helm upgrade asoc ./asoc -n <namespace> -f values.yaml - Убедитесь, что значение переменной применено:
kubectl exec -n <namespace> deploy/asoc-back -- printenv STORAGE_CLEANUP_TTL_DAYS
Этот способ работает для версии чарта от 1.7. На ранних версиях чарта значения в блоке .env отсутствуют.
Принцип работы
Очередь задач
Ни автоматическое, ни ручное удаление не выполняются напрямую. Вместо этого в таблицу file_cleanup_task помещается задача с информацией о бакете, пути к объекту и типе источника. Фоновый воркер периодически забирает pending-задачи и физически удаляет данные из S3.
Воркер запускается при старте сервиса Core, выполняет немедленную очистку, а затем повторяет цикл каждые 24 часа до остановки сервиса Core. Если значение переменной STORAGE_CLEANUP_TTL_DAYS ≤ 0, создание новых TTL-задач прекращается, но уже поставленные в очередь задачи продолжают обрабатываться.
Выбор данных по TTL
TTL-механизм не удаляет данные напрямую, а только формирует для них задачи в очереди:
-
необработанные результаты сканирования — механизм выбирает данные со следующими свойствами:
- поле
created_at(дата создания) старше TTL; - статус
done(завершено),failed(провалено) илиcanceled(отменено); - маркер
raw_result_deleted_at(когда удалять результат) не установлен;
примечание - поле
Механизм не включает повторно в выборку записи с уже открытой задачей очистки. :::
-
отчеты — механизм выбирает данные со следующими свойствами:
- статус
done(завершено); - значение
updated_at(дата обновления) старше TTL; - маркер
files_deleted_at(когда удалять файлы) не установлен.
- статус
При отсчете по значению updated_at после повторной генерации отчета новый файл заново получает полный TTL.
Каскадное удаление при удалении сущностей
При удалении проверки безопасности/слоя/проекта через API удаление и постановка задач в очередь разделены: сущность удаляется в рамках транзакции PostgreSQL, и только после ее успешной фиксации создаются задачи на удаление связанных результатов сканирования. HTTP-ответ клиенту возвращается сразу, не дожидаясь физического удаления файлов из S3, так как оно выполняется воркером асинхронно.
Аналогичным образом удаляются записи при удалении инструмента безопасности/источника сканирования: связанные проверки безпасности собираются внутри транзакции PostgreSQL, а задачи создаются только после ее завершения.
Обработка ошибок
| Ситуация | Поведение |
|---|---|
| Объект уже отсутствует в S3 | Удаление считается успешным, маркер выставляется |
| S3 временно недоступен | Задача остается в статусе pending и логируется как ошибка; воркер повторит попытку при следующем проходе |
| Объект удален, но запись в PostgreSQL не обновлена | Поскольку S3 и PostgreSQL не поддерживают общую транзакцию, возможна ситуация, когда объект уже удален, а маркер — еще нет. При следующем проходе воркер повторно и безопасно вызывает удаление объекта (идемпотентно) и завершает задачу |
Мониторинг и диагностика
Проверка состояния через SQL
Для проверки состояния удаляемых данных можно выполнить следующие запросы в БД сервиса Core:
-- Состояние результатов сканирования
SELECT id, status, created_at, deleted_at, raw_result_deleted_at
FROM scan_result
ORDER BY created_at DESC;
-- Состояние отчетов
SELECT id, status, updated_at, result, files_deleted_at
FROM report
ORDER BY updated_at DESC;
-- Очередь задач очистки
SELECT id, bucket_name, object_path, source_kind, source_id, source_updated_at, status, deleted_at
FROM file_cleanup_task
ORDER BY created_at DESC;
Известные ограничения
Ниже перечислены особенности текущей реализации механизма очистки, которые могут повлиять на скорость или полноту очистки хранилища в отдельных ситуациях:
- Риск потери задачи при аварийном завершении работы сервиса
Core. Задача на удаление файлов ставится в очередь уже после того, как связанная операция (например, удаление проекта) зафиксирована в базе данных. Если сервисCoreаварийно завершает работу в промежуток между фиксацией в БД и постановкой задачи, то задача не будет создана. В результате файлы остаются в S3, а система не хранит информации о том, что их нужно удалить. - Отсутствие пакетного удаления. Воркер удаляет объекты по одному, а не пакетами. Поэтому при удалении крупного проекта, у которого много связанных файлов, создается большое количество отдельных задач, что может существенно удлинить время полной очистки.
- TTL не обрабатывает исторические записи, удаленные ранее. Запрос на выбор артефактов по TTL включает условие
deleted_at IS NULL. Из-за этого записи, которые были помечены как удаленные (soft delete) еще до внедрения механизма очистки, под это условие не попадают и автоматической обработке не подлежат — такие файлы нужно будет удалить отдельно. - Риск при повторной генерации отчета с тем же именем файла. Если повторно сгенерировать отчет с тем же именем файла, теоретически возможна ситуация, при которой задача на удаление, поставленная в очередь еще до повторной генерации, будет обработана уже после нее и удалит новый файл. Это может произойти, если задача выполнится раньше, чем успеет сработать защита по значанию
updated_at, которая предназначена для предотвращения такого случая. 5 Нет быстрых повторных попыток с нарастающей задержкой (backoff). Если удаление завершилось ошибкой, задача остается в статусеpendingи не повторяется сразу же. Следующая попытка произойдет только в рамках следующего полного цикла воркера — то есть примерно через сутки.