Что нового

Proxmox VE: unused и orphan-диски в LVM/LVM-thin — причины и безопасная очистка

В этой статье я разберу реальный случай очистки старого сервера Proxmox VE, на котором за несколько лет накопились отключённые диски виртуальных машин, orphan volumes и оставшиеся в device-mapper представления разделов гостевых дисков.

1786718136540.png


После очистки заполнение LVM-thin pool снизилось с 94,00% до 68,17%, а проверка не обнаружила unused-дисков, orphan volumes и оставшихся device-mapper mappings.

В начале я увидел в local-lvm несколько подозрительных пар:

Код:
vm-102-disk-0
vm-102-disk-1

vm-124-disk-0
vm-124-disk-1

vm-136-disk-0
vm-136-disk-1

На первый взгляд это выглядело как дублирование виртуальных машин или их дисков.

В результате выяснилось, что проблема состояла сразу из нескольких частей:

  • старые диски, зарегистрированные в Proxmox как unused0;
  • настоящие orphan volumes — физические LVM-тома, которые уже не принадлежали ни одной существующей VM;
  • оставшиеся device-mapper mappings разделов вида vm-XXX-disk-0p1, p2, p3 и т. д.;
  • автоматически активированные на самом гипервизоре LVM-тома гостевых операционных систем;
  • почти заполненный LVM-thin pool.

В процессе очистки заполнение основного thin-pool удалось снизить с:

Код:
94.00%

до:

Код:
68.17%

То есть фактически я освободил около 430 GiB физического пространства.

Исходная конфигурация​


На момент работ сервер использовал достаточно старую версию Proxmox VE:

Код:
proxmox-ve: 7.1-1
pve-manager: 7.1-7
kernel: 5.13.19-2-pve
lvm2: 2.03.11

Основное хранилище:

Код:
lvmthin: local-lvm
thinpool data
vgname pve
content images,rootdir

Также присутствовали три отдельных обычных LVM storage:

Код:
lvm: local-lvm-3
vgname local-lvm-3
content rootdir,images
nodes pve
shared 0

lvm: local-lvm-4
vgname local-lvm-4
content images,rootdir
nodes pve
shared 0

lvm: local-lvm-5
vgname local-lvm-5
content rootdir,images
nodes pve
shared 0

Сервер к моменту диагностики не перезагружался почти два года:

Код:
uptime -s
uptime -p

Результат:

Код:
2024-08-18 16:54:02
up 1 year, 51 weeks, 4 days, 23 hours, 48 minutes

Позже эта деталь оказалась важной.

disk-0 и disk-1 не означают дубликаты​


Первое, что я проверил, — конфигурацию каждой подозрительной VM.

Например:

Код:
qm config 102

Я получил:

Код:
scsi0: local-lvm:vm-102-disk-1,size=32G
unused0: local-lvm:vm-102-disk-0

Это означает:

Код:
vm-102-disk-1 = текущий рабочий диск
vm-102-disk-0 = старый отключённый диск

То же самое было у VM 124:

Код:
scsi0: local-lvm:vm-124-disk-1,size=50G
unused0: local-lvm:vm-124-disk-0

И у VM 136:

Код:
scsi0: local-lvm:vm-136-disk-1,size=80G
unused0: local-lvm:vm-136-disk-0

Поэтому ориентироваться только на номер disk-0 или disk-1 нельзя.

Рабочий диск определяется конфигурацией VM — например, scsi0, virtio0 или sata0.

Для дополнительной проверки физических volumes я использовал:

Код:
pvesm list local-lvm --vmid 102

Например:

Код:
Volid                   Format  Type             Size VMID
local-lvm:vm-102-disk-0 raw     images    53687091200 102
local-lvm:vm-102-disk-1 raw     images    34359738368 102

Почему Proxmox не дал удалить диск из Storage​


При попытке удалить старый диск непосредственно из списка Storage → local-lvm → VM Disks я получил:

Код:
Cannot remove image, a guest with VMID '102' exists!
You can delete the image from the guest's hardware pane

Это нормальная защита Proxmox.

Если диск присутствует в конфигурации VM как:

Код:
unused0: local-lvm:vm-102-disk-0

его следует удалять через:

Код:
VM → Hardware → Unused Disk → Remove

Но в моём случае и это сначала не сработало.

Ошибка Logical volume is used by another device​


При удалении через Hardware я получил:

