Тонкие тома и переподписка диска: где ловушка
Вы создали десяток виртуальных дисков по 500 ГБ каждый на хранилище объёмом 2 ТБ — и Proxmox или ваша SAN спокойно это проглотили, не выдав ни одной ошибки. Через месяц одна из виртуалок падает с "no space left on device", хотя по её собственным ощущениям места должно быть навалом. Дело не в баге и не в повреждении диска — это штатная механика тонкого выделения тома, которая работает ровно так, как задумана, просто вы не следили за тем показателем, за которым нужно было следить.
Содержание
Что физически происходит на уровне тома
Тонкий том (thin volume) — это абстракция: том заявляет гостевой системе или потребителю некий объём (скажем, 500 ГБ), но на физическом хранилище резервируется не весь этот объём сразу, а только реально записанные блоки. Разница с "толстым" (thick/preallocated) томом принципиальна на уровне метаданных, а не только на уровне "экономии места".
У толстого тома блоки на физическом устройстве выделяются и размечаются в момент создания — том на 500 ГБ означает, что 500 ГБ физического пространства заняты немедленно, даже если внутри пусто. У тонкого тома в момент создания резервируется только запись в таблице отображения (mapping table) — структуре, которая связывает логические блоки тома с физическими блоками на устройстве. Сам физический блок выделяется лениво (lazy allocation), в момент первой записи в соответствующий логический адрес.
Механика на примере LVM-thin, который используется в Proxmox и на многих Linux-хранилищах:
# Тонкий пул на 2 ТБ
lvcreate --type thin-pool -L 2T -n thinpool vg_storage
# Три тонких тома, каждый заявляет по 500 ГБ —
# суммарно 1.5 ТБ заявлено, но пул создан только для проверки
lvcreate -V 500G --thinpool thinpool -n vol1 vg_storage
lvcreate -V 500G --thinpool thinpool -n vol2 vg_storage
lvcreate -V 500G --thinpool thinpool -n vol3 vg_storage
На этом этапе lvs -a покажет три тома по 500 ГБ (LSize), но реальное использование пула (Data%) останется близким к нулю — потому что записей ещё не было. Каждая запись в файловую систему внутри тома (создание файла, рост базы, лог) вызывает выделение нового чанка (обычно 64 КБ – 1 МБ в зависимости от настроек пула) из общего физического пространства пула — и только тогда чанк "материализуется" физически.
То же самое происходит на уровне ZFS (zvol с -s для sparse-тома), на уровне SAN-массивов (thin LUN), на уровне облачных дисков — механизм универсален: заявленный размер — это верхний предел адресного пространства, а не гарантия резервирования. Мы разбирали смежный, но более верхнеуровневый случай — thin provisioning для виртуальных дисков VM — в статье про типы хранилищ Proxmox: там LVM-thin и ZFS фигурируют как варианты хранилища для дисков VM. Здесь мы спускаемся на уровень ниже — в саму механику тома, которая работает одинаково независимо от того, кладёте вы туда диск виртуалки, файл на файловом хранилище или базу данных напрямую.
Переподписка — разрешённая и часто намеренная практика
Переподписка (overprovisioning, oversubscription) диска — это ситуация, когда сумма заявленных объёмов всех тонких томов на хранилище превышает его реальную физическую ёмкость. Это не ошибка конфигурации и не баг — thin-технология специально это разрешает, и администраторы часто делают это осознанно ради экономии.
Коэффициент переподписки считается просто:
Коэффициент = (сумма заявленных объёмов всех тонких томов) / (реальная физическая ёмкость пула)
Пример: пул на 2 ТБ, десять томов по 500 ГБ каждый — сумма заявленного 5 ТБ, коэффициент переподписки 2.5×. Если под каждым томом реально лежит база данных, которая в среднем заполняет 150-200 ГБ из заявленных 500, администратор экономит физическое место — вместо десяти реальных дисков по 500 ГБ (5 ТБ) хватает пула на 2 ТБ, потому что реальное потребление ниже заявленного лимита.
Эта логика прямо аналогична оверкоммиту CPU и памяти в виртуализации — там гипервизор тоже раздаёт виртуальным машинам больше вычислительных ресурсов "на бумаге", чем физически есть в наличии, рассчитывая, что не все виртуалки одновременно упрутся в максимум. Мы разбирали эту механику и её пределы в статье про оверкоммит CPU и памяти — и там, и здесь суть одна: подписка "с запасом на бумаге" работает, пока совокупный реальный спрос не догоняет физический предел.
Разница дисковой переподписки в том, что цена ошибки выше и последствия резче — если о CPU-оверкоммите вы обычно узнаёте по деградации производительности (VM подтормаживают, но работают), то переподписка диска при исчерпании физического пространства даёт не деградацию, а жёсткий отказ записи.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКлючевая ловушка: кто на самом деле упирается в лимит
Вот механизм, который стоит понять железно, потому что именно его недооценка приводит к авариям.
У каждого тонкого тома есть заявленный лимит (например, 500 ГБ) — это "потолок", видимый гостевой системе. Но физическое хранилище, на котором лежат все тонкие тома пула, имеет свой собственный, отдельный предел — реальную физическую ёмкость пула (в примере выше — 2 ТБ). Это два разных числа, и второе не пересчитывается автоматически при создании томов.
Пока переподписка разрешена (сумма заявленного больше физической ёмкости), возможна ситуация: ни один отдельный том формально не достиг своего заявленного лимита (каждый показывает, скажем, 40% от заявленных 500 ГБ), но сумма реально записанных данных по всем томам вместе уже съела всю физическую ёмкость пула.
# Пример на пуле в 2 ТБ с тремя томами по 500 ГБ (переподписки 0.75x — не критично)
# Но если томов десять и все активно растут:
том1: заявлено 500 ГБ, реально записано 220 ГБ (44% от лимита тома)
том2: заявлено 500 ГБ, реально записано 210 ГБ (42% от лимита тома)
том3: заявлено 500 ГБ, реально записано 195 ГБ (39% от лимита тома)
...
том9: заявлено 500 ГБ, реально записано 205 ГБ (41% от лимита тома)
том10: заявлено 500 ГБ, реально записано 190 ГБ (38% от лимита тома)
Сумма реально записанного: ~2005 ГБ
Физическая ёмкость пула: 2000 ГБ
В этот момент физический пул заполнен на 100%, хотя КАЖДЫЙ отдельный том, если смотреть только на его собственный процент заполнения относительно заявленного лимита, выглядит наполовину пустым. Проверка df -h внутри гостевой системы каждого тома покажет "занято меньше половины" — и будет технически права относительно заявленного размера, но не будет отражать реальную опасность на уровне физического пула.
Когда физический пул заполняется, происходит не постепенная деградация производительности, а резкая и одновременная остановка записи для всех томов на этом пуле — независимо от того, сколько места, казалось бы, ещё "должно было" оставаться у конкретного тома. Это принципиально другая природа отказа, чем при исчерпании места на обычном (толстом) диске, где страдает только тот раздел, который заполнился.
В LVM-thin это проявляется так: пул уходит в состояние, когда новые чанки выделить неоткуда, и запись в любой том этого пула (даже в тот, что заполнен на 20% от своего заявленного размера) начинает возвращать ошибку ввода-вывода. Если пул не был предварительно переведён в режим --errorwhenfull y, поведение по умолчанию ядра может быть ещё неприятнее — процессы, пишущие в затронутые тома, подвисают в состоянии D (uninterruptible sleep) в ожидании места, которое так и не появится, вместо чистой ошибки.
# Проверить состояние thin-пула — это ключевая метрика, а не свободное место внутри тома
lvs -a -o+data_percent,metadata_percent vg_storage
# Пример вывода: пул заполнен физически на 97%,
# при этом отдельные тома пула показывают разный процент от СВОЕГО лимита —
# это разные числа, и путать их — источник аварии
Мониторинг: смотреть нужно на физическое, а не на заявленное
Единственный надёжный способ не попасть в эту ловушку — мониторить реальное заполнение физического хранилища (пула), а не заявленные лимиты отдельных томов. Мониторинг df внутри каждой гостевой VM или каждого тома по отдельности здесь бесполезен — он покажет процент от заявленного лимита конкретного тома, а не то, сколько реально осталось в общем физическом пуле.
Метрика, которую нужно снимать регулярно:
# Для LVM-thin — Data% самого пула, не отдельных LV поверх него
lvs --noheadings -o data_percent vg_storage/thinpool
# Для ZFS — реальное занятое место в пуле против его ёмкости
zpool list -o name,size,alloc,free,capacity
# Для аппаратных SAN/NAS — смотреть панель управления массива,
# там обычно есть отдельный показатель "physical pool utilization"
# или "thin provisioning utilization", отличный от per-LUN usage
Порог алерта стоит выставлять заранее, а не по факту достижения 100%. Разумная практика — предупреждение при 80% физической ёмкости пула и критический алерт при 90%, с расчётом на то, что между алертом и полным заполнением у вас должно остаться время на реакцию (расширение или очистку), а не только на панику. Мы подробно разбирали настройку алертов и типовые ошибки такого мониторинга в статье про мониторинг диска на VPS — там же есть готовые пороги и примеры конфигурации для Zabbix/Prometheus, применимые и к мониторингу thin-пула, если добавить туда именно метрику пула, а не отдельных разделов.
Отдельно стоит завести алерт на скорость роста (rate of growth), а не только на текущий процент — если физический пул растёт на 2% в сутки при активной переподписке, 80% может превратиться в 100% за считанные дни, и разовый снимок состояния этого не покажет.
Осознанный коэффициент переподписки — а не случайный
Переподписка — легитимный инструмент экономии, но её уровень должен быть результатом решения, а не побочным эффектом того, что администраторы создавали тома по мере надобности, не сверяясь с суммой уже выданного.
Практический подход:
- Посчитайте текущий коэффициент — сумма заявленных объёмов всех тонких томов пула, делённая на физическую ёмкость пула. Если получилось больше 1.5-2×, это уже требует сознательного решения "мы согласны на этот риск", а не случайности.
- Оцените паттерн роста каждого тома — базы данных и логи растут монотонно и предсказуемо; временные файлы и кэши могут расти рывками. Чем непредсказуемее рост, тем консервативнее должен быть коэффициент.
- Заложите буфер под скорость реакции — если расширение физического хранилища занимает у вас день (добавить диск в RAID, расширить пул), держите порог алерта с запасом на этот день, а не впритык к 100%.
Таблица для ориентира (не строгие правила, а отправная точка для решения):
| Профиль нагрузки | Разумный коэффициент переподписки | Комментарий |
|---|---|---|
| Статичные данные, редкий рост (архивы, бэкапы) | 3-4× | Реальный рост предсказуем и медленный |
| Базы данных с умеренным ростом | 1.5-2× | Нужен запас реакции, рост может ускориться |
| Логи, кэши, временные данные с непредсказуемым ростом | 1-1.3× | Риск резкого скачка выше, переподписка минимальна |
| Критичные продакшн-тома без права на простой | 1× или меньше | Переподписка здесь неоправданна — цена отказа слишком высока |
План действий при приближении к порогу
Реакция на приближение к порогу должна быть спланирована заранее, а не изобретаться в момент, когда запись уже остановилась. Два основных сценария, которые стоит прописать до того, как они понадобятся:
Расширение физического хранилища. Для LVM-thin это добавление физического тома в группу и расширение пула:
# Добавить новый физический диск/раздел в volume group
vgextend vg_storage /dev/sdX1
# Расширить thin-пул на добавленное пространство
lvextend -L +500G vg_storage/thinpool
Для ZFS — добавление устройства в пул (zpool add или замена дисков на больший объём с последующим zpool online -e). Это действие лучше выполнять при заполнении 80-85%, пока есть время сделать его аккуратно, а не в аварийном режиме при 99%.
Удаление или сжатие неактуальных данных. Если расширение физически невозможно прямо сейчас (нет свободных слотов, бюджет не согласован), второй рычаг — освободить реально занятое место: удалить старые снапшоты (они тоже занимают место в пуле пропорционально изменившимся блокам), почистить логи, найти том с аномальным ростом и разобраться, не сбой ли это (например, база, которая не делает VACUUM, или процесс, который льёт лог без ротации).
Оба сценария должны быть прописаны как runbook с конкретными командами и владельцем действия — до того, как алерт сработает, а не в процессе разбора инцидента. Ситуация "физическое хранилище заполнилось, но неясно, у кого есть права его расширить" в момент отказа записи — плохое время для выяснения ролей.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Почему том вообще позволяет заявить больше места, чем физически есть?
Это и есть суть тонкого выделения — заявленный размер это верхняя граница адресного пространства тома, а не резервирование физического места. Технология рассчитана на то, что реальное использование в среднем ниже заявленного, и разрешает такую переподписку намеренно.
Как понять, что мой пул уже в опасной зоне переподписки, если я не считал это при создании томов?
Посчитайте сумму LSize (или аналог) всех тонких томов пула и разделите на физическую ёмкость пула (data_percent в LVM или alloc/size в ZFS дают текущее физическое заполнение). Если коэффициент выше 2× и все тома активно растут — стоит присмотреться внимательнее и, возможно, снизить будущую переподписку.
Можно ли автоматически ограничить том, чтобы он не мог "случайно" заполнить весь пул?
Частично — можно снизить заявленный лимит конкретных томов, но это не решает саму проблему переподписки, если несколько томов всё равно растут одновременно. Реальная защита — мониторинг физического пула плюс алерты, а не ограничение отдельных томов.
Что произойдёт с данными, если пул всё же заполнился на 100%?
Данные, уже записанные и подтверждённые (fsync), обычно не повреждаются — но новые записи будут отклоняться с ошибкой ввода-вывода или зависать, пока место не освободится. Файловые системы внутри затронутых томов могут перейти в режим только для чтения, чтобы не рисковать целостностью — восстановление возможно, но требует освобождения места и последующей проверки (fsck и аналоги).
Отличается ли это поведение для тонких дисков VM в Proxmox от тонких LUN на SAN-массиве?
Механика идентична на концептуальном уровне — заявленный размер и физическая ёмкость пула разделены, и заполнение физического пула бьёт по всем потребителям одновременно. Отличаются только инструменты мониторинга и команды — на SAN обычно есть собственная панель с готовым показателем thin utilization, тогда как на LVM-thin/ZFS это нужно снимать самостоятельно скриптами или системой мониторинга.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →