Linux: технология LVM

Алексей Федорчук
2003 г

На одной из страниц говорилось о подготовке дисковых разделов для установки Linux’а — то есть, по мнению ряда читателей, вещах достаточно элементарных. Поскольку описан был, собственно говоря, лобовой подход к этой проблеме. Попробуем подойти к ней с другого бока. Должен предупредить, что данный материал несколько устарел, так как относится к lvm 1, однако в принципе при переходе ко второй его версии изменилось немного., так что он сохраняет некоторую актуальность.

Преамбула

В чем недостаток лобового подхода? Представим простую жизненную ситуацию. Приблизившись к исчерпанию доступного дискового пространства для собственных данных, пользователь, как правило, приобретает новый жесткий диск и добавляет его в систему (случай полного переноса системы на новый носитель и выкидывания старого мы пока не рассматриваем — это отдельная история). Однако физически ввинтить винчестер в корпус — это полдела, нужно еще и сделать его для системы доступным. Как? Возможны варианты.

Можно создать на диске физический раздел, на нем — новую файловую систему и смонтировать ее к файловой системе корневой в заранее созданный каталог, например, $HOME/newhome. Это проще всего, но не всегда — лучше всего. Ведь в итоге единый пользовательский каталог будет состоять из двух физически различных файловых систем, что накладывает некоторые ограничения на манипулирование данными (например, невозможно создать жесткие ссылки на наборы данных другой файловой системы).

И вообще, это не очень удобно — все время помнить, какие данные находятся на одном физическом диске, какие — на другом. Гораздо проще, если весь пользовательский каталог видится как единое дисковое пространство, путь даже в натуре таковым и не является.

Второй пример, не менее жизненный. Послушавшись совета резонных людей, мы делим диск на разделы (без разницы, физические или логические) для всех возможных файловых систем — под каталоги /usr, /usr/local, /opt, /var, /tmp, /home. И очень быстро убеждаемся, что под /usr/local отвели слишком много места — весь новый софт по умолчанию желает собираться в каталоге /opt (с объемом которого мы явно пожадничали — никто не ожидал, что темпы стандартизации файловой системы будут столь стремительны). А каталог /usr, вследствие изобилия Иксовых приложений, напротив, заполняется через чур уж стремительно, что отнюдь не есть хорошо: производительность дисковых операций в любом Unix’е стремительно падает по достижении определенного предела заполненности файловой системы. Ну а каталог /tmp просто бездействует — роль хранителя временных файлов, как оказалось, с успехом исполняет файловая система в оперативной памяти — tmpfs. И что, спрашивается, делать? Вариант тотальной архивации и переразбиения дисков — просьба не предлагать.

Обеих ситуаций можно избежать, если озаботиться этим на стадии разбиения диска. И — прибегнуть к технологии LVM (Logical Volume Manager), то есть управления логическими томами.

Теоретическое введение

Вводное замечание, касаемое терминологии. Пользователи DOS/Windows знают, что логическими томами (logical volumes) называются те части, на которые бьется расширенный (extended) раздел DOS. Однако в случае LVM в понятие логического тома вкладывается, как станет ясно очень скоро, совершенно иной смысл. И потому впредь (здесь и во всех грядущих статьях) части расширенного DOS-раздела будут именоваться незамысловато — логическими разделами (впрочем, примерно такая терминология принята в Linux-программах разбиения диска), а звание логического тома сохранится только за элементом структуры LVM.

И вообще, это не очень удобно — все время помнить, какие данные находятся на одном физическом диске, какие — на другом. Гораздо проще, если весь пользовательский каталог видится как единое дисковое пространство, путь даже в натуре таковым и не является. И именно этой цели (в числе многих прочих) и служит технология LVM.

Теперь можно перейти к сути дела. Основа технологии LVM — в выделении двух уровней организации дискового пространства, физического и логического. Единица физической организации — физический том (Physical Volume). Это — не что иное, как самый обычный дисковый раздел с определенным идентификатором типа файловой системы — 8e (тем самым шестнадцатеричным номером, который присваивается разделу при его создании, например, программой fdisk). Физический том делится на физические же блоки (physical extents) — кванты дискового пространства, на которые может изменяться размер логических ресурсов (своего рода отдаленный аналог обычного физического блока винчестера).

