Стадия жизненного цикла модуля: Экспериментальная версия

У модуля есть требования для установки

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