Тонкие тома переподписали, хранилище кончилось и встали 12 машин
Утром дежурный увидел в мониторинге, что хост с виртуалками жив, диск занят на 62%, нагрузка в норме — и одновременно двенадцать почтовых уведомлений о недоступности сервисов. Разрыв между «на дашборде всё хорошо» и «половина кластера легла» — это всегда история про то, что мониторили не ту метрику. В этот раз виноват был тонкий том: хост честно показывал свободное место на диске, а пул данных LVM-thin, из которого реально нарезались виртуальные диски, был заполнен под завязку.
Содержание
Что случилось: хронология падения
Нода на Proxmox VE держала 14 виртуалок в общем thin-пуле pve/data поверх RAID-массива на NVMe. Часть машин — рабочие сервисы клиентов, часть — внутренние: очередь задач, база для логов, пара тестовых стендов, которые давно пора было снести, но руки не дошли.
Около 03:40 по логам первым встал сервис очереди задач: клиенты жаловались, что задачи принимаются, но не выполняются. К 04:10 пришли алерты о недоступности ещё нескольких машин. К моменту, когда дежурный открыл консоль, из 14 виртуалок не отвечали 12 — они не были выключены, они были в состоянии paused, QEMU-процессы висели, не потребляя CPU.
Первое, что бросилось в глаза: df -h на хосте показывал занятость смонтированных разделов на 58-64% — ничего похожего на «диск кончился». Но это была ловушка. df смотрит на файловую систему хоста, а не на реальное заполнение LVM-thin пула, из которого нарезаны виртуальные диски. Эти две цифры расходятся ровно там, где включена переподписка — thin provisioning.
Что показывали логи и метрики
В dmesg и journalctl -k на хосте нашлись строки такого вида:
device-mapper: thin: 253:7: reached low water mark for data device: sending event
device-mapper: thin: 253:7: no free data space available
А чуть позже, уже про конкретные виртуалки:
block I/O error in device 'drive-scsi0': No space left on device
Первая строка — предупреждение о low water mark — теоретически должна была прийти заранее и дать время среагировать. Она и пришла, за 11 часов до падения, но ушла в общий поток syslog, откуда её никто не вытащил: алертинг был настроен на заполнение файловых систем хоста через node_exporter, а не на data-процент самого thin-пула. Это частая дыра: стандартные экспортеры дисковых метрик видят точки монтирования, но не заглядывают внутрь lvs. О том, какие именно параметры диска стоит закладывать с запасом и мониторить отдельно от общего «места на диске», у нас есть отдельный разбор — сколько диска на самом деле нужно и что мониторить отдельно.
Проверка lvs на живой ноде (со временем инцидента, до починки) дала бы что-то вроде:
LV VG Attr LSize Pool Data% Meta%
data pve twi-aotz-- 1.80t 100.0 62.3
Data% в 100 — это и есть настоящая причина. LVM-thin пул, столкнувшись с заполнением своего data-девайса, переводит операции записи для всех томов в этом пуле в состояние ошибки. Не только для того тома, который «съел» место — для всех. Отсюда и одновременное падение 12 машин: они физически не были связаны друг с другом ничем, кроме общего пула.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПервая гипотеза: отказ RAID-контроллера
Первая мысль дежурного — контроллер или сам массив. NVMe-диски в RAID иногда деградируют резко, и картина «половина хоста легла разом» на это похожа. Проверили состояние массива через утилиту контроллера и smartctl по каждому диску отдельно — все диски здоровы, ошибок чтения/записи нет, батарея кэша (если она есть в конкретной конфигурации) в порядке. Массив не деградировал, ребилда не было. Гипотезу отбросили в первые 10 минут — благо это самая быстрая проверка.
Вторая гипотеза: сетевое хранилище или сбойный диск конкретной ВМ
Вторая версия — что подвисло сетевое хранилище (у части инфраструктуры диски лежат на NFS) или что один конкретный «шумный» том с обвалившейся файловой системой утянул за собой остальные через общий backend. Проверили: хранилище этой ноды было полностью локальным — LVM-thin поверх локального RAID, никакого NFS/Ceph в цепочке. Отдельно проверили, не «просел» ли конкретный диск из-за бэд-блоков — smartctl -a по каждому физическому диску массива ошибок не показал.
Тогда посмотрели на конфигурацию хранилища самого Proxmox — тип storage, режим переподписки, какие тома thin, а какие thick. Про то, чем локальный LVM-thin отличается от директории, ZFS-пула или Ceph в терминах Proxmox и когда какой выбирать, у нас есть отдельная статья: хранилища в Proxmox — что и когда. В этом кластере исторически выбрали LVM-thin ради гибкости — можно было раздавать виртуалкам диски «с запасом», не резервируя место заранее. Именно эта гибкость и оказалась миной замедленного действия.
Что оказалось на самом деле: пул был переподписан в разы
Собрали полную картину через lvs -a --units g -o+data_percent,metadata_percent,lv_size и сверили с суммой виртуальных размеров дисков всех ВМ (qm config <id> по каждой машине, поле scsi0 и так далее).
Оказалось: суммарный виртуальный объём дисков всех 14 машин был примерно в 2.8 раза больше физической ёмкости thin-пула. Такое overcommit — обычная практика для thin provisioning, и сама по себе цифра не катастрофа: большинство виртуалок реально используют куда меньше, чем им выделено «на бумаге». Проблема была в трёх наложившихся факторах:
- Постепенный рост реального использования. За несколько месяцев несколько ВМ действительно наполнили выделенное место — база логов разрослась, тестовые стенды скопили мусор, который никто не чистил.
- Снапшоты держались подолгу. На части машин стояли почасовые снапшоты с ретеншеном в несколько дней «на всякий случай» — а в LVM-thin каждый снапшот держит собственные изменённые блоки, и чем дольше он живёт при активной записи в оригинал, тем больше реального места он занимает сверх видимого размера тома. Мы отдельно разбирали, как это работает и какие риски несёт долгоживущий снапшот, в статье про LVM-снапшоты, расширение и риски.
- Мониторинг видел не ту цифру. Алерты были настроены на заполнение файловых систем хоста (
df), а не на data-процент thin-пула (lvs). Диск хоста показывал разумные 60%, потому что там лежали только образы бэкапов и системные файлы — сам thin-пул как логическая сущность в это число не попадал напрямую, его нужно опрашивать отдельной командой.
В сумме: реальное потребление данных внутри пула росло медленно и незаметно несколько недель, пересекло low water mark за 11 часов до инцидента, никто не увидел предупреждение — и в 03:40 пул исчерпался полностью. С этого момента любая запись в любой том пула получала ошибку, а libvirt/QEMU реагировали на это постановкой виртуалки на паузу, чтобы не потерять данные окончательно.
Как раскопали причину и восстановили сервисы
Порядок действий на месте:
- Убедились, что физически места для расширения пула нет — на массиве действительно не оставалось свободных экстентов внутри volume group. Проверка:
vgsпоказываетVFreeблизко к нулю. - Приняли решение освободить место, а не расширять пул железом прямо ночью. Нашли и удалили самые старые и явно ненужные снапшоты через
lvremove— это единственная быстрая операция, которая реально возвращает блоки пулу (обычное удаление файлов внутри гостевой ОС пространство пулу не возвращает, пока фактически не задействован discard/TRIM с проброшеннымdiscardна уровне тома). - После освобождения нескольких процентов пространства (Data% опустился ниже 95%) сняли виртуалки с паузы:
qm unpause <id>по каждой из 12 машин. - Проверили целостность файловых систем внутри поднявшихся гостей —
fsckна linux-гостях в safe-режиме, там, где были логи о прерванной записи. В большинстве случаев обошлось без потери данных: журналируемые ФС (ext4, xfs) пережили обрыв записи корректно, но пара баз данных потребовала ручного восстановления из WAL. - Только после стабилизации сервисов занялись расширением самого пула — добавили физический том в volume group и выполнили
lvextendдля thin-пула, чтобы получить постоянный запас, а не временную передышку.
Восстановление большинства сервисов заняло около часа с момента обнаружения; часть тестовых машин решили не поднимать вовсе, раз они годами простаивали и без пользы занимали место в пуле.
Что изменили после инцидента
Первое и самое важное — мониторинг стал смотреть на правильную метрику. Добавили отдельную проверку lvs -o+data_percent,metadata_percent с порогами предупреждения на 75% и критики на 90% по data и отдельно по metadata (метаданные thin-пула — маленький, но не менее опасный ресурс: если кончится он, поведение будет таким же катастрофичным). Подробно про то, какие метрики диска стоит собирать отдельно от общего df и с каким шагом опроса, разобрано в статье про мониторинг диска на сервере — частые ошибки и решения.
Второе — включили автоматическое расширение пула на уровне LVM, где это оправдано железом. В /etc/lvm/lvm.conf для thin-пулов доступны параметры автоматического роста:
activation {
thin_pool_autoextend_threshold = 80
thin_pool_autoextend_percent = 20
}
Это не панацея — если в volume group физически нет свободных экстентов, автоматика не поможет, но она даёт запас времени при наличии свободного места, которое просто не было довыделено вовремя.
Третье — пересмотрели коэффициент переподписки. Вместо «выдавать диски щедро, потому что тонкий том всё равно сожмётся» приняли внутреннее правило: суммарный виртуальный объём в одном thin-пуле не должен превышать физическую ёмкость более чем в полтора-два раза, а не в почти три, как было. Отдельно завели правило по ретеншену снапшотов — не больше 48 часов почасовых точек на продакшн-томах, дальше — только суточные бэкапы вне пула.
Четвёртое — развели критичные и некритичные нагрузки по разным пулам хранения. Тестовые стенды и внутренние вспомогательные сервисы теперь живут в отдельном, меньшем по важности пуле, чтобы их рост или чья-то забытая нагрузка не могли утянуть за собой рабочие клиентские машины. Заодно почистили давно неиспользуемые тестовые ВМ — простой аудит qm list по каждой ноде раз в квартал экономит куда больше места, чем кажется на старте.
Наконец, договорились, что при любом алерте уровня low water mark на thin-пуле реакция — не «посмотреть позже», а немедленная проверка в течение часа, потому что временной запас между первым предупреждением и полным заполнением пула на практике оказался куда меньше, чем хотелось бы закладывать.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Почему df -h на хосте не показал проблему заранее?
Потому что df видит файловые системы хоста и точки монтирования, а не внутреннее заполнение LVM-thin пула. Пул может быть заполнен на 100% при том, что физический раздел, на котором он лежит, использован лишь частично — это два разных уровня абстракции, и мониторить нужно оба отдельно.
Значит ли это, что тонкие тома вообще не стоит использовать?
Нет, thin provisioning — рабочий и распространённый подход, он экономит место там, где виртуалкам реально не нужен весь заявленный объём. Проблема не в самой технологии, а в отсутствии мониторинга правильной метрики и в слишком агрессивном коэффициенте переподписки без плана на случай, если он себя не оправдает.
Почему упали именно все 12 машин, а не только та, что заполнила диск?
Потому что все они делили один и тот же thin-пул. Когда data-девайс пула заканчивается, LVM переводит в состояние ошибки операции записи для всех логических томов этого пула — изоляции между томами на этом уровне нет, это общий ресурс.
Можно ли было предотвратить это без апгрейда железа?
Частично да — более раннее обнаружение через мониторинг lvs, более короткий ретеншен снапшотов и своевременная чистка неиспользуемых томов отодвинули бы момент исчерпания на недели или месяцы. Но при постоянно растущей реальной нагрузке рано или поздно физическое расширение всё равно потребуется — мониторинг покупает время на плановую реакцию, а не отменяет саму проблему роста данных.
Что делать, если пул уже заполнился и виртуалки встали прямо сейчас?
В первую очередь искать быстро освобождаемое место — старые снапшоты, ненужные тома, — и удалять именно через lvremove, а не удаление файлов внутри гостя (без проброшенного TRIM это не освобождает блоки пулу). Только после того как data-процент опустится до безопасного уровня, снимать виртуалки с паузы и проверять целостность файловых систем внутри них.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →