Стадия жизненного цикла модуля: Экспериментальная версия
У модуля есть требования для установки
v0.0.6
Дата релиза: 2026-09-19
SeaweedFS-store считает бюджет томов и время проверки целостности от запрошенной ёмкости, а не от констант, которые ограничивали каждый volume-сервер 256 ГиБ, а каждый проход скраба — двенадцатью часами.
Ключевые изменения
Изменения в этом релизе:
- Store больше не перестаёт принимать запись на 256 ГиБ на volume-сервер: размер тома и число слотов выводятся из
spec.storage.sizePerNode, поэтому заполненный store — это заполненный диск. - Публикуемая ёмкость store ограничивается тем, что способны адресовать слоты томов, поэтому алерты заполнения описывают действительное состояние store.
- Проверка целостности отводит себе время по объёму данных, которые надо прочитать, а проход, не прочитавший ничего, больше не засчитывается как проверка.
Новый функционал
В этом релизе добавлено:
SeaweedFSStore.spec.volumeIndexзадаёт, где volume-сервер держит needle map (индекс объектов):Memory(по умолчанию, прежнее поведение) илиLevelDB. В режимеLevelDBрасход памяти определяется числом томов, а не числом объектов, и под резервирует его в requests.- Алерт
D8SdsObjectStoreScrubIncompleteсообщает о проверке целостности, оставившей volume-серверы непроверенными: store может проверяться по расписанию, и при этом часть его данных не читает никто.
Улучшения
В этом релизе улучшено:
SeaweedFSStore.spec.volumeServersтеперь должно быть не меньше числа копий изspec.replication; store с меньшим числом отклоняется при создании, а не остаётся навсегда без единого бакета.- Алерт
D8SdsObjectStoreAlmostFullсрабатывает после 90 % вместо 95 % — на пороге, за которым мастер SeaweedFS перестаёт размещать новые тома на диске, поэтому предупреждение больше не приходит после того, как store уже перестал принимать бакеты. - Store, которому некуда положить том, пишет об этом в терминах последствий: встаёт и запись в существующие бакеты, а не только создание новых.
- Go-типы API и CRD несут одинаковую валидацию, включая девять правил, которые прежде жили только в манифестах; в
USAGEописано, какие поля живого store поменять можно, а какие нет.
Исправления
В этом релизе исправлено:
- SeaweedFSStore, у которого на volume-серверах было больше 256 ГиБ, переставал принимать запись с
No writable volumes and no free volumes leftпри почти пустых дисках, а в собственном статусе сообщал, что места достаточно. - Проверка целостности store размером примерно от трёх volume-серверов по 2Ti обрывалась на середине прохода, а volume-серверы, до которых она не дошла, показывались как недоступные, а не как непроверенные.
spec.storage.sizePerNodeпринимался и молча игнорировался у существующего store: это размер volumeClaimTemplate у StatefulSet, поэтому новое значение не доходило ни до одного диска. Теперь поле неизменяемо, причина названа в сообщении об отказе.- Endpoint метрик контроллера не мог аутентифицировать сбор, из-за чего метрики самого модуля отсутствовали.
Обновления безопасности
Обновления безопасности в этом релизе:
- Зависимости образов контроллера и SeaweedFS подняты до версий, закрывающих находки сканера уязвимостей.
Несовместимые изменения
Изменения, влияющие на обратную совместимость:
spec.storage.sizePerNodeиspec.mastersнеизменяемы после создания, аspec.volumeServersможно только увеличивать. Правки, которые раньше принимались — а в случаеsizePerNodeещё и молча ничего не делали, — теперь отклоняются.- SeaweedFSStore, у которого volume-серверов меньше, чем копий требует
spec.replication, отклоняется. Такой store не смог бы разместить ни одного тома, поэтому ничего работавшего не ломается.
Рекомендации по обновлению
Перед обновлением учтите следующее:
- Руками делать ничего не нужно. Существующие store сохраняют диски и данные: мастера и volume-серверы перезапускаются, чтобы подхватить новый бюджет, который только поднимает потолок store, и уже записанные тома снова принимают запись.
- Store, заполненный между 90 % и 95 %, после обновления поднимет
D8SdsObjectStoreAlmostFull. Это тот порог, за которым мастер уже перестал размещать новые тома на его дисках, — именно об этом алерт теперь и сообщает. - Store, у которого
spec.volumeServersменьше числа копий изspec.replication, продолжает работать и обновлять статус, но любая другая правка его спеки будет отклонена, пока число серверов не поднимут.
Документация
Изменения в документации:
- Русский перевод справочника по CRD и документа
DESIGNприведён в соответствие с английским текстом.
v0.0.5
- Исправление: spec.placement (nodeSelector и tolerations) наконец применяется. Поле было в API с самого начала и описано как действующее на поды data plane, но его никто не читал — API его принимал, а поды планировались так, будто ничего не указано. Теперь применяется ко всем подам, которые разворачивает модуль: мастера, volume-серверы и filer’ы
- Реплики одного компонента разводятся по разным узлам. Для мастеров и volume-серверов правило жёсткое: три volume-сервера на одном узле не переживают отказ этого узла, а код репликации обещал копии на других серверах. Реплика, которой не досталось своего узла, остаётся в Pending — это видимая форма невыполнимого обещания. Filer’ы предпочитают разъезжаться, но запускаются и когда не могут: они стоят перед метаданными, которые лежат в другом месте
- Обновление затронет уже развёрнутые хранилища: мастера и volume-серверы будут перезапущены, а на кластере, где узлов меньше, чем реплик, часть подов не поднимется, пока не уменьшат число реплик или не добавят узлов
- Появилось поле spec.postgresClassName — имя PostgresClass, из которого разворачивается управляемая база метаданных. Это единственный способ повлиять на размещение её подов: у ресурса Postgres полей планирования нет вовсе, tolerations и nodeSelector принадлежат PostgresClass, поэтому spec.placement до базы не дотягивается. Пусто — класс default
v0.0.4
- Хранилище сообщает, сколько у него места: status.capacity с общим объёмом, занятым, свободным и долей занятого — на обоих бэкендах. Пока ни один узел не ответил, поле не заполняется: «неизвестно» и «пусто» это разные вещи
- Метрики модуля, правила алертов и дашборд: готовность хранилища и его заполненность. Алерты предупреждают о заполнении выше 85% и выше 95%, а хранилище, которое не Ready полчаса, сообщает об этом отдельно от хранилища, которое просто перестало отчитываться
- Метаданные filer можно держать во внешнем PostgreSQL: metadataStore External и Secret с параметрами подключения (host, port, database, username, password, sslmode, ca.crt), включая проверку сервера по своему CA. Соединение проверяется до запуска filer’ов, а sslmode disable и значения, которых libpq не знает, отклоняются — по этому соединению идут пароль и все имена объектов
- Правила истечения срока хранения на бакете: spec.lifecycle с expireAfterDays, expireNoncurrentAfterDays и abortIncompleteUploadsAfterDays и необязательным префиксом; у каждого правила обязательный уникальный id. Правила снимаются с бакета, когда их убирают из Bucket. Переноса между уровнями хранения при этом нет: один из движков его не выполняет, а поле, которое молча ничего не делает, не заводится
- Бакет, который уже есть в бэкенде и не принадлежит модулю, больше не подхватывается по имени: модуль помечает свои бакеты и отказывается трогать чужой, сообщая об этом в условии BucketNotOwnedByModule
- В документации появилась матрица поддержки операций S3 по бэкендам, с указанием версий движков, на которых она заполнена
- Исправление: filer’ы перезапускаются при смене подключения к базе метаданных — раньше ротация пароля обновляла конфигурацию, но работающие filer’ы продолжали ходить со старыми реквизитами
- Исправление: Secret с конфигурацией filer больше не перезаписывается на каждом цикле согласования
- Внутренние изменения: юнит-тесты реконсайлеров, e2e-сценарии и внутренняя проектная документация
v0.0.3
- Модель ресурсов переработана и несовместима с предыдущей версией — ресурсы, созданные в прежней модели, модуль больше не обслуживает, их нужно завести заново
- Профили System и Lightweight убраны вместе с бэкендом Garage. Остались два бэкенда — SeaweedFS и Ceph RGW
- ObjectStore больше не разворачивает хранилище, а описывает класс по образцу StorageClass: он ссылается на стор через spec.storeRef, а само хранилище описывают новые ресурсы SeaweedFSStore и SDSElasticStore
- BucketClaim теперь называется Bucket и остаётся в namespace, а прежний общекластерный Bucket называется BucketContents. Данные, сохранённые по reclaimPolicy Retain, ждут в фазе Released и подхватываются заново созданным Bucket
- BucketClaimPolicy больше нет. Вместе с ним ушли общий доступ к одному бакету из нескольких namespace и привязка к существующему бакету по regex
- Публикация S3-эндпойнта наружу: spec.publish на сторе задаёт имя хоста, Gateway и TLS-сертификат, модуль создаёт листенер и маршрут и публикует внешний адрес в status.endpoint.external. Публикация без TLS запрещена
- Поле spec.endpointScope в BucketAccess выбирает, какой адрес попадёт в Secret с реквизитами — внутренний или внешний; при смене эндпойнта выданные Secret’ы перевыпускаются
- Значение PublicRead в spec.accessPolicy бакета открывает анонимное чтение объектов на обоих бэкендах. Листинг содержимого при этом не выдаётся
- Версионирование и Object Lock на обоих бэкендах: режимы GOVERNANCE и COMPLIANCE, срок хранения и legal hold. Удаление данных под непросроченным retention блокируется, а причина отказа попадает в статус
- Отчёт о целостности данных: status.integrity и condition IntegrityHealthy. На SeaweedFS модуль сам запускает скраб по расписанию (spec.integrity) и по отдельному разрешению заменяет повреждённую копию; на Ceph RGW состояние скраба берётся из кластера
- Учёт копий данных: status.redundancy и condition RedundancyHealthy сообщают о томах, у которых копий меньше, чем запрошено репликацией
- Метрики, алерты и дашборд Grafana по целостности данных, недостаче копий и просроченному скрабу
- Шифрование хранимых данных: spec.encryption. На SeaweedFS — серверное шифрование ключом из Secret; смена ключа не применяется молча, а удерживается до подтверждения, иначе уже записанные объекты перестали бы читаться. На Ceph RGW ключи берутся из Deckhouse Stronghold
- Компоненты data plane закрыты сетевыми политиками
- Исправление: идентификатор пользователя RGW укладывается в ограничение Rook на длину метки — раньше бакет на Ceph RGW не мог стать Ready
- Исправление: политика бакета собирается из состояния кластера целиком, а не инкрементальными патчами — устранены гонки при нескольких доступах на один бакет
- Исправление: отказ «данные удерживает retention» определяется по самому бакету, а не по его спецификации — раньше любая ошибка доступа выглядела так же и навсегда удерживала финализатор
- Исправление: удаление Bucket будит контроллер его содержимого, а удаляющийся Bucket больше не считается живым владельцем — иначе бакет мог остаться в бэкенде без единой ссылки на него
- Исправление: число слотов под тома SeaweedFS больше не считается по размеру диска, том растёт по одному на бакет
- Исправление: стор не сообщает о готовности, если не может принять бакет
- Исправление: скраб выполняется вне цикла согласования — раньше он не укладывался в его бюджет и не завершался; проход, не покрывший ни одного тома, проверкой не считается
- Единый логгер и сервер метрик контроллера
- Внутренние изменения в сборке модуля
v0.0.2
- Исправление: образы data-plane (Garage, SeaweedFS) тянутся с секретом реестра, привязанным к модулю, — раньше pull падал в кластерах с закрытым реестром
- Фиксы CVE
- Обновление lib-helm до 1.72.13
v0.0.1
- Первоначальный релиз модуля в стадии Experimental. Модуль управляет S3-совместимым объектным хранилищем через набор ресурсов ObjectStore, Bucket, BucketClaim, BucketAccess и BucketClaimPolicy
- ObjectStore разворачивает и обслуживает само хранилище по одному из четырёх профилей: System (Garage на control-plane узлах, локальные PV), Lightweight (Garage на PVC), Full (SeaweedFS) и Heavy (Ceph RGW на существующем кластере sds-elastic)
- BucketClaim запрашивает бакет — собственный приватный либо привязку к общему бакету, разрешённую ресурсом BucketClaimPolicy в namespace владельца бакета (запрет по умолчанию)
- BucketAccess выдаёт отдельный ключ доступа и записывает Secret со стандартными переменными подключения; ключ ротируется аннотацией storage.deckhouse.io/rotate
- Ресурсы модуля публикуют status.conditions и status.observedGeneration