Единицей организации логической в LVM выступает группа томов (Volume Group). Она сливает воедино физические тома так, что для ОС они выглядят как единый носитель, и, следовательно, может представляться как нечто вроде логического аналога винчестера. Как и винчестер, группа томов может делиться на разделы (или, напротив, представлять собой единый раздел). Один такой раздел и есть логический том, на котором создаются обычные файловые системы и к которому непосредственно обращается пользователь, например, при монтировании. Он образован последовательностью логических блоков (logical extents), которые можно сопоставить с блоками обычного раздела, размечаемыми при создании файловой системы. А уж эти логические extent’ы (во избежание путаницы оставляю этот термин без перевода) по определенным правилам связываются с extent’ами физическими.

В LVM-HOWTO взаимосвязь элементов LVM иллюстрируется следующим образом:

    hda1   hdc1      (PV:s on partitions or whole disks)
        /
       /
     diskvg        (VG)
    /  |
   /   |
usrlv rootlv varlv (LV:s)
 |      |     |
ext2  reiserfs  xfs (filesystems)

Взаимосвязь физических и логических extent’ов обозначается термином mapping. Причем возможны два варианта такой взаимосвязи — линейный (linear mapping) и «чередующийся» (striped mapping). В первом случае непрерывной последовательности физических extent’ов просто ставится в соответствие столь же непрерывная последовательность extent’ов логических. Во втором же — непрерывная последовательность логических extent’ов соотнесена с физическими extent’ами, чередующимися между физическими носителями:

   .+-- Volume Group --------------------------------+
 |                                                |
 |    +----------------------------------------+  |
 | PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
 |    +----------------------------------------+  |
 |      .          .          .        .          |
 |      .          .          .        .          |
 |    +----------------------------------------+  |
 | LV | LE |  LE | LE | LE | LE | LE | LE | LE |  |
 |    +----------------------------------------+  |
 |            .          .        .         .     |
 |            .          .        .         .     |
 |    +----------------------------------------+  |
 | PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
 |    +----------------------------------------+  |
 |                                                |
 +------------------------------------------------+

Эта схема подобна той, что осуществляется в программных RAID-массивах нулевого (strip) уровня и преследует ту же цель — повышение производительности дисковых операций. Правда, последнее достижимо только в том случае, если физические тома, на которых расположены чередующиеся физические extent’ы, расположены не просто на разных дисках, но и на разных IDE-каналах.

Подготовка к практике

Для начала технология LVM требует поддержки ядром системы. Это достигается его перекомпиляцией с включением двух опций. При использовании make menuconfig в секции Multi-device support (RAID and LVM) нужно включить, во-первых, поддержку Multiple devices, во-вторых — собственно менеджера логических томов (Logical volume manager (LVM) support). А в make config следует положительно ответить на соответствующие вопросы, после чего соответствующий раздел файла /usr/src/linux-*/.config должен приобрести следующий вид:

#
# Multi-device support (RAID and LVM)
#
CONFIG_MD=y
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
# CONFIG_MD_MULTIPATH is not set
CONFIG_BLK_DEV_LVM=y

Далее, потребуется софт для работы с LVM. Он входит в пакет lvm, который нынче включается в штатный комплект любого уважающего себя дистрибутива. В составе пакета — три группы утилит, предназначенных для работы с физическими томами (pv*), логическими группами (lg*) и логическими томами (lv*). Так, команда pvcreate создает физические тома, команда pvscan — сообщает об наличествующих, а команда pvdisplay выводит о них полную информацию. А тройки команд vgcreate, vgscan, vgdisplay и lvcreate, lvscan, lvdisplay проделывают то же для групп томов и логических томов, соответственно.

Как и положено уважающим себя Unix-программам, все компоненты пакета хорошо документированы, и с их опциями можно ознакомиться на стандартных man- и info-страницах. Вышеупомянутый LVM-HOWTO содержит много информации по практическому применению этих команд (в том числе и душераздирающую историю о глупом Джо, не использовавшем LVM, и умной Джейн, без нее жизни себе не мыслившей). Так что описывать команды в подробностях я не буду — необходимые опции будут приведены при описании практических упражнений.

