ActiveScaleинженерная практика

Формула политики DSS

Проектирование dsspolicycapacity507blockstore

Коротко. Политика раскладки задаёт ширину полосы w и число фрагментов чётности s. Продукт требует w + s ≤ N, где N — число блоксторов. Если условие не выполняется, генератор экстентов не может разложить данные → барометр full → S3 отдаёт 507 Storage is full при свободных дисках. Usable = (w − s) / w.


1. Термины

Термин Смысл
Блокстор единица раскладки на дисках; их число видит DSS
w (spread width) сколько фрагментов данных в полосе
s (safety) сколько фрагментов чётности
N число блоксторов
Usable доля ёмкости, доступная приложению: (w−s)/w
Барометр индикатор заполнения DSS: ok / full

2. Условие и примеры

Условие: w + s ≤ N.
Usable: (w − s) / w.

N w/s Занято Запас Usable Когда подходит
4 2/1 3 1 50% мини-стенд
8 4/2 6 2 50% 8 дисков
10 6/2 8 2 67% 10 дисков
16 10/2 12 4 80% 16 дисков
20 12/4 16 4 67% безопаснее
24 14/4 18 6 71% крупная полка

Аварийный случай: политика 6/2 на 8 дисках занимает ровно 8, запас 0. При первом отказе диска запись встанет. Не повторять.


3. Почему стоковые пресеты не влезают

Пресеты рассчитаны на большие полки:

  • balanced — 13/4 (нужно ≥ 17 блоксторов);
  • lowest_overhead — 15/4 (нужно ≥ 19);
  • 2site_replicated — 12/2 (нужно ≥ 14).

На 8–10 дисках они не проходят по w+s ≤ N. Штатный слот для своей политики — category: custom. Имя вида balanced-8 схема не принимает (жёсткий CHOICES) → 500 ValidationError.


4. Как применить

4.1 При установке

В config-ng.ini (секция [general]):

policy_type = single-denali-8

или флагом:

install-ng.py ... -P single-denali-8

find_policy_group() берёт это значение как индекс ветки в dssconfig.yml.

4.2 Через модель (после установки)

  1. Создать политику в каталоге (POST .../supportedstoragepolicy/) с category: custom, честными properties и осмысленным name.
  2. Выбрать её: PUT .../environment/<ENV_GUID>/ с {"selectedstoragepolicy": {"category": "custom", "small_file_threshold": 524288}}.
  3. Продукт сам пересчитает колонки (configureColumns).

4.3 Через CLI продукта

cli.dss.policy.add(4, 2, [100,100,60], port=11060)
cli.dss.policy.add(3, 2, [100,100,60], full_copy=True, port=11060)
for name in cli.dss.namespace.list_all():
    cli.dss.namespace.change_policy(name, '<ID>', port=11060)

Грабли: change_policy ждёт имя неймспейса (не id) и строковые аргументы; успех — None.


5. Проверка

  • Барометр: cli.dss.capacity.read_barometer() → ok.
  • Неймспейсы: get_namespaces_with_fill_status() → все status: ok.
  • Модель: selectedstoragepolicy не null.
  • Политика: w + s ≤ N (пересчитать после расширения).
  • S3: PUT небольшого объекта → 200.

6. Частые ошибки

  1. Считать только raw. Usable меньше; политика съедает чётность.
  2. Оставлять запас 0. Один отказ диска — и запись встанет.
  3. Менять политику без пересчёта. После добавления дисков N изменился — проверьте снова.
  4. Использовать balanced-8. Схема не примет; нужен custom.
  5. Инъектить capacity руками. На реальном железе сканер сам даёт enclosure/diskgroup.

7. Пошаговый расчёт политики под конкретное железо

Ниже — порядок, который снимает 90% ошибок «507 при свободных дисках». Считать надо до установки, а не после первой неудачной записи.

Шаг 1. Посчитать N — число блоксторов, а не дисков. Блокстор — это единица раскладки, которую видит DSS. На реальном железе сканер строит enclosure и diskgroup сам, и N берётся из модели, а не из спецификации полки. Пока enclosure не смоделирован, N равно нулю, и любая политика формально не влезает — отсюда ложный 507 на ровном месте. Смотрите на число блоксторов, доступных DSS, а не на число слотов в шасси.

Шаг 2. Проверить w + s ≤ N. Если условие не выполняется, генератор экстентов не может разложить полосу, барометр уходит в full, S3 отдаёт 507 Storage is full. Это не нехватка места, а нераскладываемая политика.

Шаг 3. Оставить запас. Разница N − (w + s) — это сколько блоксторов может выпасть, прежде чем запись встанет. Запас 0 (например 6/2 на 8 блоксторах) означает: первый отказ диска — и кластер переходит в режим «только чтение». Практическое правило: запас не меньше двух, а на малых конфигурациях лучше не гнаться за usable.

Шаг 4. Посчитать usable. usable = (w − s) / w. Именно эта доля, а не raw, доходит до приложения. Для 4/2 это 50%, для 6/2 — 67%, для 10/2 — 80%. Считайте от raw ёмкости после вычета служебных нужд, а не от красивой цифры в спецификации.

Шаг 5. Сверить с ожиданиями по durability. Слишком «жирная» политика (большое s) даёт запас по отказам, но съедает usable; слишком «тонкая» — экономит место, но не переживает одновременного выпадения двух блоксторов и хуже ремонтируется. Компромисс ищется по числу допустимых одновременных отказов, а не по проценту.

Шаг 6. Записать результат в конфиг. policy_type = single-denali-<N> в секции [general] файла config-ng.ini (или флаг -P). find_policy_group() берёт это значение как индекс ветки в dssconfig.yml; стоковая ветка single-denali (13/4) остаётся нетронутой.

Шаг 7. Пересчитать после расширения. Добавили диски или полку — N изменилось, условие надо проверить снова. Политика, которая влезала в 8 блоксторов, на 12 может оказаться неоптимальной по usable, хотя формально проходит.


8. Что происходит с уже записанными объектами при смене политики

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

Из этого следуют три практических вывода.

  1. Кластер какое-то время живёт на двух политиках. Старые экстенты разложены по прежней ширине, новые — по новой. Это нормальное состояние, а не рассинхронизация: DSS умеет читать экстенты по их собственным метаданным раскладки.
  2. Эффект смены виден не сразу. Занимаемая доля и поведение при отказе меняются по мере перезаписи данных. Если нужно, чтобы «всё было по новой политике», данные надо перезаписать приложением или дождаться естественного оборота (новые бэкапы, новая аналитика).
  3. Перед сменой на продуктивной системе — тестовый прогон. Даже при том, что механизм неразрушающий, проверка на probe-объектах стоит минуты: положить объект, сменить политику, положить ещё один, прочитать оба. Критичные данные всё равно лучше подстраховать штатным бэкапом — не потому что политика «съест» данные, а потому что любая работа с политикой идёт через модель и CLI, где ошибка в аргументах стоит дорого.

Отдельно: смена политики не освобождает место. Если барометр уже full, смена политики на более широкую не поможет — наоборот, сделает раскладку ещё более требовательной. Сначала разбираются с причиной full (ёмкость, недоступные блоксторы, не смоделированные enclosure), и только потом трогают политику.


9. Как проверить, что политика применилась

Проверять надо в трёх местах: в DSS, в модели и на живом S3. Любая из проверок по отдельности врёт.

DSS — барометр и неймспейсы. Через sherpa (порт 11060, дефолт 23510 даёт connection-refused):

cli.dss.capacity.read_barometer()                 # ожидается 'ok'
cli.dss.capacity.get_namespaces_with_fill_status()  # все NS: status 'ok'
cli.dss.policy.list_all()                          # политика с нужными w/s в списке

full на барометре при свободных дисках — почти всегда политика, а не место.

Модель — selectedstoragepolicy. GUI берёт durability-метрики именно отсюда. Если поле null, метрик не будет, даже когда система здорова:

curl -sk --cert <CERT> --key <KEY> \
  https://127.0.0.1:8443/model/environment/<ENV_GUID>/ | jq .selectedstoragepolicy

Ожидается объект с category (custom для своей политики) и small_file_threshold. Категория в схеме — жёсткий CHOICES: balanced, lower_overhead, lowest_overhead, 2site_replicated, custom. Своё имя вида balanced-8 схема не примет — 500 ValidationError. Штатный слот для своей политики — custom, а осмысленное имя задаётся полем name (его и показывает GUI).

S3 — живая запись. PUT небольшого объекта и чтение обратно: 200 и совпадающее содержимое. Если PUT даёт 507, а диски свободны — вернуться к шагу 1 (число блоксторов) и к барометру. Если PUT даёт 403 — это уже не политика, а часы (SigV4, ±15 минут) или resource policy аккаунта.

Дополнительно стоит проверить, что политика применилась к нужным неймспейсам, а не только существует в каталоге: change_policy ждёт имя неймспейса (не id) и строковые аргументы, успех — возврат None. Политика в списке и политика, назначенная неймспейсу, — разные вещи, и именно вторая определяет раскладку.


10. Источники

  • ActiveScale Datasheet DS00546A
  • Внутренняя практика (обезличено): кейсы политик на 8/16/24 блокстора.

Нужен инженер? Разберу вашу ситуацию и скажу, что делать — по шагам, с проверками.

Обсудить задачу