Страницы

Сохранить статью у себя в соцсети:

пятница, 7 сентября 2012 г.

§ Long and interesting way to add LVM storage to Proxmox VE.

Организация LVM хранилища в Proxmox VE.

Эта статья описывает длинный и извращенный способ реализации хранения образов дисков в отдельном LVM в Proxmox VE в рамках одного физического диска. Способ интересен не результатом, а самим процессом. Рекомендую провернуть это на выходных.
Более легий и безопасный способ описан здесь.
Disclaimer: Материал описанный в статье носит чисто академический характер, и вся операция делается из чисто спортивного интереса. В ходе выполнения задачи есть риск порчи или потери данных. Все это не рекомендуется делать на критически важных серверах. Бэкапы никто не отменял.
Наипростейшим способом реализации возможности запуска виртуальных машины с образами хранящимися в LVM, является вариант добавления еще одного физического диска в систему и создания на нем группы томов. 
Но это слишком просто и очевидно. Допустим что операционной системе доступен только один диск и возможностей для добавления нет. Взять пример, когда создан RAID-массив на аппаратном контроллере, и нет возможности добавить дисков в сервер, и RAID массив то переразбить нет возможности (данные то потеряются). А еще сервер далеко и есть только ssh... И нельзя перезагружаться =).
Так вот ниже описывается способ как без перезагрузки создать LVM хранилище для томов в Proxmox VE, в случае когда имеется всего один диск и доступ только по ssh. Своеобразный just for fun!
Суть задачи сводится к следующему:
  • существующая группа на имеющемся диске уменьшается;
  • из освободившегося места создается новый раздел;
  • на новом разделе создается новая группа.
Единственная сложность которая встретятся на пути это то, что после переразбивки системного диска (где размещен корень системы) не будет возможности перечитать таблицу разделов. Это архитектурные ограничения самого Linux.
Поэтому будем переносить корневую систему в оперативную память, потом из этой временной корневой фс, отключим наш диск и перечитаем таблицу разделов. Потом вернемся в нашу физическую корневую систему и создадим хранилище. Однако тут есть существенный минус, запущенные виртуальные машины, если таковые имеются - придется остановить. увы.
Более детально алгоритм выглядит так:
  • уменьшаем файловую систему в томе который будем урезать (resize2fs);
  • урезаем существующий LVM-том pve/data (lvreduce);
  • урезаем физический PV раздел /dev/sda2 (pvresize);
  • из освободившегося места создаем еще один раздел (parted);
  • теперь нужно перечитать таблицу разделов , чтобы ядро узнало об изменениях
  • останавливаем сервисы (service);
  • завершаем оставшиеся процессы (kill);
  • перемонтируем корневой раздел в read-only (mount);
  • переносим корень в оперативную память (pivot_root);
  • останавливаем lvm (vgchange);
  • делаем partprobe;
  • pivot'ируемся назад;
  • запускаем сервисы;
  • создаем LVM сторадж и вирт.машину.
Вначале имеем следующую картину. Есть относительной большой раздел в рамках существующей группы. Увы эту группу нельзя назначить в качестве хранения образов виртуальных машин (Хотя я конечно уверен что это можно сделать через правку системных скриптов Proxmox) - да это способ я нашел после написания этой статьи и выложил немного раньше.). Вот им то мы и будем жертвовать, его ресурс пойдет на создание нового раздела под LVM группу.
# df -h /var/lib/vz
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/pve-data  152G   36G  117G  24% /var/lib/vz

Уменьшение раздела на лету на данный момент не поддерживается, поэтому придется отмонтировать том. Если же там размещаются образа виртуальных машин, то их (машины) нужно остановить. На данный момент используется 36GB пространства, уменьшим раздел до 40GB. Предварительно нужно выполнить проверку тома.
# umount /var/lib/vz
# e2fsck -f /dev/pve/data
e2fsck 1.41.12 (17-May-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/pve/data: ***** FILE SYSTEM WAS MODIFIED *****
/dev/pve/data: 31/10125312 files (0.0% non-contiguous), 9906950/40471552 blocks
# resize2fs -F -p /dev/pve/data 40G
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/pve/data to 10485760 (4k) blocks.
Begin pass 2 (max = 7770368)
Relocating blocks             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 1236)
Scanning inode table          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 17)
Updating inode references     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/pve/data is now 10485760 blocks long.

После уменьшения размеров файловой системы, выполняем уменьшение тома (в lvreduce также есть встроенная функция уменьшения фс, но эта функция вобщем то использует все тот же resize2fs)
# lvreduce -r -L40G /dev/pve/data 
fsck from util-linux-ng 2.17.2
/dev/mapper/pve-data: clean, 31/2621440 files, 9433051/10485760 blocks
resize2fs 1.41.12 (17-May-2010)
The filesystem is already 10485760 blocks long.  Nothing to do!
  Reducing logical volume data to 40.00 GiB
  Logical volume data successfully resized