Код:
lvremove 'pve/vm-102-disk-0' error:
Logical volume pve/vm-102-disk-0 is used by another device.

На этом этапе я ничего не стал удалять принудительно.

Я не использовал:

Код:
lvremove -f
dmsetup remove -f
wipefs

Сначала я посмотрел состояние device-mapper:

Код:
dmsetup info -c -o name,major,minor,attr,open | grep -E 'Name|102'
dmsetup ls --tree

И обнаружил:

Код:
centos-root
└─pve-vm--102--disk--0p2
└─pve-vm--102--disk--0

centos-swap
└─pve-vm--102--disk--0p2
└─pve-vm--102--disk--0

То есть старый виртуальный диск был разобран на разделы прямо на хосте:

Код:
pve-vm--102--disk--0p1
pve-vm--102--disk--0p2

А находившийся внутри гостевой CentOS LVM был активирован уже LVM самого Proxmox-хоста.

Как я безопасно освободил старый диск VM 102​


Сначала я проверил, что гостевые LVM-тома нигде не смонтированы:

Код:
findmnt -S /dev/mapper/centos-root
findmnt -S /dev/mapper/centos-swap
swapon --show

Затем проверил open count:

Код:
dmsetup info -c -o name,open | grep -E 'centos|102'

После того как убедился, что:

Код:
centos-root  Open 0
centos-swap  Open 0

я деактивировал только гостевые LV:

Код:
lvchange -an centos/root
lvchange -an centos/swap

После этого mappings разделов имели:

Код:
pve-vm--102--disk--0p1  0
pve-vm--102--disk--0p2  0

Утилиты kpartx на сервере не оказалось, поэтому mappings я снял напрямую:

Код:
dmsetup remove pve-vm--102--disk--0p1
dmsetup remove pve-vm--102--disk--0p2

Проверка:

Код:
dmsetup info -c -o name,open | grep 102

После этого старый диск имел:

Код:
pve-vm--102--disk--0    0

и нормально удалился через:

Код:
VM 102 → Hardware → Unused Disk 0 → Remove

После удаления я проверил:

Код:
qm config 102
pvesm list local-lvm --vmid 102

В результате остался только рабочий диск:

Код:
scsi0: local-lvm:vm-102-disk-1,size=32G

Аналогичный случай с Ubuntu на VM 124​


У VM 124 было:

Код:
scsi0: local-lvm:vm-124-disk-1,size=50G
unused0: local-lvm:vm-124-disk-0

Но внутри старого диска на хосте оказался активирован гостевой LVM:

Код:
ubuntu-vg/ubuntu-lv

Диагностика:

Код:
dmsetup info -c -o name,open | grep -E 'ubuntu|124'
lvs -o vg_name,lv_name,lv_attr,lv_size,devices | grep -E 'ubuntu|124'

Я увидел:

Код:
ubuntu-vg   ubuntu-lv   24.50g   /dev/mapper/pve-vm--124--disk--0p3

Проверив отсутствие mount:

Код:
findmnt | grep -E 'ubuntu--vg|vm--124'

и убедившись, что этот LV не используется, я деактивировал его:

Код:
lvchange -an ubuntu-vg/ubuntu-lv

После этого снял mappings:

Код:
dmsetup remove pve-vm--124--disk--0p1
dmsetup remove pve-vm--124--disk--0p2
dmsetup remove pve-vm--124--disk--0p3

Проверил:

Код:
dmsetup info -c -o name,open | grep 124

И затем удалил Unused Disk 0 через Hardware VM 124.

VM 136 — только partition mappings​


У VM 136 гостевого LVM поверх старого диска уже не было:

Код:
pve-vm--136--disk--0      3
pve-vm--136--disk--0p1    0
pve-vm--136--disk--0p2    0
pve-vm--136--disk--0p3    0

Поэтому достаточно было снять три mappings:

Код:
dmsetup remove pve-vm--136--disk--0p1
dmsetup remove pve-vm--136--disk--0p2
dmsetup remove pve-vm--136--disk--0p3

Проверить:

Код:
dmsetup info -c -o name,open | grep 136

После этого старый диск имел Open 0 и нормально удалился через:

Код:
VM 136 → Hardware → Unused Disk 0 → Remove

Один только этот диск освободил около 80 GiB физического пространства.

Поиск всех unused-дисков​


После ручной очистки нескольких VM я проверил весь сервер:

