Политики очистки задают срок хранения содержимого репозиториев: администратор описывает правилами, что и как долго держать, а Galleon применяет эти правила сам, без ручной уборки.

Типовые задачи, которые они закрывают: не держать snapshot-сборки дольше месяца, убирать версии, которые давно никто не скачивает, ограничивать размер кеша proxy-репозитория, оставлять только несколько последних релизов каждого пакета.

Политика — это набор критериев: возраст, давность скачивания, путь. Компонент удаляется, только если подходит под все критерии политики одновременно: политика с возрастом «больше 30 дней» и путём .*-SNAPSHOT.* удалит лишь то, что и старше тридцати дней, и лежит по подходящему пути.

Политика создаётся для одного формата и применяется только к репозиториям этого формата: политику формата Maven нельзя привязать к репозиторию npm. К одному репозиторию можно привязать несколько политик — компонент удаляется, если его отобрала любая из них. Порядок политик значения не имеет: результаты складываются.

Политика удаляет компоненты из каталога, а место на диске возвращает сборка мусора — она забирает содержимое, на которое не осталось ссылок, не раньше чем через gc.grace_period (Хранилище и сборка мусора).

Hosted и proxy

Политики работают с репозиториями обоих типов, но результат разный.

В hosted-репозитории удаление безвозвратно: артефакт публиковали в Galleon, и вернуть его можно только повторной публикацией. Поэтому для hosted-репозиториев выбирайте критерии осторожно и проверяйте их пробным запуском.

В proxy-репозитории удаляется только закешированная копия. Сам артефакт остаётся во внешнем реестре, и следующий запрос скачает его снова — для пользователей это незаметно, разве что первый запрос будет медленнее. Очистка работает здесь как вытеснение кеша: освобождает место, занятое тем, что перестали спрашивать.

Очистка не подчиняется политике записи репозитория. Репозиторий с политикой записи DENY закрыт от записи для клиентов, но привязанная политика очистки его вычистит.

Создание политики

Страница «Настройки» → «Политики очистки», кнопка «+ Новая политика».

Имя политики начинается с буквы, цифры или дефиса, содержит буквы, цифры, дефисы, подчёркивания и точки, не длиннее 255 символов. Имена сравниваются без учёта регистра, а после создания имя изменить нельзя.

Формат менять можно, пока политика не привязана ни к одному репозиторию. У привязанной политики смена формата отклоняется: сначала снимите привязки, потом меняйте формат.

Политика без единого критерия не удаляет ничего — в списке она помечена как «критерии не заданы». Это же относится к политике, где задано только «Сохранять новейших версий»: отбирать нечего, и исключать тоже нечего.

Критерии

Компонент удаляется, только если подходит под все заданные критерии одновременно. Общие для всех форматов критерии:

«Возраст компонента (дней)» — отбирает компоненты, у которых последнее изменение содержимого по всем ассетам старше указанного числа дней. Значение — целое число от 1 до 24 855.

«Использование компонента (дней)» — отбирает компоненты, ни один ассет которых не скачивали указанное число дней. Ассет, который не скачивали ни разу, считается от последнего изменения содержимого. Диапазон значений тот же.

«Регулярное выражение пути asset» — отбирает компоненты, у которых хотя бы у одного ассета путь совпадает с выражением. Совпадение полное: выражение закреплено с обеих сторон и сверяется с полным путём, включая ведущий слэш. Синтаксис — RE2, длина до 1024 символов; конструкции, которых в RE2 нет, отклоняются при сохранении политики — например, .*(?!-SNAPSHOT)\.jar.

Выражение antlr.* не подойдёт ни под один путь, потому что сверяется с путём целиком. Пишите .*antlr.*.

Критерии, зависящие от формата

«Тип релиза» доступен для форматов Maven и npm и отбирает либо только релизы, либо только предрелизы. Предрелиз определяется по-разному: у Maven это версия с суффиксом -SNAPSHOT, у npm — версия с semver-суффиксом предрелиза.

«Сохранять новейших версий» оставляет указанное число новейших версий пакета: они не удаляются, даже если подходят под остальные критерии. Счёт ведётся по каждому пакету, а не по репозиторию целиком. Критерий доступен двум форматам:

  • Maven — версии упорядочиваются по номеру версии, и критерий требует, чтобы был выбран тип релиза «Релизы»: исключение действует только для релизных версий;
  • Docker — теги упорядочиваются по дате и учитываются только в области тегов.

Особенности Docker

Компонент формата Docker — это пара «образ и тег», поэтому у политики есть две области, и хотя бы одна должна быть включена:

  • «Теги» — тегированные образы, по одному компоненту на тег. Включён по умолчанию. Только в этой области действует «Сохранять новейших версий»;
  • «Manifest без тега» — отдельно стоящие манифесты, не входящие в живой индекс образа. По умолчанию выключен.