Итак, как видно, у нас есть 130GB свободного пространства, которое можно использовать под новый раздел
# pvs
  PV         VG   Fmt  Attr PSize   PFree  
  /dev/sda2  pve  lvm2 a--  232.38g 130.38g

Уменьшаем PV том и в качестве значения для нового размера берем сумму размеров всех томов в группе, плюс небольшой запас.
# pvresize --setphysicalvolumesize 110G /dev/sda2
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized

Смотрим полученный результат. От 130GB осталось всего 8GB.
# pvs
  PV         VG   Fmt  Attr PSize   PFree
  /dev/sda2  pve  lvm2 a--  110.00g 8.00g

Приступаем к переразметке физического диска. Для создания придется "удалить" имеющийся раздел, пересоздать его с новыми границами и затем создать новый раздел (вот они риски потери данных). Дело в том что команда resize не всегда корректно делает свою работу, а в более новых версиях parted её вообще убрали. 
(parted) unit MB
(parted) print                                                            
Model: ATA WDC WD2500AAKS-0 (scsi)
Disk /dev/sda: 250059MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End       Size      Type     File system  Flags
 1      1.05MB  537MB     536MB     primary  ext3         boot
 2      537MB   250059MB  249522MB  primary               lvm
(parted) rm 2
Error: Partition(s) 2 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before
making further changes.
Ignore/Cancel? I
(parted) mkpart primary 537 111000
Error: Partition(s) 2 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before
making further changes.
(parted) mkpart primary 111001 250059
(parted) quit

Теперь нужно перечитать таблицу разделов. Все бы хорошо, если бы не то, что корневой раздел находится на этом же диске. Поэтому при попытке перечитать таблицу будет вывалена ошибка.
# partprobe 
Error: Partition(s) 2 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.

Для вступления изменений в силу, проще и быстрее перезагрузиться, но так неинтересно. Здесь начинается авантюра. Сделаем все без перезагрузки.
Для того чтобы сделать это без перезагрузки, нужно остановить все LVM-тома. 
Итак сначала останавливаем все сервисы, это необходимо чтобы не один процесс не использовал корневую фс. Сначала прибегаем к штатным средствам, а то что запущено не как сервис - завершаем вручную.
# for i in rsyslog udev ksmtuned atd vzeventd vz ntp ssh rrdcached postfix cron pvedaemon apache2 pvestatd nfs-common portmap; do service $i stop; done
# kill -9 1145 1146 1228 1239 1397 

В результате таблица процессов должна выглядеть следующим образом (потоки ядра тут значения не имеют, оставшиеся getty и ssh+bash будут завершены позже). 

Теперь отмонтируем все точки куда смонтированы LVM тома (кроме корневого), остался лишь swap.
# swapoff -a

Далее необходимо создать образ в оперативной памяти который станет нашим временным корневым разделом. Размер раздела указывае чуть больше чем объем используемого пространства в корневой фс. Затем переносим туда данные.
# mkdir /mnt/newroot
# mount -t tmpfs -o size=2g tmpfs /mnt/newroot
# rsync -avx / /mnt/newroot

Теперь все готово для перехода во временный корневой раздел. Важной командой является pivot_root, ее важно выполнить именно в том месте и в том виде, чтобы избежать блокировок связанных с текущим каталогом.
# cd /mnt/newroot
# mkdir mnt/oldroot
# pivot_root . mnt/oldroot

В результате корень системы стал отсчитываться относительно старого /mnt/newroot, а старый корень перенесся в текущий /mnt/oldroot. Следующим шагом будет перенос точек монтирования из старого корня в новый.
# mount -n --move /mnt/oldroot/proc /proc
# mount -n --move /mnt/oldroot/dev /dev
# mount -n --move /mnt/oldroot/sys /sys

Оставшиеся точки смотрим через /proc/mounts и переносим аналогичным образом. в моем случае это три каталога
# grep oldroot /proc/mounts
tmpfs /mnt/oldroot/lib/init/rw tmpfs rw,nosuid,relatime,mode=755 0 0
/dev/fuse /mnt/oldroot/etc/pve fuse rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other 0 0
tmpfs /mnt/oldroot tmpfs rw,relatime,size=2097152k 0 0
# mount -n --move /mnt/oldroot/lib/init/rw /lib/init/rw
# mount -n --move /mnt/oldroot/etc/pve /etc/pve

Остается выполнить проверку не используют ли старую корневую систему какие-либо процессы (lsof /mnt/oldroot). Это будет наш процесс sshd, bash, udevd и getty. Эти процессы нужно завершить. В случае sshd и bash нужно перезапустить эти сервисы и просто переподключиться по ssh. 
# service udev restart
# service ssh restart

Переподключаемся. Перед тем как выйти, убедитесь что новый инстанс ssh запущен. Иначе миссия будет провалена))).  getty можно завершить через killall. После завершения процессов выполняем отмонтирование старой корневой фс
# umount /mnt/oldroot

Если операция завершится ошибкой device is busy, значит какой то процесс продолжает удерживать фс. Следует повторить операцию с lsof, найти процесс и завершить его.
Когда же все точки перенесены и никакие процессы не используют старую корневую фс, можно продолжить с операцией отключения LVM и перечитыванием таблицы разделов.
После отмонтирования старой корневой фс, атрибуты lvm томов должны выглядеть следующим образом (должен отсутствовать флаг "o" свидетельствующий о том что том открыт).
# lvs
  LV   VG   Attr     LSize  Pool Origin Data%  Move Log Copy%  Convert
  data pve  -wi-a--- 40.00g                                           
  root pve  -wi-a--- 58.00g                                           
  swap pve  -wi-a---  4.00g

Отключаем тома в группе и выполняем перезагрузку таблицы в ядре. Ради этих двух команд и затеивалась вся авантюра. А ведь проще и быстрее, было выполнить перезагрузку ))
# vgchange -an pve
0 logical volume(s) in volume group "pve" now active
# partprobe
# vgchange -ay pve
3 logical volume(s) in volume group "pve" now active

Теперь возвращаем все на место, по тому же алгоритму:
  • монтируем реальный наш корневой том;
  • пивотируемся в него;
  • переносим точки монтирования;
  • перезапускаем ssh и переподключаемся;
  • завершаем процессы удерживающие временную корневую фс;
  • отмонтируем временную фс и удаляем ее;
# mount /dev/pve/root /mnt/newroot/
# cd /mnt/newroot/ 
# mkdir mnt/oldroot
# pivot_root . mnt/oldroot
# mount -n --move /mnt/oldroot/dev /dev
# mount -n --move /mnt/oldroot/proc /proc
# mount -n --move /mnt/oldroot/sys /sys
# grep oldroot /proc/mounts 
tmpfs /mnt/oldroot/lib/init/rw tmpfs rw,nosuid,relatime,mode=755 0 0
/dev/fuse /mnt/oldroot/etc/pve fuse rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other 0 0
tmpfs /mnt/oldroot tmpfs rw,relatime,size=2097152k 0 0
# mount -n --move /mnt/oldroot/lib/init/rw /lib/init/rw
# mount -n --move /mnt/oldroot/etc/pve /etc/pve
# killall getty
# service ssh restart
# service udev restart

Снова переподключаемся по ssh и перезапускаем init. Продолжаем с удалением временной корневой фс.
# telinit u
# lsof /mnt/oldroot/
lsof: WARNING: can't stat() fuse file system /etc/pve
      Output information may be incomplete.
COMMAND  PID USER  FD   TYPE DEVICE SIZE/OFF  NODE NAME
sshd    2850 root txt    REG   0,21   475896 21847 /mnt/oldroot/usr/sbin/sshd
sshd    2850 root mem    REG   0,21    51728 13180 /mnt/oldroot/lib/libnss_files-2.11.3.so

Временную корневую фс все еще удерживает ssh процесс, перед тем как завершить его, удостоверимся что это не наш текущий процесс (сравним pid'ы)
# echo $$
3753

Все нормально, pid'ы отличаются, завершаем процесс и смотрим lsof. Warning можно игнорировать.
# kill 2850
# lsof /mnt/oldroot/
lsof: WARNING: can't stat() fuse file system /etc/pve
      Output information may be incomplete.

Все хорошо. удаляем временную фс.
# umount /mnt/oldroot
# rm -rf /mnt/oldroot

Запускаем наши службы, список нужных служб я подкорректировал
# pmxcfs
# for i in rsyslog ksmtuned atd ntp rrdcached postfix cron pvedaemon apache2 pvestatd nfs-common portmap; do service $i start; done

Теперь все вернулось как было, за исключением переразбитого диска. Создаем из нового раздела, новую группу томов.
# pvcreate /dev/sda3
  Writing physical volume data to disk "/dev/sda3"
  Physical volume "/dev/sda3" successfully created
# vgcreate storage /dev/sda3
  Volume group "storage" successfully created

Теперь в веб-интерфейсе создаем новое хранилище. Вкладка Storage в Datacenter, кнопка Add.

Создаем виртуальную машину с образом размещенным в LVM хранилище

Проверяем наше хранилище, как видно там появился новый том.
# lvs storage
  LV            VG      Attr     LSize  Pool Origin Data%  Move Log Copy%  Convert
  vm-201-disk-1 storage -wi-ao-- 10.00g

На этом можно считать дело сделанным.

На главную "Virtualizing Linux"

3 комментария:

Популярные сообщения

Профиль в Google+ Яндекс цитирования Яндекс.Метрика