Хранение
Arkvory хранит каждый опубликованный файл один раз, без изменений, в каталоге хранилища файлов на локальном диске сервера. На этой странице объясняется, что занимает место на диске, как ограничить его квотами и политиками хранения, как удалённые файлы уходят с диска и что делать, когда диск заполнен.
Где лежит содержимое
Каталог хранилища файлов задаёт переменная ARKVORY_DATA_DIR. Установщики используют такие расположения:
| Установка | Хранилище файлов |
|---|---|
| Windows | data\ в C:\ProgramData\ProAnima\Arkvory |
| Linux | data/ в /opt/proanima-arkvory |
| Docker Compose | Том Docker proanima-arkvory_storage |
Внутри каталога blobs/ содержит готовые файлы, staging/ и parts/ — загрузки в процессе, а файл storage-id связывает каталог с базой данных. Сведения каталога — все имена, метки, версии и права — находятся в PostgreSQL. Файлы и база данных принадлежат друг другу.
- Используйте локальную файловую систему с поддержкой жёстких ссылок. Не размещайте хранилище файлов на сетевом ресурсе.
- Не добавляйте, не изменяйте и не удаляйте файлы в каталоге вручную. Arkvory удаляет файлы сам, как описано ниже.
- Опубликованный файл никогда не меняется. Новое содержимое — это новый файл с новым ID.
Спланируйте диск
Место на томе хранилища файлов занимает следующее:
| Что | Примечания |
|---|---|
| Опубликованные файлы | Все версии, которые вы храните |
| Загрузки в процессе | Части и промежуточные файлы, пока загрузка не завершится |
| Файлы завершённых загрузок по частям | Временные части остаются рядом с готовым файлом, пока их не удалит проход физической очистки. См. Физическая очистка |
| Удалённые файлы | Остаются на диске, пока не закончится защитный срок и проход очистки не удалит их |
| Копии зеркал | Часть в mirror-staging, пока зеркало копирует файл. См. Зеркала |
Помимо хранилища файлов, по возможности размещайте базу данных PostgreSQL, журналы и хранилище копий на отдельных томах. См. Резервные копии.
Arkvory держит на томе хранилища файлов резерв свободного места. По умолчанию это 1 ГиБ (ARKVORY_STORAGE_RESERVE_BYTES). Загрузка, которая заняла бы резерв, отклоняется с HTTP 507 и причиной storage_full. Скачивания продолжают работать. Пока для новых данных нет места, GET /health/ready показывает writable: false.
Два предела действуют независимо от диска:
ARKVORY_CAPACITY_BYTESограничивает всё зарезервированное содержимое установки. По умолчанию — 10 ТиБ. Это логический предел, а не проверка диска. Когда он достигнут, загрузки завершаются неудачей с HTTP 507 и причинойcatalog_limit.ARKVORY_MAX_OBJECT_BYTESограничивает размер одного файла.
См. Переменные окружения. В Arkvory нет метрики свободного места хранилища файлов или базы данных. Следите за томами средствами операционной системы или с помощью node exporter.
Кто может управлять хранением
Настройки хранения не входят в обычные права на чтение и запись. Ключу сервиса нужны явные действия в репозитории:
| Действие | Что позволяет |
|---|---|
storage.read | Видеть политику, использование и настройки очистки |
storage.manage | Менять политику, квоту и настройки очистки и запрашивать пакет очистки |
artifact.delete | Просматривать удаления, удалять артефакты и включать автоматическую политику хранения |
diagnostics.read | Читать события хранилища |
Учётные записи с паролем и ключ восстановления сами по себе этих прав не имеют. Чтобы управлять хранением в консоли:
- Создайте сервисную учётную запись с политикой для репозитория, включающей эти четыре действия. См. Учётные записи и доступ.
- Выпустите и активируйте для неё ключ.
- В консоли откройте Подключиться ключом сервиса или автоматизации, вставьте ключ и нажмите Подключиться.
- Откройте Репозитории и на карточке репозитория нажмите Хранение и очистка.
Над каталогом появится панель Хранение и автоочистка. Без этих прав панель остаётся скрытой.
Включённая политика хранения привязана к ключу, который её включил. Каждый автоматический запуск заново проверяет, что этот ключ ещё активен, не истёк и по-прежнему имеет storage.manage и artifact.delete. Если вы отзовёте ключ или сократите его права, удаление остановится и появится событие retention.failed. После ротации ключа сохраните политику снова с новым ключом.
Квоты и пороги предупреждений
У репозитория может быть квота. Без квоты действует только общий предел.
| Параметр | Поле в консоли | Значение | По умолчанию |
|---|---|---|---|
| Квота | Квота, ГиБ (пусто — без ограничения) | Наибольший объём, который может занять репозиторий. API принимает точное число байт от 1 до 9 007 199 254 740 991, а null означает отсутствие предела | Без ограничения |
| Порог предупреждения | Порог предупреждения (%) | Доля квоты, при которой появляется предупреждение. 1–98 | 80 |
| Критический порог | Критический порог (%) | Доля, при которой появляется ошибка. 2–99, больше порога предупреждения | 95 |
В использование, которое учитывается в квоте, входит размер всех файлов репозитория, ещё не удалённых с диска: опубликованных файлов, незавершённых загрузок и удалённых файлов, ожидающих очистки. Поэтому удалённый файл продолжает занимать квоту, пока его не удалит проход очистки.
- Проверка. Сервер проверяет квоту при начале загрузки. Новая загрузка, которая превысила бы квоту, завершается неудачей с HTTP 507 и причиной
storage_quota. Повтор с тем же ключом идемпотентности не резервирует место дважды. - Уменьшение. Квоту можно задать ниже текущего использования. Выполняющиеся загрузки могут завершиться. Новые загрузки сверх предела отклоняются.
- Нет автоматического освобождения. Квота никогда не вызывает удаление. Правила хранения не удаляют лишние сборки, чтобы уложиться в квоту.
- Состояния. Состояние бывает
unlimited,normal,warning,criticalилиexceeded. Смена состояния один раз записывается как событие хранилища. - Наблюдение. Сервер каждую минуту заново проверяет состояния не более чем 20 репозиториев, в том числе когда автоматическое удаление выключено.
Эти числа — логические резервирования, а не свободное место на диске. Репозиторий может быть в пределах квоты, а диск при этом заполнен, потому что на диске есть ещё промежуточные файлы и другие репозитории.
Политика хранения
Политика хранения автоматически удаляет старые зарегистрированные сборки UPack и оставляет последние N из них. Другие файлы она не удаляет: обычные файлы по пути, образы контейнеров, объекты Git LFS и пакеты npm в её область не входят. Без политики ничего не удаляется автоматически.
Параметры
| Параметр | Поле в консоли | Значение | По умолчанию |
|---|---|---|---|
| Включить | Включить автоочистку | Включает автоматическое удаление | Выключено |
| Группировка | Считать последние N по | Единица, по которой ведётся счёт: Пакету и каналу, Пакету или Всему репозиторию | Пакет и канал |
| Последних N | Последних N сборок по умолчанию | Сколько сборок хранить для каждого счётчика, 1–100 000 | 10 |
| Каналы | Настройки каналов: метка=N, каждая с новой строки | Собственное N для метки в виде метка=N, по одной на строку, до 32. Используется только при группировке по пакету и каналу | test=10, staging=10, release=10 |
| Минимальный возраст | Минимальный возраст для удаления (часы) | Сборка моложе этого возраста сохраняется; в часах, 0–87 600 | 24 |
| Защищённые метки | Защищённые метки через запятую | Сборки с одной из этих меток никогда не удаляются, до 32, через запятую | bse, release |
| Интервал | Интервал очистки (минуты) | Минуты между запусками, 1–10 080 | 60 |
Метка состоит из 1–64 букв, цифр или символов _ . : -.
Как выбираются сборки
- Сервер ранжирует сборки каждого счётчика по времени публикации, от самой новой. Порядок не совпадает с порядком версий SemVer.
- Счётчик зависит от группировки. При группировке по пакету и каналу сборка учитывается отдельно для каждой настроенной метки канала, которую она несёт, по каждому пакету (
group/name). Сборка без настроенной метки попадает в один общий счётчик пакета с N по умолчанию. При группировке по пакету у каждого пакета один счётчик. При группировке по всему репозиторию у всех сборок один общий счётчик. Имена пакетов не зависят от регистра, метки зависят. - Сборка остаётся, если она входит в последние N любого счётчика, к которому относится.
- Сборка моложе минимального возраста остаётся.
- Сборка с защищённой меткой остаётся. Её метки берутся из текущей аннотации или из загрузки, если аннотации нет. Защищённые сборки всё равно участвуют в ранжировании, поэтому число сохранённых сборок может быть больше N.
Сборка никогда не удаляется, пока она кому-то нужна:
- Внешний сервис держит на неё ссылку.
- Её использует путь к файлу, текущий или из истории.
- Другая сборка перечисляет её как вложение, сейчас или в истории.
- Она продвинута в стадию. Сначала снимите стадию.
- Её использует образ контейнера, запись Git LFS или npm.
Удаление сборки логическое: она исчезает из списков, а новые скачивания завершаются ответом 404. Байты уходят с диска позже, при физической очистке. Версия пакета остаётся зарезервированной, поэтому ту же версию нельзя опубликовать снова с другим содержимым.
Включите политику безопасно
Сначала просмотрите, потом включайте. Просмотр показывает, что удалила бы сохранённая политика, и ничего не удаляет.
- Подключитесь с ключом, у которого есть эти четыре действия, и откройте панель хранения репозитория.
- Задайте поля и оставьте Включить автоочистку выключенным. Нажмите Сохранить политику.
- Нажмите Проверить сохранённую политику. В списке до 100 сборок, которые сохранённая политика удалила бы за один пакет. Если кандидатов остаётся больше, консоль сообщает об этом.
- Если список верный, установите флажок Включить автоочистку и флажок подтверждения Понимаю, что сохранение включённой политики разрешает автоматическое удаление., затем сохраните снова. Для этого нужно
artifact.delete.
Примечания:
- Просмотр показывает один момент времени. Когда политика запускается, она ранжирует сборки и проверяет зависимости заново.
- Политика сохраняется вместе с номером версии. Если её изменил кто-то другой, перезагрузите страницу и сохраните снова.
- Обновить настройки и место перезагружает настройки и использование.
Как выполняется политика
Пишущий процесс API (не шлюз чтения) проверяет политики каждые 60 секунд и обрабатывает до 20 политик, срок которых наступил. Один пакет удаляет не более 100 сборок. Если остаются кандидаты, следующий пакет начинается через минуту. Иначе следующий запуск наступит через интервал. Расписание хранится в базе данных и переживает перезапуск.
Один пакет можно запустить и самому с помощью операции API runStoragePolicy. Использование, просмотр и события имеют операции в том же справочнике API по хранению.
Физическая очистка
Удаление артефакта, человеком или политикой, лишь убирает его из каталога. Физическая очистка удаляет его байты с диска в фоне, не останавливая API, обработчик и шлюзы чтения. Кроме того, она:
- Отменяет загрузки, срок которых истёк без завершения, и удаляет их части.
- Удаляет временные части завершённых загрузок.
Она не выбирает сборки для удаления. Она убирает только то, что уже удалено или отменено.
Физическая очистка по умолчанию выключена, и она настраивается для каждого репозитория отдельно. Включите её в каждом используемом репозитории. Пока она выключена, удалённые файлы, истёкшие загрузки и части завершённых загрузок остаются на диске, а квота учитывает удалённые файлы.
Параметры очистки
В панели репозитория откройте Физическая очистка:
| Параметр | Поле в консоли | Значение | По умолчанию | Диапазон |
|---|---|---|---|---|
| Включить | Включить фоновую очистку | Включает фоновую очистку | Выключено | |
| Защитный срок | Защитный срок после удаления (часы) | Как долго удалённый файл остаётся на диске, в часах | 24 | 0–8760 |
| Пакет | Файлов за проход | Сколько файлов обрабатывается за один пакет | 25 | 1–100 |
| Интервал | Интервал между проходами (секунды) | Секунды между пакетами | 60 | 5–86 400 |
| Пауза | Пауза между файлами (миллисекунды) | Миллисекунды паузы между файлами | 50 | 0–1000 |
Нажмите Применить настройки, чтобы применить настройки. Изменение действует сразу. Если вы выключите очистку, она остановится после текущего файла. Кнопка Запросить проход запрашивает пакет в ближайшее время, а не удаляет сразу. Нажмите Обновить состояние очистки, чтобы увидеть результат последнего пакета.
Защитный срок — это не корзина. При значении 0 файл может быть удалён сразу после удаления, если его не читает ни один клиент. Arkvory не умеет восстанавливать удалённый артефакт.
Что очистка делает и что пропускает
- Она удаляет только отменённые или удалённые файлы, у которых прошёл защитный срок. Она ещё раз проверяет, что их ничто не использует: ни ссылка, ни история пути к файлу, ни история вложений.
- Открытое скачивание, записываемая загрузка и файл, который нужен выполняющейся резервной копии, заставляют очистку пропустить этот файл. Следующий пакет попробует снова. Последний результат показывает, сколько файлов обработано, пропущено и завершилось ошибкой и сколько байт освобождено.
- Квота и логическая ёмкость освобождаются только после удаления файлов с диска.
- Пакет ограничен размером пакета и паузой, что снижает нагрузку на диск. Это не гарантирует строгую пропускную способность диска и не обещает нулевого влияния на задержку других запросов.
- Очистка выполняется в пишущем процессе API, один раз на базу данных. Раз в 5 секунд он проверяет один репозиторий, срок которого наступил. Без работающего пишущего процесса ничего не очищается.
- Включайте очистку только после обновления всех процессов Arkvory, включая шлюзы и обработчик. Старый процесс без протокола очистки заставляет очистку откладывать работу.
Удалите артефакт
Один опубликованный артефакт можно удалить вручную. Для этого нужно artifact.delete в репозитории.
- Откройте артефакт в разделе Свойства артефакта и найдите Удаление артефакта.
- Нажмите Проверить зависимости. Консоль покажет, что ещё использует артефакт. Если что-то блокирует удаление, сначала уберите эту зависимость.
- Вставьте ID артефакта для подтверждения и нажмите Удалить этот артефакт.
Такое удаление не проверяет защищённые метки, потому что вы сами выбираете объект. Зависимости проверяются всегда. После удаления:
- Артефакт исчезает из списков и поиска. Новое скачивание завершается ответом 404. Уже идущее скачивание может завершиться.
- Версия пакета остаётся зарезервированной.
- Байты остаются на диске, пока физическая очистка не удалит их после защитного срока.
- Отменить удаление в консоли или через API нельзя.
Для удаления многих артефактов в API есть previewRetention и applyRetention. Просмотр перечисляет кандидатов, опубликованных до заданной даты, с причинами блокировки. Применение удаляет только переданные вами ID, до 100 за вызов, и возвращает результат для каждого ID: deleted, already_deleted, protected, changed, not_eligible или not_found. Проверяйте каждый результат, а не только статус HTTP.
Диагностика и события хранилища
Раздел Предупреждения, ошибки и события хранилища перечисляет, что происходило в репозитории, от старых к новым, по 100 на страницу. Нажмите Следующие события, чтобы открыть следующую страницу. Чтобы читать его, нужно diagnostics.read. Операция API — getStorageEvents, с фильтром по уровню (info, warning, error).
| Событие | Уровень | Значение |
|---|---|---|
storage.policy_updated | info | Политика хранения сохранена |
retention.completed | info | Пакет удалил сборки. В событии указано число |
retention.failed | error | Автоматическое удаление остановлено, например потому, что отозван разрешивший его ключ |
cleanup.configured | info | Настройки очистки сохранены |
cleanup.completed | info или error | Пакет очистки обработал файлы, пропустил их или завершился по ним ошибкой. В событии числа и освобождённые байты |
capacity.normal, capacity.warning, capacity.critical, capacity.exceeded, capacity.unlimited | info, warning или error | Состояние квоты изменилось |
| Коды ошибок HTTP | warning или error | Запрос управляемого ключа к этому репозиторию завершился ошибкой. Событие хранит ID запроса, маршрут и статус |
История ограничена: 1000 событий на репозиторий и 20 000 всего, самые старые отбрасываются. Это диагностика по возможности, а не журнал с гарантированной доставкой. Вовремя экспортируйте то, что вам нужно, а для долгосрочных свидетельств используйте журнал сервера. См. Мониторинг.
Панель показывает и использование: опубликованные байты, незавершённые загрузки, байты, ожидающие очистки, и итог относительно квоты. Операция API — getStorageUsage.
Когда диск заполнен
Признаки: загрузки завершаются неудачей с HTTP 507 и причиной storage_full, GET /health/ready показывает writable: false или операционная система сообщает, что свободного места нет. Скачивания продолжают работать. Клиенты могут продолжить свои загрузки после того, как вы освободите место.
- Найдите причину. Проверьте свободное место на томах хранилища файлов, базы данных и хранилища копий. Сравните цифры использования в панели хранения. Большие значения «ожидает очистки» означают, что удалённые данные ещё на диске. Большое значение «незавершённые загрузки» означает брошенные загрузки.
- Запустите очистку. Если очистка выключена, включите её в каждом репозитории с коротким защитным сроком, например 0, если вы согласны, что удалённые файлы уходят сразу. Нажмите Запросить проход. Она также удаляет временные части завершённых загрузок и истёкшие загрузки. Дождитесь пакетов и прочитайте последний результат. Очистка пропускает используемые файлы, поэтому повторите её.
- Удалите ненужное. Примените политику хранения или удалите артефакты. Место освободится только после того, как очистка удалит байты.
- Добавьте места. Расширьте том или диск. Если хранилище копий или другие данные лежат на том же томе, перенесите их.
- Проверьте восстановление. Когда место освободится,
writableвернётся вtrue, и загрузки снова заработают.
Не удаляйте файлы в blobs/, staging/ и parts/ вручную: это нарушает связь между базой данных и диском. Если резерва мало для журналов и базы данных на том же томе, увеличьте ARKVORY_STORAGE_RESERVE_BYTES.
Если загрузка завершается неудачей с причиной storage_quota или catalog_limit, дело не в диске. Увеличьте квоту или общий предел либо удалите данные.
Ограничения
- Политика хранения работает только с зарегистрированными сборками UPack. Другие файлы она никогда не удаляет.
- Порядок хранения определяет время публикации, а не номер версии.
- Для хранения, квот и очистки нужны явные действия ключа сервиса. У учётных записей с паролем и у ключа восстановления их нет.
- Физическая очистка по умолчанию выключена и настраивается для каждого репозитория.
- Удалённый артефакт восстановить нельзя. Восстанавливайте данные из резервной копии. См. Резервные копии.
- В зеркалируемых репозиториях политики хранения не выполняются. См. Зеркала.
- Хранилище файлов должно быть на локальной файловой системе. Сетевые ресурсы и несколько хранилищ не поддерживаются.