Очистка снимает теги и удаляет манифесты; сами файлы образа забирает потом сборка мусора.

Когда в одной политике включены обе области, они оцениваются по очереди: сначала манифесты без тега, затем теги. Поэтому манифест, у которого этот же проход снял последний тег, попадает под удаление только на следующем — ночном или запущенном вручную. Планируя первую большую уборку, рассчитывайте, что образ полностью исчезнет за два прохода: сначала теги, потом манифест.

Если теги и манифесты без тега разнесены по разным политикам, всё зависит от порядка привязки: политика манифестов, стоящая в списке после политики тегов, увидит освободившиеся манифесты уже в текущем проходе.

Возраст Docker-компонента считается по его тегу: создание тега и push, меняющий то, на что тег указывает, сбрасывают отсчёт, а повторный push того же содержимого — нет. Возраст манифеста без тега считается с момента, когда его загрузили в репозиторий.

Регулярное выражение отбирает Docker-компонент только по пути манифеста: /v2/<IMAGE>/manifests/<TAG> для тегированного компонента и путь с digest для манифеста без тега. Пути слоёв компонент не отбирают никогда.

Подписи и attestation

Подписи и attestation живут в репозитории рядом с образом, и очистка обращается с ними по-разному — в зависимости от того, как они к образу привязаны.

Подпись, привязанная к образу ссылкой subject из стандарта OCI 1.1, хранится ровно столько же, сколько сам образ: пока образ в репозитории, политика подпись не удалит, а вместе с образом удалит и её. Так подписи публикуют oras attach и cosign, запущенный с параметром --registry-referrers-mode=oci-1-1. Настраивать для таких подписей ничего не нужно — достаточно включить область манифестов без тега.

Подпись, опубликованная отдельным тегом вида sha256-<DIGEST>.sig (а также .att и .sbom), с образом ничем не связана: для Galleon это отдельный образ со своим тегом, и политика оценивает его сама по себе. Такие теги создаёт cosign в режиме legacy: этот режим появился раньше стандарта OCI 1.1 и остаётся включённым, пока клиенту не задан режим oci-1-1. Подпись скачивают редко, только когда её проверяют, поэтому по давности скачивания она попадает под удаление, даже если сам образ скачивают каждый день. В hosted-репозитории подпись после этого не восстановить: политика её удалит, образ останется, и проверка подписи начнёт падать там, где раньше проходила. Вернуть подпись можно только повторной подписью образа. В proxy-репозитории последствий нет: удаляется закешированная копия, и при следующей проверке подпись будет скачана из внешнего реестра заново.

Если такие подписи есть в hosted-репозитории, составьте регулярное выражение так, чтобы под политику попадали только нужные образы, задавайте сроки с запасом и перед привязкой обязательно выполните пробный запуск.

Привязка к репозиториям

Политика начинает действовать, когда её привязали к репозиторию: в форме репозитория (Репозитории) есть поле «Политики очистки», в котором выбираются политики того же формата.

Удаление политики снимает привязку у всех репозиториев, которые её использовали.

Запуск

Способы запуска очистки:

  1. Планово — ежедневно в 01:00 UTC по всем репозиториям с привязанными политиками. Репозиторий, выведенный из обслуживания («в сети» снят), плановый проход пропускает.
  2. Вручную по всем репозиториям — кнопка «Запустить сейчас» на карточке задачи на странице политик очистки.
  3. Вручную по одному репозиторию — кнопка «Запустить очистку» в форме репозитория. Ручной запуск работает и для выведенного из обслуживания репозитория.

Одновременно для репозитория выполняется только один запуск; повторный отвечает, что очистка уже выполняется. Итог планового прохода виден на карточке задачи в поле «Последний запуск».

Пробный запуск

Кнопка «Пробный запуск» считает компоненты, которые политика удалила бы из выбранного репозитория, и ничего не удаляет. Политика при этом может быть и не привязана к репозиторию — это способ проверить критерии до того, как они начнут действовать.

Пробный запуск считает по каждой политике отдельно, поэтому компонент, который отобрали две привязанные политики, будет посчитан дважды; при настоящем запуске он удаляется один раз.

У образов есть ещё одно расхождение: если проход удаляет индекс без тега, входившие в него манифесты становятся кандидатами прямо в этом проходе, и настоящий запуск может удалить больше, чем показал пробный.

Права

Политики относятся к области settings: просмотр списка требует привилегии nx-settings-read, а создание, правка и удаление — привилегии nx-settings-update (Привилегии).

Запуск очистки — привилегия nx-tasks-run, состояние задачи — nx-tasks-read. Кнопка запуска работает и без права на чтение состояния задачи: в этом случае не показывается только карточка с итогом прошлого прохода.