Упражнение первое: случай одного диска

Итак, технология LVM наиболее эффективна ( и эффектна) в случае, если в машине имеется более одного физического диска. Однако и в однодисковой системе ее можно использовать с большим успехов (в том числе и в расчете на обогащение вторым накопителем).

Условия задачи: машина с винчестером Seagate Barracuda ATA IV на 80 Мбайт (прочие компоненты несущественны). Требуется: разбить диск так, чтобы максимально разгрузить корневую файловую систему, вынеся за ее пределы все, что можно (и нужно). И при этом не сожалеть потом о бесцельно растраченном дисковом пространстве.

Оговоримся, что в этом разделе молчаливо предполагается, что мы устанавливаем дистрибутив Gentoo — по описанной в соответствующей статье схеме. Однако большая часть сказанного применима и ко многим иным ситуациям.

Для начала определяемся, что же следует оторвать от корней. В первую очередь, разумеется, /boot — его, как и swap-раздел, помещаем на отдельные (причем первичные) разделы. Далее, разумеется, /home, /usr, /opt — эти обязательно. При желании — /var и /tmp. Может быть — /usr/local, если планируется ставить много внедистрибутивного софта. После чего убеждаемся, что под корневую файловую систему потребуется совсем немного места. И начинаем разбиение. Лучше всего для этой цели подойдет старый добрый fdisk — его собрат cfdisk почему-то не способен присвоить разделу требуемый идентификатор типа файловой системы.

Итак, /dev/hda1 на 20-50 Мбайт — под /boot (из расчета по 2 Мбайт на ядро, и с хорошим запасом). Под swap-раздел, /dev/hda2 — удвоенный объем ОЗУ, как советуют резонные люди. А вот под корень на /dev/hda3 потребуется всего-навсего сотня-другая мегабайт — и это тоже с избытком. У меня (дистрибутив Gentoo) на / занято около 30 Мбайт. В любом случае, объем этот можно рассчитать очень точно, исходя из особенностей конкретного дистрибутива. И накинуть сотенку для страховки — переполнение корневой файловой системы, как говорят, — вещь крайне неприятная.

Все же остальное пространство, конечно, можно объявить расширенной DOS-партицией и поделить на логические разделы в количестве, как нетрудно подсчитать, пяти-шести штук. Но мы пойдем иным путем. И, действительно создав extended-раздел остаточного объема (/dev/hda4), создаем в нем всего один логический раздел. И меняем его тип с Linux native на Linux LVM (шестнадцатеричный идентификатор типа файловой системы — 8e). Сохраняем изменения и покидаем fdisk. После чего посредством, например,

$ sfdisk -l /dev/hda

созерцаем картину вроде следующей:

Disk /dev/hda: 9729 cylinders, 255 heads, 63 sectors/track
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0Device Boot Start     End   #cyls    #blocks   Id  System
 /dev/hda1   *      0+      5       6-     48163+  83  Linux
 /dev/hda2          6     129     124     996030   82  Linux swap
 /dev/hda3        130     191      62     498015   83  Linux
 /dev/hda4        192    9728    9537   76605952+   5  Extended
 /dev/hda5        192+   9728    9537-  76605921   8e  Linux LVM

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

$ vgscan

которая отыщет все имеющиеся в наличии потенциальные физические тома, то есть разделы типа 8e (в нашем случае такой будет только один) и создаст необходимые файлы конфигурации — /etc/lvmtab и /etc/lvmtab.d, о чем любезно нас проинформирует:

vgscan -- reading all physical volumes (this may take a while...)
vgscan -- "/etc/lvmtab" and "/etc/lvmtab.d" successfully created

Второй шаг — собственно превращение дискового раздела Linux LVM в физический том командой

$ pvcreate /dev/hda5

После этого командой pvscan можно проверить, что система думает о наших томах. В ответ она сообщит путь к каждому из файлов устройств физических томов (при использовании devfs — в полной нотации), их объем и степень занятости (пока, разумеется, нулевую), а также состояние (на данном этапе — не активное):

$ pvscan
pvscan -- reading all physical volumes (this may take a while...)
pvscan -- inactive PV "/dev/ide/host0/bus0/target0/lun0/part5" is in no VG [73
pvscan -- total: 1 [73.06 GB] / in use: 0 [0] / in no VG: 1 [73.06 GB]

Третий шаг — создание из физических томов логической группы (Volume Group). Для этого потребуется команда vgcreate с именем группы в качестве первого аргумента и имени файла устройства раздела — как аргумента второго.

Имя группы — произвольно, в путях к файлам устройств физических томов при использовании devfs должна применяться полная нотация (как это вывела команда pvscan). По умолчанию тома нарезаются на физические блоки extent’ы размером 4 Мбайт. При желании иметь другой размер блока — это можно явно задать опцией -s ##m. Резонные люди рекомендует использовать extent’ы в 32 Мбайт. То есть требуемая команда будет иметь вид вроде

$ vgcreate -s 32m all /dev/ide/host0/bus0/target0/part5

В этом случае максимальный размер любого из будущих логических томов ограничивается фантастической (пока) величиной 2 терабайта. Если же остановиться на умолчальном extent’е, предел тома составил бы всего-навсего 256 Гбайт. Именно всего-навсего — согласитесь, ныне эта величина не кажется недостижимой.

Теперь можно выполнить команду pvscan, дабы убедиться в результате. Она, плюс к прежней информации, сообщит нам, что физические тома активированы и включены в группу имя рек (конкретно в примере — all):

$ pvscan
pvscan -- reading all physical volumes (this may take a while...)
pvscan -- ACTIVE   PV "/dev/ide/host0/bus0/target0/lun0/part5" of VG "all" [73
pvscan -- total: 1 [73.06 GB] / in use: 1 [73.06 GB] / in no VG: 0 [0]

А полную информацию о вновь созданной группе мы получим командой vgdisplay, которая, в числе прочего, сообщит нам имя группы, режим доступа к ней и ряд других данных:

--- Volume group ---
VG Name               all
VG Access             read/write
VG Status             available/resizable
VG #                  0
MAX LV                256
...
MAX LV Size           2 TB
Max PV                256
Cur PV                1
Act PV                1
VG Size               73 GB
PE Size               32 MB
Total PE              2336
...
VG UUID               TiYr9D-5Ub5-ordV-Zcv6-A7Eg-AIqD-1ALFe6

Четвертый шаг — собственно создание логического тома или томов, по желанию. Это — некий аналог нарезания на разделы физического жесткого диска. И осуществляется он командой lvcreate, для которой в качестве опций нужно указать размер тома и его имя (-L и -n, соответственно), а аргументом — имя ранее созданной группы. Размер тома можно указывать в гигабайтах или в любых других *байтах. И очевидно из названия, что под логический том можно отвести как весь объем группы, так и ее часть — в последнем случае у нас останется место и для других томов.

Собственно, именно последнее и было нашей целью. И потому — последовательность команд:

$ lvcreate -L 10G -n lvusr all &&
> lvcreate -L 2G -n lvar all &&
> lvcreate -L 2G -n lvopt all &&
> lvcreate -L 55G -n lvhome all &&
> lvcreate -L 2G -n lvtmp all

создаст нам тома под все намеченные к использованию файловые системы. Имена томов, разумеется, произвольны и даны просто в мнемонически удобном виде.

Замечу, что приведенной последовательностью команд создаются логические тома с линейным соответствием физических и логических extent’ов. Предписать использование схемы чередования (striped) можно было бы дополнительной опцией -i. А опция -I [значение] задаст размер чередующих блоков (в килобайтах). Однако в случае единственного диска (и единственного физического тома) это не имеет физического смысла.

Как и ранее, выполним некоторую проверку: командой lvscan отыскиваем все новообразованные логические тома, узнаем пути к файлам соответствующих им устройств, их размеры и убеждаемся в том, что тома (прекрасный каламбур, господа?) активированы

lvscan -- ACTIVE            "/dev/all/lvusr" [10 GB]
lvscan -- ACTIVE            "/dev/all/lvar" [2 GB]
lvscan -- ACTIVE            "/dev/all/lvopt" [2 GB]
lvscan -- ACTIVE            "/dev/all/lvhome" [55 GB]
lvscan -- ACTIVE            "/dev/all/lvtmp" [2 GB]
lvscan -- 5 logical volumes with 71 GB total in 1 volume group
lvscan -- 5 active logical volumes

.А командой

$ lvdisplay /dev/all/lv*

получаем о каждом томе всю информацию, которую в силах предоставить нам система, например:

$ lvdisplay /dev/all/lvhome
--- Logical volume ---
LV Name                /dev/all/lvhome
VG Name                all
LV Write Access        read/write
LV Status              available
LV #                   4
# open                 1
LV Size                55 GB
Current LE             1760
Allocated LE           1760
Allocation             next free
Read ahead sectors     1024
Block device           58:3

Остается пятый, последний, шаг: создание на каждом логическом томе файловой системы. Это делается точно так же, как для любого дискового раздела, и будет предметом подробного рассмотрения в дальнейшем. Пока же замечу, что на логических томах можно размещать любые файловые системы из числа поддерживаемых ядром Linux — их драйверы не видят разницы между обычным дисковым разделом, физическим или логическим, и томом LVM.

Завершающие действия (не шаги даже, а шажки) не несут ничего специфичного для логических томов: новообразованные файловые системы нужно смонтировать в соответствующие каталоги (которые, разумеется, должны существовать заранее), проверить ее работоспособность (какими-либо простыми операциями чтения-записи) и, при благоприятном исходе (сомневаться в оном у нас оснований нет) внести изменения в файл /etc/fstab на предмет их увековечивания. Который в итоге приобретет вид вроде следующего:

$ less /etc/fstab
#                  
# NOTE: If your BOOT partition is ReiserFS, add the notail option to opts.
/dev/discs/disc0/part1  /boot  ext2  noauto,noatime  1 1
/dev/discs/disc0/part3  /  ext3  noatime   0 0
/dev/discs/disc0/part2  none  swap  sw    0 0
/dev/all/lvusr          /usr  reiserfs noatime,notail  0 0
/dev/all/lvar           /var  reiserfs noatime,notail  0 0
/dev/all/lvopt          /opt  reiserfs noatime,notail  0 0
/dev/all/lvtmp          /tmp  ext2  noatime   0 0
/dev/all/lvhome         /home  reiserfs noatime,notail  0 0

Ну и, конечно, не худо перезагрузиться (или реинициализировать систему иным образом). Дабы лицезреть и пощупать все проделанное вживе…

Собственно говоря, ни в одном из документов, посвященных технологии LVM, мне не удалось обнаружить запрета и корень файлового древа поместить на логический том, однако собственного опыта по сему поводу не имею. Да и смысла в этом не вижу — по указанным выше причинам размер коневого каталога будет а) небольшим, б) точно рассчитанным, и в) практически неизменным. Но для тех, кто захочет экспериментировать — каталог /boot для ядра и загрузчика я все же оставил бы на физическом разделе — во избежание, как сказал один восточный мудрец.

Упражнение второе: диск хорошо, а два лучше

Концепция LVM построена в прямом противоречии с заветами товарища Ленина: для ее реализации, прежде чем размежеваться, необходимо решительно объединиться — в группу логических томов. Что особенно наглядно видно при ее приложению к системе с двумя (и более) дисками. Что, опять-таки, рассмотрим на конкретном примере.

Условия новой задачи: два одинаковых жестких диска по 40 Гбайт каждый. На первом — существующие разделы: корневой (/dev/hda3) — 12 Гбайт, загрузочный с GRUB (/dev/hda1, по умолчанию не монтируется при загрузке) — 50 Мбайт, раздел подкачки (/dev/hda2) — 1024 Мбайт, прочее пространство — /dev/hda4 под каталог /home. А второй физический диск — такой же, но свежевынутый из пластиковой коробки и свежевкрученный в корпус, ничего, по определению, на себе не несущий. Требуется: создать единое дисковое пространство из второго диска и раздела под домашний каталог первого на предмет монтирования как /home.

Для начала содержимое прежнего /home дублируем на независимый носитель — дабы оно могло быть безболезненно уничтожено. Теоретически рассуждая, можно было бы обойтись без этого. Но в любом случае, начинать какую бы то ни было дисковую операцию без полного бэкапа данных — по меньшей мере не предусмотрительно.

Далее, опять-таки, пошаговое описание. Первый шаг, как и ранее, — создание расширенных разделов на дисках (для первого диска, понятно, из прежнего /dev/hda4), внутри каждого — по логическому разделу на весь объем. Логическим разделам присваивается все тот же идентификатор файловой системы за шестнадцатеричным номером 8e. Наиболее прозрачно и контролируемо этот процесс осуществляется классически fdisk.

К слову сказать: наличие второго диска можно попутно использовать для повышения производительности своппинга. Для чего предварительно (то есть перед созданием логического раздела, в начальных цилиндрах диска) создаем первичный раздел с идентификатором 82, командой mkswap определяем его как раздел подкачки и добавляем строку в файл /etc/fstab, после чего соответствующая его часть приобретает вид

/dev/discs/disc0/part2  none    swap    sw,pri=1  0 0
/dev/discs/disc1/part1  none    swap    sw,pri=1  0 0

Второй шаг: двукратным повторением команды pvcreate на вышупомянутых логических разделах создаются физические тома (Physical Volume):

$ pvcreate /dev/hda5
$ pvcreate /dev/hdb5

Теперь — собственно объединение, предшествующее размежеванию:

$ vgcreate имя_группы /dev/discs/disc0/part5 /dev/discs/disc1/part5

опять же с использованием полной нотации по правилам devfs. И наконец — размежевание:

$ lvcreate -L 60G -n lvhome имя_группы

Легко видеть, что при этом никакого размежевания не происходит — образуется логический том под каталог /home. Но никто не в силах запретить нам и поделить группу томов на логические тома, например, для каждого пользователя системы.

Тут не лишне напомнить, что с помощью опций -i и -I можно попытаться повысить производительность дисковых операций: команда вроде

$ lvcreate -i 2 -I 8 -L 60G -n lvhome имя_группы

создаст схему соответствия stripped между физическими и логическими extent’ами, то есть иллюзию чередования записи на два физических диска блоками (chunks) по 8 Кбайт. Что, однако, сработает только при разнесении дисков с физическими томами на разные IDE-линии. Мне этого проверить не удалось. Но в случае нахождения дисков на одном IDE-канале результат неизменно скверный: скорость тяжелых дисковых операций падает в 4-8 раз (впрочем, для констатации этого и экспериментов не нужно — очевидно из общих соображений).

И вообще, для IDE-дисков следует всегда (по возможности) размещать физические тома не просто на разных носителях, но и на разных каналах встроенного контроллера, причем — в качестве master-устройств. Конечно, для типичной настольной, особенно домашней, машины этого добиться трудно — редко какой десктоп этого класса не несет на втором IDE-канале пару дивайсов типа CD ROM, CD-R/RW, DVD, Zip. И потому использование LVM практически неизбежно ведет к деградации производительности при мало-мальски тяжелых дисковых операциях.

Не смотря на это, рискну предположить, что применение LVM оправдано в любых условиях. Потому что взамен некоторого падения быстродействия дисковых операций (а вследствие особенностей файловых систем Linux это — далеко не самый критический фактор для интегральной производительности машины в настольных условиях) пользователь приобретает возможность исключительно гибко управлять своими файловыми системами.

Так, по мере подключения к машине новых физических дисков на них можно создавать новые физические тома, присоединять их к существующей группе томов (или группам — никто не запрещал нам ранее создать их больше одной, пусть даже каждая до поры до времени и включала бы по единственному физическому тому), расширять за счет этого объем имеющихся логических томов или создавать новые (например, для новых пользователей системы). А между существующими логическими томами возможно динамическое перераспределение занимаемого дискового пространства — на величину, кратную размеру заданного физического extent’а. После всех этих изменений логические тома могут представать перед пользователем как бы в двух ипостасях — реальном и в виде среза (snapshot) на некоторый предшествующий момент времени, что весьма удобно для резервного копирования.

Так что технология LVM являет собой достижение если и не вполне классической, с точки зрения старика Аристотеля, но все же — логики. И потому заслуживает рекомендации к всенародному применению.