Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки
Работоспособность модуля гарантируется только при использовании стоковых ядер, поставляемых вместе с поддерживаемыми дистрибутивами.
Работоспособность модуля при использовании других ядер или дистрибутивов возможна, но не гарантируется.
Почему в кластере не создаются ресурсы BlockDevice и LVMVolumeGroup?
-
Ресурсы BlockDevice могут не создаваться, если устройства не проходят фильтрацию контроллера. Убедитесь, что устройства соответствуют требованиям.
-
Ресурсы LVMVolumeGroup могут не создаваться из-за отсутствия в кластере ресурсов BlockDevice, так как их имена используются в спецификации LVMVolumeGroup.
-
Если ресурсы BlockDevice существуют, а ресурсы LVMVolumeGroup отсутствуют, убедитесь, что у существующих групп томов LVM на узле имеется LVM-тег
storage.deckhouse.io/enabled=true.
Почему LVMVolumeGroup сообщает BlockDeviceNotFound или NodeNotDescribed?
Обе причины появляются на условии VGReady и означают одно и то же: у физического тома группы нет ресурса BlockDevice, который бы его называл, поэтому status.nodes не может перечислить это устройство. Различаются они тем, насколько полно агент всё же смог описать узел, и от этого зависит, продолжает ли группа томов принимать новые тома.
| Причина | Что означает | Что делать |
|---|---|---|
BlockDeviceNotFound |
Часть физических томов удалось назвать, часть — нет. status.nodes был перезаписан в этом же проходе, поэтому vgSize, vgFree и занятость thin-пулов актуальны — отсутствуют только записи для неназванных устройств. Группа томов остаётся Ready и продолжает принимать тома. |
Обычно ничего: состояние проходит за секунды, как только дискаверер блочных устройств зарегистрирует устройство. Если держится — устройство из тех, что не становятся BlockDevice (см. ниже). |
NodeNotDescribed |
Ни один физический том назвать не удалось, поэтому агент отказался перезаписывать status.nodes. Ресурс показывает статус от прошлого прохода, и свободное место в нём настолько же старое. LVMVolumeGroup намеренно выходит из Ready, и планировщик перестаёт размещать на нём новые тома. |
Выяснить, почему на узле вообще не появляется ни одного BlockDevice (см. ниже), затем посмотреть лог агента на этом узле. |
Устройство никогда не становится BlockDevice в двух случаях, и в обоих условие держится, пока вы не вмешаетесь:
- устройство меньше минимального размера, который принимает контроллер (см. требования);
- устройство исключено фильтром BlockDeviceFilter.
Агент повторяет попытку ограниченное число проходов дискавери, затем прекращает и пишет об этом в лог; условие продолжает сообщать о состоянии. Правка BlockDeviceFilter, допускающая устройство, сама запускает проход дискавери, поэтому группа томов восстановится без перезапуска агента.
LVMVolumeGroup, который ни разу не описал свой узел, остаётся в фазе Pending, а не NotReady: условие AgentReady выставляется только на ресурс, чей status.nodes называет узел. Сообщение агрегированного условия Ready при этом несёт блокирующую причину, поэтому kubectl describe показывает причину, а не голое «waiting for the conditions AgentReady to be configured».
Почему ресурс LVMVolumeGroup и группа томов остались после попытки удаления?
Такая ситуация возможна в двух случаях:
-
В группе томов имеются логические тома (Logical Volume).
Контроллер не отвечает за удаление логических томов с узла. Если в созданной с помощью ресурса группе томов имеются логические тома, удалите их вручную на узле. После этого ресурс и группа томов вместе с физическими томами (Physical Volume) будут удалены автоматически.
-
На ресурсе имеется аннотация
storage.deckhouse.io/deletion-protection.Данная аннотация защищает от удаления ресурс и созданную им группу томов. Удалите аннотацию, выполнив команду:
d8 k annotate lvg %lvg-name% storage.deckhouse.io/deletion-protection-После выполнения команды ресурс и группа томов будут удалены автоматически.
Почему не удаётся создать группу томов с помощью ресурса LVMVolumeGroup?
Ресурс не проходит валидацию контроллера (валидация Kubernetes прошла успешно). Причину можно увидеть в поле status.message ресурса или в логах контроллера.
Чаще всего проблема связана с некорректно указанными ресурсами BlockDevice. Убедитесь, что выбранные ресурсы удовлетворяют следующим требованиям:
- поле
status.consumableимеет значениеtrue; - для групп томов типа
Localуказанные ресурсы BlockDevice принадлежат одному узлу; - указаны актуальные имена ресурсов BlockDevice.
Полный список ожидаемых значений доступен в описании ресурса LVMVolumeGroup.
Что произойдет, если я отключу одно из устройств в группе томов? Соответствующий ресурс LVMVolumeGroup удалится?
Ресурс LVMVolumeGroup существует до тех пор, пока существует соответствующая группа томов. Пока существует хотя бы одно устройство, группа томов сохраняется, но помечается как неработоспособная. Текущее состояние отражается в поле status ресурса.
После восстановления отключённого устройства на узле группа томов LVM восстановит работоспособность, а соответствующий ресурс LVMVolumeGroup отобразит актуальное состояние.
Как передать управление существующей группой томов LVM контроллеру?
Добавьте LVM-тег storage.deckhouse.io/enabled=true на группу томов LVM на узле:
vgchange myvg-0 --addtag storage.deckhouse.io/enabled=trueКак остановить отслеживание группы томов LVM контроллером?
Удалите LVM-тег storage.deckhouse.io/enabled=true у нужной группы томов LVM на узле:
vgchange myvg-0 --deltag storage.deckhouse.io/enabled=trueПосле этого контроллер перестанет отслеживать выбранную группу томов и самостоятельно удалит связанный с ней ресурс LVMVolumeGroup.
Почему LVM-тег storage.deckhouse.io/enabled=true появляется автоматически?
LVM-тег появляется в следующих случаях:
- Группа томов LVM создана через ресурс LVMVolumeGroup. В этом случае контроллер автоматически добавляет LVM-тег
storage.deckhouse.io/enabled=trueна созданную группу томов LVM. - На группе томов или её thin pool был LVM-тег модуля
linstor—linstor-*.
При миграции со встроенного модуля linstor на модули sds-node-configurator и sds-replicated-volume LVM-теги linstor-* автоматически заменяются на storage.deckhouse.io/enabled=true в группах томов. Управление этими группами томов передаётся модулю sds-node-configurator.
Как создать LVMVolumeGroup с помощью ресурса LVMVolumeGroupSet?
Для создания ресурсов LVMVolumeGroup с помощью LVMVolumeGroupSet укажите в спецификации LVMVolumeGroupSet селекторы для узлов и шаблон для создаваемых ресурсов LVMVolumeGroup.
Поддерживается только стратегия PerNode: контроллер создаёт по одному ресурсу LVMVolumeGroup из шаблона для каждого узла, соответствующего селектору.
Пример спецификации LVMVolumeGroupSet:
apiVersion: storage.deckhouse.io/v1alpha1
kind: LVMVolumeGroupSet
metadata:
name: my-lvm-volume-group-set
labels:
my-label: my-value
spec:
strategy: PerNode
nodeSelector:
matchLabels:
node-role.kubernetes.io/worker: ""
lvmVolumeGroupTemplate:
metadata:
labels:
my-label-for-lvg: my-value-for-lvg
type: Local
blockDeviceSelector:
matchLabels:
status.blockdevice.storage.deckhouse.io/model: <model>
actualVGNameOnTheNode: <actual-vg-name-on-the-node>Как изменить UUID у групп томов при клонировании виртуальных машин?
UUID у групп томов можно изменить только при отсутствии активных логических томов в группе томов.
Если в группе томов есть активные логические тома, выполните следующие действия:
-
Отмонтируйте логический том, выполнив команду:
umount /mount/point -
Деактивируйте логический том или группу томов, выполнив команду:
-
Для деактивации конкретного логического тома выполните команду, изменив
<LV_NAME>на имя логического тома:lvchange -an <LV_NAME> -
Для деактивации всех логических томов в группе выполните команду, изменив
<VG_NAME>на имя группы томов:lvchange -an <VG_NAME>
-
-
После деактивации всех логических томов измените UUID у групп томов, выполнив команду:
vgchange -u <VG_NAME>Команда сгенерирует новые UUID для указанной группы томов. Для изменения UUID всех групп томов на виртуальной машине выполните:
vgchange -u
При необходимости команду можно добавить в скрипт cloud-init для автоматического выполнения при создании виртуальных машин.
Как работают файловые устройства (fileDevices)?
Файловые устройства позволяют отдать часть существующей файловой системы под LVM, не имея выделенных блочных устройств. Агент создаёт в указанном каталоге файл с предварительно выделенным местом, подключает его как loop-устройство и использует как LVM Physical Volume.
Ограничения
- Утилиты на узле. В отличие от
lvm,nsenterиlsblk, которые агент приносит с собой в/opt/deckhouse/sds/bin, операции с loop-устройствами и файлами выполняются собственными утилитами узла —losetup,fallocate,stat,mkdirиrm— в mount namespace (пространстве имён монтирования) процесса PID 1.losetupдолжен поддерживать--nooverlap, то есть требуется util-linux 2.29 или новее (2016 год; все актуальные дистрибутивы подходят, RHEL/CentOS 7 — нет). На более старом узле каждая попытка выделить устройство завершается ошибкойunrecognized option '--nooverlap', которая попадает в ресурс какFileDeviceNotApplied.--direct-ioобязательным не является: если его нет или ядро отказывает, агент пишет предупреждение и продолжает работать с буферизованным вводом-выводом. - Только внутри базового каталога. Каждый
directoryдолжен совпадать с параметром модуляfileDevicesDirectory(по умолчанию/opt/deckhouse/sds/file-devices) либо быть его подкаталогом. Пути вне этого поддерева отклоняются, чтобы нельзя было заполнить произвольный путь на узле. Чтобы использовать другое расположение, укажите вfileDevicesDirectoryточку монтирования выделенного диска. - Каталог создаётся автоматически. Агент сам создаёт каталог (
mkdir -p), если его нет. Путь должен быть абсолютным и без сегментов..— относительный путь отклоняется на admission, сегмент..проверяет агент, — и изменитьdirectoryвпоследствии нельзя. Само выделение места завершится ошибкой только если файловая система смонтирована только для чтения или в пути встречается не-каталог. - Увеличение. У существующей записи можно увеличить
size— файл-подложка, loop-устройство и физический том (PV) вырастают на месте, online, без размонтирования. Полеdirectoryизменить нельзя; чтобы взять место с другой файловой системы, добавьте новую запись с новымname(не более 32 записей). - Уменьшение не поддерживается. Уменьшить
sizeнельзя, такая правка отклоняется на уровне admission. Вернуть ёмкость — значит уменьшить Volume Group (pvmove+vgreduce), а это может быть невозможным, если на остальных PV нет места, и деструктивным, если возможно; для блочных устройств модуль Volume Group тоже не уменьшает. Чтобы вернуть место, не меняя размеров, используйте discard/TRIM (см. ниже). - Удаление записи. Запись, которая ещё не была создана на узле, можно удалить из спецификации. Удаление записи с живым PV трактуется как drift (расхождение между запрошенным и фактическим состоянием) — агент сообщает об этом в условии
VGConfigurationAppliedс причинойFileDeviceDriftи ничего не разрушает. Группа томов продолжает работать и остаётся в фазеReady: эта причина считается допустимым состоянием, поэтому сообщение о расхождении не выводит хранилище узла из строя. Чтобы устранить расхождение, либо верните запись, либо удалите PV вручную:pvmove+vgreduce+pvremove. - Место выделяется сразу. Файлы создаются через
fallocate, то есть место резервируется на файловой системе целиком. Агент откажется создавать или увеличивать файл, после которого на файловой системе останется меньше свободного места, чем резервирует параметр модуляfileDevicesMinFreeSpacePercent(по умолчанию 15%), — слишком большая запись будет отражена в статусе ресурса, а не доведёт узел доDiskPressure. Уменьшать этот параметр стоит, только еслиfileDevicesDirectoryуказывает на диск, от которого больше ничего на узле не зависит. - Минимальный размер — 1Gi.
- Накладные расходы. LVM поверх loop-устройства поверх файловой системы даёт двойную косвенность. Используйте файловые устройства только когда выделенных дисков нет. Агент запрашивает у loop-драйвера direct I/O (прямой ввод-вывод, минующий кэш страниц), чтобы каждая страница не кэшировалась дважды; если файловая система под файлом-подложкой не поддерживает
O_DIRECT(например, tmpfs), ядро откажет, агент напишет предупреждение и продолжит работу с буферизованным вводом-выводом. - Фильтр LVM на узле. NodeGroupConfiguration добавляет loop-устройства в общесистемный
global_filterLVM, поэтому запущенные на узлеlvm/pvsих не видят (фильтр задан вlvm.confи действует независимо от привилегий). Агент переподключает свои файлы-подложки при старте и передаёт собственный--configдля управляемых групп томов. dmeventdне следит за thin-пулами на файловых устройствах.dmeventdчитаетlvm.confузла, поэтому фильтр выше скрывает от него физические томá на loop-устройствах. Для thin-пула в файловой группе томов не работают ни autoextend (автоматическое расширение) на стороне ядра, ни предупреждения «пул заполнен на 80 %», которые есть у thin-пула на блочном устройстве. На управление ёмкостью это не влияет — размер thin-пула модуль задаёт черезspec.thinPools, а не через autoextend, — но привычных сообщенийdmeventdне будет. Следите за метриками самого модуля:sds_node_configurator_lvg_thin_pool_used_size_bytesи гейджи..._file_devices_directory_*(см. ниже).- Посторонний
losetupна узле агент не трогает. Агент считает loop-группу томов своей только если имя файла-подложки соответствует шаблонуsds-<имя LVMVolumeGroup>.<имя записи>.img, и не станет ни активировать, ни перетегировать, ни принимать под управление, ни реконсилировать группу, которая ему не соответствует. Это важно для образов, несущих LVM-теги самого модуля: например, бэкап диска узла, подключённый черезlosetup -fдля восстановления, или вложенный кластер на rawfile-томе — по одному тегу такая группа томов выглядела бы управляемой, а совпадение её имени с именем живой группы приводило бы к отчёту о дубликате. Делать на узле ничего не нужно, но каждую пропущенную по этой причине группу томов агент называет в логе. - Не удаляйте файл-подложку, пока к нему подключено loop-устройство. Физический том останется живым на удалённом inode (
losetup -aпокажет путь с пометкой(deleted)), а сам путь перестанет существовать. Агент это распознаёт и отказывается провижинить запись, сообщаяFileDeviceNotApplied, вместо того чтобы создать второй файл по тому же пути — это добавило бы в группу томов второй физический том и удвоило её. Восстановиться можно, вернув файл на место либо выведя физический том черезpvmove+vgreduce+pvremoveи затем удалив запись. Чтобы освободить место внутри файлового устройства, используйтеfstrim(см. ниже). - Не подключайте файл-подложку через
losetupвручную. Два loop-устройства на один файл — это два физических тома одинакового размера над одними и теми же блоками. Агент отказывается работать с таким файлом вообще: он не будет его провижинить, увеличивать или удалять, а удаление LVMVolumeGroup остановится с перечислением loop-устройств в condition, вместо того чтобы отключить одно из двух и удалить файл, из которого второе ещё читает. Отключите лишнее устройство командойlosetup -d, и reconcile продолжится сам.
Как посмотреть файловую группу томов на узле
Из-за общесистемного фильтра, описанного выше, обычный pvs на узле показывает файловую группу томов как группу без физических томов — а именно с этой команды и начинается диагностика. Чтобы увидеть реальную картину, переопределите фильтр на один вызов (это тот же фильтр, который передаёт сам агент):
# физические томá, включая loop-устройства
lvm pvs --config 'devices/global_filter=["r|^/dev/rbd|","r|^/dev/drbd|","r|^/dev/nbd|"]'
# то же самое для vgs / lvs
lvm vgs --config 'devices/global_filter=["r|^/dev/rbd|","r|^/dev/drbd|","r|^/dev/nbd|"]'
# к какому файлу-подложке подключён каждый loop-минор
losetup -a
# файлы-подложки, которыми владеет модуль; имя файла — sds-<имя LVMVolumeGroup>.<имя записи>.img
ls -l /opt/deckhouse/sds/file-devicesНе удаляйте запись про loop из lvm.conf: именно этот фильтр не даёт собственным pvscan и юнитам активации на узле забрать эти устройства в обход агента.
Если запись не удалось применить
Запись, которую узел не смог поднять (не осталось места под файл-подложку, losetup отказал, не прошло увеличение), отражается в условии VGConfigurationApplied с причиной FileDeviceNotApplied и повторяется на каждом цикле согласования. Сама группа томов при этом не затронута: она продолжает обслуживать все свои тома и остаётся в фазе Ready, а остальная часть цикла (другие записи, рост thin-пула, увеличение PV) выполняется. Не поступившая ёмкость — это не то же самое, что сломавшееся хранилище, поэтому одна неудачная запись никогда не выводит хранилище узла из строя.
Причины, которые агент выставляет в этом условии, пока группа томов продолжает работать:
| Причина | Что означает | Что делать |
|---|---|---|
ValidationFailed |
Запись некорректна (каталог вне базового пути, размер меньше 1Gi). | Исправить запись. |
FileDeviceNotApplied |
Узел не смог поднять запись. | Освободить место в directory либо посмотреть в логе агента, какая именно команда не прошла. |
FileDeviceGrowFailed |
Увеличение size у записи не прошло. Каждый шаг последовательности роста завершается в сторону меньшего размера, поэтому группа томов осталась прежнего размера. |
Освободить место в directory; попытка будет повторена. |
AliasResolutionFailed |
Агент не может привести пути PV, о которых сообщил LVM, к каноническому виду и потому не может определить, входит ли loop-устройство в группу томов. Пока это не устранено, новые файловые устройства в неё не добавятся. | Проверить бинарник nsenter у агента и ссылки /dev/disk/by-id на узле. |
FileDeviceDrift |
Из спецификации удалена запись, за которой стоит живой PV. | Вернуть запись либо удалить PV вручную. |
CacheStale |
На узле есть группа томов, о которой LVM-кэш агента ещё не знает, поэтому реконсиляции не с чем работать. Проходит само. | Ничего; разрешится на следующем скане. |
Ещё одной причины, VGCheckFailed, в этом списке нет: она означает, что агент вообще не может прочитать группы томов узла, и LVMVolumeGroup, чьё хранилище агент перестал видеть, намеренно выводится из обслуживания. Проверьте, что lvm.static и nsenter работают внутри пода агента.
Как откатить слишком большой размер
size можно только увеличивать, поэтому запись, поднятую выше того, что вмещает файловая система, просто вернуть к прежнему значению нельзя — LVMVolumeGroup будет сообщать FileDeviceNotApplied на каждом цикле. Откат без пересоздания ресурса делается в два шага:
- Удалите запись из
spec.fileDevices. API-сервер такое удаление принимает. Если запись уже была создана на узле, её PV и файл-подложка сохраняются, а причина в условии меняется наFileDeviceDrift. - Добавьте запись обратно с тем же
nameи прежним размером. Правило перехода сравнивает только с текущим состоянием записи, а её сейчас нет, поэтому меньший размер принимается. Он совпадёт с существующим PV, ничего увеличивать не потребуется, и LVMVolumeGroup вернётся вReady.
Между шагами группа томов продолжает работать, ничего не удаляется.
Возврат места (обычный ответ на вопрос «как уменьшить размер?»)
Чаще всего просьба уменьшить файловое устройство означает «верните место, которое освободилось после удаления данных». Для этого resize не нужен — нужен fstrim.
Файлы-подложки создаются через fallocate, поэтому файл занимает свой полный размер на файловой системе узла с момента создания и не растёт и не уменьшается сам по мере записи или удаления данных внутри тома.
Вернуть место файловой системе узла всё же можно — через цепочку discard (TRIM), которая для таких устройств работает от начала до конца:
файловая система на томе → thin LV → thin pool (создаётся с discards=passdown по умолчанию) → /dev/loopN → файл-подложка.
Loop-устройство транслирует discard в FALLOC_FL_PUNCH_HOLE на файле-подложке, превращая освобождённые области в дыры и делая файл разреженным. Чтобы запустить возврат места после удаления данных:
- периодически выполняйте
fstrim <точка монтирования>на файловой системе тома (например, через systemd-юнитfstrim.timer), либо - монтируйте том с опцией
-o discardдля непрерывного (online) discard.
Нюансы:
- Освобождаются только целые чанки thin pool, поэтому эффект зависит от размера чанка и выравнивания.
- Снапшоты удерживают чанки, на которые ссылаются: место, общее со снапшотом, не освободится, пока снапшот не удалён.
- Файл-подложка уменьшается только после цикла «запись → удаление → trim»; только что созданный файл всегда занимает полный выделенный размер.
Мониторинг
Агент экспортирует по узлу четыре gauge-метрики для файловых устройств:
| Метрика | Метки | Смысл |
|---|---|---|
sds_node_configurator_file_device_size_bytes |
node, lvg_name, volume_group, file_device |
размер PV, созданного на одном файле-подложке |
sds_node_configurator_file_devices_directory_allocated_bytes |
node, directory |
сколько модуль суммарно занял в этом каталоге |
sds_node_configurator_file_devices_directory_free_bytes |
node, directory |
сколько осталось на файловой системе, где лежит каталог |
sds_node_configurator_file_devices_directory_total_bytes |
node, directory |
размер этой файловой системы |
На пару free/total стоит завести алерт. Файлы создаются с предварительным выделением места, поэтому модуль держит фиксированную долю файловой системы, которая ему не принадлежит (по умолчанию — корня узла). Агент оставляет fileDevicesMinFreeSpacePercent этой файловой системы вне собственной досягаемости, но ничто не мешает заполнить её чем-то другим позже, а её исчерпание приводит к вытеснению подов по DiskPressure на всём узле. Алертить стоит на падение free / total ниже резерва:
sds_node_configurator_file_devices_directory_free_bytes
/ sds_node_configurator_file_devices_directory_total_bytes < 0.15Если прочитать свободное место в этом цикле не удалось, публикуется предыдущее значение, а не ноль, — иначе разовая ошибка выглядела бы как заполненный диск.
Восстановление после перезагрузки
После перезагрузки узла агент автоматически восстанавливает привязку loop-устройств до активации групп томов. Путь к файлу-подложке хранится в status.nodes[].fileDevices[].filePath.
Удаление
При удалении LVMVolumeGroup с файловыми устройствами агент отключает loop-устройства и удаляет файлы-подложки.
Какие лейблы добавляются контроллером на ресурсы BlockDevices?
status.blockdevice.storage.deckhouse.io/type— тип LVM.status.blockdevice.storage.deckhouse.io/fstype— тип файловой системы.status.blockdevice.storage.deckhouse.io/pvuuid— UUID физического тома.status.blockdevice.storage.deckhouse.io/vguuid— UUID группы томов.status.blockdevice.storage.deckhouse.io/partuuid— UUID раздела.status.blockdevice.storage.deckhouse.io/lvmvolumegroupname— имя ресурса LVMVolumeGroup, к которому относится устройство.status.blockdevice.storage.deckhouse.io/actualvgnameonthenode— имя группы томов на узле.status.blockdevice.storage.deckhouse.io/wwn— идентификатор WWN (World Wide Name) для устройства.status.blockdevice.storage.deckhouse.io/serial— серийный номер устройства.status.blockdevice.storage.deckhouse.io/size— размер устройства.status.blockdevice.storage.deckhouse.io/model— модель устройства.status.blockdevice.storage.deckhouse.io/rota— указывает, является ли устройство ротационным.status.blockdevice.storage.deckhouse.io/hotplug— указывает возможность горячей замены устройства (HotPlug).status.blockdevice.storage.deckhouse.io/machineid— идентификатор сервера, на котором установлено блочное устройство.