Коротко. Политика раскладки задаёт ширину полосы 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 Через модель (после установки)
- Создать политику в каталоге (
POST .../supportedstoragepolicy/) сcategory: custom, честнымиpropertiesи осмысленнымname. - Выбрать её:
PUT .../environment/<ENV_GUID>/с{"selectedstoragepolicy": {"category": "custom", "small_file_threshold": 524288}}. - Продукт сам пересчитает колонки (
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. Частые ошибки
- Считать только raw. Usable меньше; политика съедает чётность.
- Оставлять запас 0. Один отказ диска — и запись встанет.
- Менять политику без пересчёта. После добавления дисков
Nизменился — проверьте снова. - Использовать
balanced-8. Схема не примет; нуженcustom. - Инъектить 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. Что происходит с уже записанными объектами при смене политики
Смена политики — это не форматирование. Политика задаёт схему раскладки для вновь записываемых экстентов; уже записанные объекты остаются читаемыми по той схеме, по которой были разложены. Никакого «перелить всё заново» при смене не происходит, и окна обслуживания под это не требуется.
Из этого следуют три практических вывода.
- Кластер какое-то время живёт на двух политиках. Старые экстенты разложены по прежней ширине, новые — по новой. Это нормальное состояние, а не рассинхронизация: DSS умеет читать экстенты по их собственным метаданным раскладки.
- Эффект смены виден не сразу. Занимаемая доля и поведение при отказе меняются по мере перезаписи данных. Если нужно, чтобы «всё было по новой политике», данные надо перезаписать приложением или дождаться естественного оборота (новые бэкапы, новая аналитика).
- Перед сменой на продуктивной системе — тестовый прогон. Даже при том, что механизм неразрушающий, проверка на 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 блокстора.