Код:
for id in $(qm list | awk 'NR>1 {print $1}'); do
unused=$(qm config "$id" | grep '^unused')
if [ -n "$unused" ]; then
echo "=== VM $id ==="
echo "$unused"
fi
done

После удаления известных старых дисков вывод стал пустым.

Это означает, что зарегистрированных unused0, unused1 и т. д. больше не осталось.

Поиск настоящих orphan volumes​


Отсутствие unused ещё не означает, что storage полностью чист.

Я отдельно сравнил все физически существующие volumes в local-lvm с volumes, упоминающимися в конфигурациях VM и контейнеров.

Список физических томов:

Код:
pvesm list local-lvm | awk 'NR>1 {print $1}' | grep '^local-lvm:vm-' | sort -u > /tmp/local-lvm-all.txt

Список томов из конфигураций QEMU VM и LXC:

Код:
grep -rhoE 'local-lvm:vm-[0-9]+-disk-[0-9]+' /etc/pve/qemu-server/*.conf /etc/pve/lxc/*.conf 2>/dev/null | sort -u > /tmp/local-lvm-used.txt

Сравнение:

Код:
comm -23 /tmp/local-lvm-all.txt /tmp/local-lvm-used.txt

Я получил:

Код:
local-lvm:vm-108-disk-0
local-lvm:vm-115-disk-0
local-lvm:vm-132-disk-0
local-lvm:vm-134-disk-0
local-lvm:vm-138-disk-0
local-lvm:vm-139-disk-0

Это уже выглядело как настоящие orphan volumes.

Дополнительная проверка orphan volumes​


Перед удалением я проверил каждый VMID по всем конфигурациям:

Код:
for id in 108 115 132 134 138 139; do
echo "===== VM $id ====="
grep -R "local-lvm:vm-$id-disk-0" /etc/pve/nodes/*/qemu-server /etc/pve/nodes/*/lxc 2>/dev/null || echo "NO CONFIG REFERENCE"
done

Для всех получил:

Код:
NO CONFIG REFERENCE

Далее, например:

Код:
qm config 108

возвращал:

Код:
Configuration file 'nodes/pve/qemu-server/108.conf' does not exist

То же самое было для остальных найденных VMID.

При этом:

Код:
pvesm list local-lvm --vmid 108

показывал реально существующий:

Код:
local-lvm:vm-108-disk-0

То есть сама VM уже отсутствовала, но её старый LVM volume продолжал существовать и занимать место.

Основными проверками для orphan volume я считал следующие:

  • volume физически существует;
  • ссылки на него в конфигурациях VM и LXC отсутствуют;
  • VM с соответствующим VMID не существует.

Дополнительная проверка через qm rescan​


Моя версия Proxmox поддерживала:

Код:
qm rescan --dryrun 1

Вывод:

Код:
NOTE: running in dry-run mode, won't write changes out!
rescan volumes...

Больше команда ничего не показала.

Это стало дополнительной проверкой того, что Proxmox не собирался восстанавливать какие-либо найденные volumes как unused существующих VM.

При этом сам по себе пустой qm rescan я не считал достаточным доказательством orphan volume.

Основными оставались проверки конфигураций и существования VMID.

Удаление orphan volume​


Для orphan volume уже нельзя использовать Hardware конкретной VM, потому что самой VM больше нет.

После снятия всех device-mapper зависимостей я удалял такие volumes штатной командой Proxmox:

Код:
pvesm free local-lvm:vm-XXX-disk-0

Например:

Код:
pvesm free local-lvm:vm-108-disk-0

Результат:

Код:
Logical volume "vm-108-disk-0" successfully removed
Removed volume 'local-lvm:vm-108-disk-0'

Важно: pvesm free окончательно удаляет содержимое volume. Я использовал эту команду только после полной проверки конкретного диска.

VM 108 и гостевой cl-root/cl-swap​


У orphan-диска VM 108 обнаружилась ещё одна интересная ситуация:

Код:
cl-root
└─pve-vm--108--disk--0p2

cl-swap
└─pve-vm--108--disk--0p2

Сначала я проверил, какой swap реально используется самим Proxmox:

Код:
dmsetup info -c -o name,major,minor | grep -E 'pve-swap|cl-swap'
swapon --show

Получил:

Код:
cl-swap                          253  66
pve-swap                         253   1

NAME      TYPE      SIZE USED PRIO
/dev/dm-1 partition   8G   4G   -2

То есть хост использовал pve-swap с major/minor 253:1, а не гостевой cl-swap с 253:66.

После этого я деактивировал гостевые LV:

Код:
lvchange -an cl/root
lvchange -an cl/swap

Затем снял mappings:

Код:
dmsetup remove pve-vm--108--disk--0p1
dmsetup remove pve-vm--108--disk--0p2

Проверил:

Код:
dmsetup info -c -o name,open | grep 108

После того как родительский volume получил Open 0, я удалил orphan:

Код:
pvesm free local-lvm:vm-108-disk-0

Сколько места занимали найденные orphan volumes​


До очистки у найденных orphan volumes были следующие значения:

Код:
vm-108-disk-0   70G × 42.80%  ≈ 30 GiB
vm-115-disk-0   32G × 82.99%  ≈ 27 GiB
vm-132-disk-0   50G × 67.84%  ≈ 34 GiB
vm-134-disk-0   80G × 90.72%  ≈ 73 GiB
vm-138-disk-0   80G × 90.50%  ≈ 72 GiB
vm-139-disk-0   80G × 100.00% ≈ 80 GiB

Только эти orphan volumes занимали примерно 316 GiB реально выделенного пространства.

Почему LSize не равен реально освобождённому месту в LVM-thin​


Основное хранилище у меня было LVM-thin.

Например:

Код:
vm-102-disk-0
LSize: 50G
Data%: 28.80

Удаление такого диска освобождает не обязательно все 50 GiB, потому что реально в thin-pool могли быть выделены только использованные блоки.

Приблизительная оценка:

Код:
50 × 0.288 ≈ 14.4 GiB

Для оценки я использовал:

Код:
lvs -o lv_name,lv_size,data_percent pve

Именно поэтому при работе с LVM-thin важен не только LSize, но и Data%.

Очистка оставшихся partition mappings рабочих VM​


После удаления старых дисков выяснилось, что на хосте всё ещё находятся десятки mappings:

Код:
pve-vm--100--disk--0p1
pve-vm--100--disk--0p2
pve-vm--100--disk--0p3

При этом они имели:

Код:
Open 0

Это не дополнительные копии дисков и не отдельные данные VM.

Это только device-mapper mappings разделов внутри существующих виртуальных дисков.

Сначала я сформировал список только тех mappings, которые имели Open 0:

Код:
dmsetup info -c --noheadings --separator ':' -o name,open | awk -F: '$2 == 0 && $1 ~ /^pve-vm--[0-9]+--disk--[0-9]+p[0-9]+$/ {print $1}' > /root/pve-partmaps-to-remove.txt

Здесь перенаправление в файл я специально оставил в той же строке, чтобы визуальный редактор XenForo не попытался интерпретировать строку, начинающуюся с символа >, как цитату.

Затем проверил сформированный список:

Код:
wc -l /root/pve-partmaps-to-remove.txt
cat /root/pve-partmaps-to-remove.txt

Изначально у меня было 31 такое устройство.

Для удаления я использовал:

Код:
udevadm settle

while IFS= read -r map; do
echo "Removing $map"
dmsetup remove --retry "$map" || {
echo "FAILED: $map"
break
}
done < /root/pve-partmaps-to-remove.txt

Я принципиально не использовал --force.

Device or resource busy при Open 0​


На одном из разделов VM 100 я получил:

Код:
device-mapper: remove ioctl on pve-vm--100--disk--0p3 failed: Device or resource busy
Command failed.

Хотя ранее mapping имел Open 0.

Я проверил его отдельно:

Код:
dmsetup info -c -o name,major,minor,open | grep -E 'vm--100--disk--0|pve-swap'

Затем дерево зависимостей:

Код:
dmsetup ls --tree | grep -A12 -B5 'pve-vm--100--disk--0p3'

Mount и открытые процессы:

Код:
findmnt -S /dev/mapper/pve-vm--100--disk--0p3
fuser -vm /dev/mapper/pve-vm--100--disk--0p3

Проверил, не является ли раздел LVM PV:

Код:
pvs -o pv_name,vg_name,pv_attr,pv_size,pv_free | grep 'pve-vm--100--disk--0p3'

И наличие LVM-томов поверх него:

Код:
lvs -a -o vg_name,lv_name,lv_attr,lv_size,devices | grep -E 'pve-vm--100--disk--0p3|vm-100'

Никаких зависимостей обнаружено не было.

После этого я выполнил:

Код:
udevadm settle
dmsetup remove --retry pve-vm--100--disk--0p3
dmsetup remove --retry pve-vm--100--disk--0p4
dmsetup remove --retry pve-vm--100--disk--0p5

Mappings удалились.

Родительский диск остался:

Код:
pve-vm--100--disk--0    1

Проверка:

Код:
qm status 100

показала:

Код:
status: running

То есть Open 1 был нормальным открытием диска работающей виртуальной машиной.

Массовая очистка остальных свободных mappings​


После VM 100 я пересоздал список:

Код:
dmsetup info -c --noheadings --separator ':' -o name,open | awk -F: '$2 == 0 && $1 ~ /^pve-vm--[0-9]+--disk--[0-9]+p[0-9]+$/ {print $1}' > /root/pve-partmaps-to-remove.txt

Проверил:

Код:
wc -l /root/pve-partmaps-to-remove.txt
cat /root/pve-partmaps-to-remove.txt

После чего снова выполнил:

Код:
udevadm settle

while IFS= read -r map; do
echo "Removing $map"
dmsetup remove --retry "$map" || {
echo "FAILED: $map"
break
}
done < /root/pve-partmaps-to-remove.txt

На одном из mappings VM 122 появилась кратковременная ошибка:

Код:
device-mapper: remove ioctl on pve-vm--122--disk--0p1 failed: Device or resource busy

Но благодаря --retry удаление в итоге прошло, и итоговая проверка стала пустой:

Код:
dmsetup info -c -o name,open | grep -E 'pve-vm--.*disk--.*p[0-9]+'

Финальная проверка основного local-lvm​


После очистки команда:

Код:
dmsetup info -c -o name,open | grep -E 'pve-vm--.*disk--.*p[0-9]+'

не выводила ничего.

При этом сами рабочие виртуальные диски оставались:

Код:
dmsetup info -c -o name,open | grep '^pve-vm'

Например:

Код:
pve-vm--100--disk--0    1
pve-vm--101--disk--0    1
pve-vm--102--disk--1    0
pve-vm--103--disk--0    1

Для работающих VM значение Open 1 является ожидаемым.

Затем я заново сформировал списки всех volumes и всех volumes из конфигураций:

Код:
pvesm list local-lvm | awk 'NR>1 {print $1}' | grep '^local-lvm:vm-' | sort -u > /tmp/local-lvm-all.txt

Код:
grep -rhoE 'local-lvm:vm-[0-9]+-disk-[0-9]+' /etc/pve/qemu-server/*.conf /etc/pve/lxc/*.conf 2>/dev/null | sort -u > /tmp/local-lvm-used.txt

Сравнение:

Код:
comm -23 /tmp/local-lvm-all.txt /tmp/local-lvm-used.txt

Вывод был пустым.

Также:

Код:
qm rescan --dryrun 1

показал только:

Код:
NOTE: running in dry-run mode, won't write changes out!
rescan volumes...

После этого основной local-lvm я считал полностью очищенным.

Отдельные storage local-lvm-3, local-lvm-4 и local-lvm-5​


На сервере также находились три обычных LVM storage:

Код:
local-lvm-3    99.23%
local-lvm-4    99.81%
local-lvm-5    99.90%

Сначала такие значения выглядели пугающе.

Но это обычный LVM, а не LVM-thin.

Практически весь объём VG был заранее выделен под большие виртуальные диски:

Код:
VM 123:
scsi0: local-lvm-3:vm-123-disk-0,size=5546G

VM 137:
scsi0: local-lvm-4:vm-137-disk-0,size=13014G

VM 140:
scsi0: local-lvm-5:vm-140-disk-0,size=20470G

Поэтому 99.x% у такого storage не означает, что файловая система внутри гостевой VM заполнена на 99%.

Проверка:

Код:
pvesm list local-lvm-3
pvesm list local-lvm-4
pvesm list local-lvm-5

показала ровно по одному ожидаемому диску:

Код:
local-lvm-3:vm-123-disk-0
local-lvm-4:vm-137-disk-0
local-lvm-5:vm-140-disk-0

Orphan volumes там не было.

Очистка mappings на других LVM storage​


У VM 123 и VM 137 присутствовали:

Код:
local--lvm--3-vm--123--disk--0p1
local--lvm--3-vm--123--disk--0p2
local--lvm--3-vm--123--disk--0p3
local--lvm--3-vm--123--disk--0p4

local--lvm--4-vm--137--disk--0p1
local--lvm--4-vm--137--disk--0p2
local--lvm--4-vm--137--disk--0p3
local--lvm--4-vm--137--disk--0p4

А у VM 140 уже было нормальное состояние без mappings разделов:

Код:
local--lvm--5-vm--140--disk--0    1

Сначала я проверил дерево:

Код:
dmsetup ls --tree | grep -E -A8 -B3 'local--lvm--(3-vm--123|4-vm--137)--disk--0p'

Никаких дополнительных LVM или других device-mapper устройств поверх этих разделов не было.

После этого я снял mappings:

Код:
udevadm settle

dmsetup remove --retry local--lvm--3-vm--123--disk--0p1
dmsetup remove --retry local--lvm--3-vm--123--disk--0p2
dmsetup remove --retry local--lvm--3-vm--123--disk--0p3
dmsetup remove --retry local--lvm--3-vm--123--disk--0p4

dmsetup remove --retry local--lvm--4-vm--137--disk--0p1
dmsetup remove --retry local--lvm--4-vm--137--disk--0p2
dmsetup remove --retry local--lvm--4-vm--137--disk--0p3
dmsetup remove --retry local--lvm--4-vm--137--disk--0p4

Финальное состояние:

Код:
local--lvm--3-vm--123--disk--0    1
local--lvm--4-vm--137--disk--0    1
local--lvm--5-vm--140--disk--0    1

Все три VM были запущены, поэтому Open 1 здесь является нормальным состоянием.

Финальная проверка всех partition mappings:

Код:
dmsetup info -c --noheadings --separator ':' -o name,open | grep -E 'disk--[0-9]+p[0-9]+'

ничего не вывела.

Откуда взялись гостевые LVM на самом Proxmox​


Здесь удалось установить вторую половину механизма.

В моей конфигурации /etc/lvm/lvm.conf присутствовал:

Код:
global_filter=["r|/dev/zd.*|"]

То есть этот filter отсеивал /dev/zd*, но не исключал device-mapper устройства вида:

Код:
/dev/mapper/pve-vm--108--disk--0p2

При этом на сервере работала стандартная event-based activation LVM.

Проверка:

Код:
systemctl status 'lvm2-pvscan@*' --no-pager

показала сервисы вида:

Код:
lvm2-pvscan@8:19.service
lvm2-pvscan@8:0.service
lvm2-pvscan@8:48.service
lvm2-pvscan@8:32.service

Их команда запуска:

Код:
ExecStart=/sbin/lvm pvscan --cache --activate ay %i

Кроме того, в udev присутствовало:

Код:
ENV{SYSTEMD_WANTS}+="lvm2-pvscan@$major:$minor.service"

То есть если в системе появлялся block device с LVM PV гостевой системы, дальше могла происходить следующая цепочка:

Код:
partition mapping
↓
udev
↓
lvm2-pvscan@
↓
pvscan --cache --activate ay
↓
активация гостевого VG/LV

Именно так на Proxmox-хосте могли оказаться активированными:

Код:
centos-root
centos-swap

cl-root
cl-swap

ubuntu-vg/ubuntu-lv

Кто первоначально создал p1, p2, p3 и другие mappings​


Однозначно установить источник этих partition mappings мне не удалось.

Формат:

Код:
vm--XXX--disk--0p1
vm--XXX--disk--0p2
vm--XXX--disk--0p3

характерен для device-mapper представлений разделов, которые могут создавать kpartx и похожие инструменты.

Однако на момент диагностики:

Код:
dpkg -l | grep -Ei 'kpartx|multipath|libguestfs'

ничего не показывал.

Также я не нашёл следов следующих инструментов:

Код:
kpartx
partx
qemu-nbd
guestmount
guestfish

в bash history, локальных скриптах и текущей конфигурации.

Проверка истории пакетов:

Код:
zgrep -hiE 'kpartx|multipath-tools|libguestfs' /var/log/apt/history.log* /var/log/dpkg.log* 2>/dev/null

тоже ничего не показала.

Поиск в конфигурациях и локальных скриптах:

Код:
grep -RniE '\b(kpartx|partx|dmsetup[[:space:]]+create|qemu-nbd|guestmount|guestfish)\b' /etc /usr/local /root 2>/dev/null

также был пустым.

Поэтому утверждать, что причиной был именно kpartx, я не могу.

Почему я считаю mappings историческими leftovers​


Сервер работал непрерывно с:

Код:
2024-08-18 16:54:02

то есть почти два года.

После ручной очистки команда:

Код:
dmsetup info -c --noheadings -o name,open | grep -E 'disk--[0-9]+p[0-9]+'

оставалась пустой.

Mappings не возникли повторно.

Это хорошо укладывается в сценарий:

Код:
когда-то был запущен инструмент
↓
были созданы p1, p2, p3 и другие mappings
↓
LVM хоста увидел гостевые LVM PV
↓
автоматически активировались гостевые VG/LV
↓
инструмент перестал использоваться или был удалён
↓
mappings продолжили жить в device-mapper
↓
из-за почти двухлетнего uptime они оставались в системе до момента очистки

Полностью подтвердить эту версию можно будет после следующей плановой перезагрузки.

Почему я не стал менять lvm.conf​


Можно было бы пытаться ограничить LVM autoactivation через filters или auto_activation_volume_list.

Но сервер использовал:

Код:
Proxmox VE 7.1
LVM 2.03.11

Команда:

Код:
lvmconfig --type full activation/auto_activation_volume_list

ничего не вывела.

Команда:

Код:
lvmconfig --type current | grep -A10 -B3 auto_activation

также была пустой.

При этом неправильный global_filter или неправильная activation policy на гипервизоре потенциально могут создать гораздо более серьёзные проблемы, чем уже удалённые stale mappings.

Поэтому после очистки я решил не менять:

Код:
/etc/lvm/lvm.conf

и оставить существующую LVM-конфигурацию без изменений.

Состояние LVM после очистки​


После всех операций я проверил:

Код:
lvs -a -o vg_name,lv_name,lv_attr,lv_active,lv_device_open

Рабочие VM-диски выглядели примерно так:

Код:
VG          LV              Attr       Active DevOpen
local-lvm-3 vm-123-disk-0   -wi-ao---- active       open
local-lvm-4 vm-137-disk-0   -wi-ao---- active       open
local-lvm-5 vm-140-disk-0   -wi-ao---- active       open
pve         vm-100-disk-0   Vwi-aotz-- active       open
pve         vm-101-disk-0   Vwi-aotz-- active       open
pve         vm-102-disk-1   Vwi-a-tz-- active
pve         vm-124-disk-1   Vwi-a-tz-- active
pve         vm-136-disk-1   Vwi-aotz-- active       open

Для работающей VM состояние active/open является ожидаемым.

Для выключенной VM LV может оставаться активным, но не иметь DevOpen.

Само по себе это не означает orphan volume.

Что получилось в итоге​


До начала очистки:

Код:
pve/data Data%: 94.00%

После очистки:

Код:
pve/data Data%: 68.17%

Были удалены старые volumes:

Код:
vm-102-disk-0
vm-124-disk-0
vm-136-disk-0

vm-108-disk-0
vm-115-disk-0
vm-132-disk-0
vm-134-disk-0
vm-138-disk-0
vm-139-disk-0

Первые три были unused disks существующих VM.

Остальные шесть были подтверждёнными orphan volumes.

Для этих orphan volumes одновременно выполнялись условия:

  • не существовало соответствующей конфигурации VM;
  • не было ссылок на volume из конфигураций qemu-server или LXC;
  • сам LVM volume физически продолжал существовать.

В результате было освобождено примерно:

Код:
430 GiB

реального пространства основного thin-pool.

Мой алгоритм безопасной очистки​


Если я снова столкнусь с подобной ситуацией, буду действовать именно в таком порядке.

1. Проверить конфигурацию VM​


Код:
qm config VMID
pvesm list STORAGE --vmid VMID

Нужно определить:

Код:
scsi0 / virtio0 / sata0 = рабочий диск
unused0                  = отключённый диск

2. Не считать disk-0 автоматически старым​


Имена:

Код:
disk-0
disk-1
disk-2

являются только именами volumes.

Рабочим вполне может быть disk-1, а старым — disk-0.

3. Если unused не удаляется — проверить device-mapper​


Код:
dmsetup info -c -o name,open | grep VMID
dmsetup ls --tree

4. Проверить mount и swap​


Код:
findmnt
swapon --show
fuser -vm DEVICE

5. Если поверх старого диска активирован гостевой LVM​


Сначала я убеждаюсь, что гостевой LV нигде не используется.

После этого деактивирую именно гостевой LV:

Код:
lvchange -an VG/LV

6. Удалять только свободные partition mappings​


Проверяю Open:

Код:
dmsetup info -c -o name,open

И снимаю только mappings с Open 0:

Код:
dmsetup remove --retry MAPPING

Без --force.

7. Для unused существующей VM​


Удаляю через:

Код:
VM → Hardware → Unused Disk → Remove

8. Для подтверждённого orphan volume​


После всех проверок:

Код:
pvesm free STORAGE:vm-XXX-disk-N

Эта команда окончательно удаляет данные указанного volume.

9. Найти все orphan volumes​


Для основного local-lvm:

Код:
pvesm list local-lvm | awk 'NR>1 {print $1}' | grep '^local-lvm:vm-' | sort -u > /tmp/local-lvm-all.txt

Код:
grep -rhoE 'local-lvm:vm-[0-9]+-disk-[0-9]+' /etc/pve/qemu-server/*.conf /etc/pve/lxc/*.conf 2>/dev/null | sort -u > /tmp/local-lvm-used.txt

Сравнение:

Код:
comm -23 /tmp/local-lvm-all.txt /tmp/local-lvm-used.txt

В нормальном состоянии вывод должен быть пустым.

10. Проверить Proxmox rescan​


На моей версии:

Код:
qm rescan --dryrun 1

11. Проверить остаточные partition mappings​


Код:
dmsetup info -c --noheadings --separator ':' -o name,open | grep -E 'disk--[0-9]+p[0-9]+'

После моей очистки вывод был пустым.

12. Проверить заполнение thin-pool​


Код:
lvs -o lv_name,lv_size,data_percent pve

И общий статус storage:

Код:
pvesm status

Что проверить после следующей перезагрузки​


Поскольку я предполагаю, что mappings являлись историческими остатками почти двухлетнего uptime, окончательная проверка будет после следующей плановой перезагрузки.

Перед reboot можно сохранить текущее состояние:

Код:
dmsetup info -c --noheadings -o name,open > /root/dmsetup-before-reboot.txt

После reboot:

Код:
dmsetup info -c --noheadings -o name,open | grep -E 'disk--[0-9]+p[0-9]+'

Если вывод останется пустым, это будет сильным подтверждением того, что проблема действительно была связана со старыми накопившимися mappings.

Также я проверю:

Код:
pvs
vgs
lvs -a -o vg_name,lv_name,lv_attr,lv_active,lv_device_open

На хосте не должны самопроизвольно появиться гостевые VG и LV вроде:

Код:
centos
cl
ubuntu-vg

Вывод​


Главный вывод, который я сделал после этой чистки: наличие нескольких volumes вида vm-XXX-disk-N ещё не означает дублирование виртуальной машины.

Сначала нужно определить, какой volume действительно подключён к VM, какой зарегистрирован как unused, а какой вообще больше не связан ни с одной существующей конфигурацией.

Особенно осторожно нужно работать с LVM и LVM-thin, потому что поверх виртуального диска могут оставаться device-mapper mappings его разделов, а LVM хоста способен увидеть LVM PV гостевой операционной системы и автоматически активировать находящиеся внутри VG/LV.

Поэтому мой порядок действий теперь такой:

конфигурация VM → проверка storage → device-mapper → mount/swap → гостевой LVM → снятие mappings → удаление volume.

Я не использую массовые lvremove -f и dmsetup remove -f, пока точно не установлено, что именно держит конкретный диск.

В моём случае такой подход позволил без потери рабочих данных убрать старые unused и orphan-диски, очистить накопившиеся device-mapper mappings и снизить заполнение основного LVM-thin pool с 94.00% до 68.17%.
Об авторе
Guru
Василий, cистемный админ /gnu/linux/windows/macos/mikrotik/troubleshooter, создатель сайта
Интересуюсь всем что делает инфраструктуру быстрой и надёжной
Открыт к общению и проектам, написать мне можно через форму или в личном сообщении

❗ Если есть пожелания по обзору какого-либо вопроса не представленного на сайте - пиши в комментариях

Комментарии

Нет комментариев для отображения.

Информация о статье

Автор
Guru
Время чтения статьи
17 мин чтения
Просмотры
17
Посл. обновление

Ещё от Guru

Поделиться этой статьёй

Назад
Верх