Давно заметил что в Ubuntu (server edition) во время инсталляции начали предлагать использовать LVM. Но я все не решался поставить production на него. Затем пообщался со теми кто его использовал, почитал доку - и последний год стал его использовать, так как постиг скрытую в нем мощь :)
Допустим, у нас есть простенький бюджетный сервер. Мы развернули новое приложение, и его база стала расти весьма стремительно. Итого - база, веб-файлы и система живут на одном физическом диске.
Был куплен диск WD Razor, и на него перенесли базу. Нагрузка диска (
iostat -x -m 1) составила 1-2%. Решено перенести туда же и веб-файлы, однако решение это пришло лишь через пару дней. Так что получилось наглядно продемонстрировать возможности LVM.
Part1. Creating...
Когда поставили разор на нем создали один раздел - LVM:
[cc lang="bash"]
# fdisk -l
Disk /dev/sdb: 74.3 GB, 74355769344 bytes
255 heads, 63 sectors/track, 9039 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000
Device Boot Start End Blocks Id System
/dev/sdb1 1 9039 72605736 8e Linux LVM
[/cc]
Пару слов об организации LVM.
Уровень 1: volume group (vg). Это наивысший уровень абстракции, объединяющий в себе logical volumes и physical volumes.
Уровень 2: physical volume (pv). Это некое блочное устройство, способное хранить данные (HDD, RAID, ...)
Уровень 3: logical volume (lv). Это эквивалент раздела на жестком диске.
Таким образом в группу добавляются физические тома (pv), и потом во всем этом пространстве свободного места создаются разделы (lv), на которых уже создается файловая система.
Итак, сначала создавался pv:
[cc lang="bash"]
pvcreate /dev/sdb1
[/cc]
Затем vg:
[cc lang="bash"]
vgcreate sys_vg /dev/sdb1
[/cc]
И затем на все свободное место указанного pv (/dev/sdb1) создали lv с именем var_lib_mysql:
[cc lang="bash"]
lvcreate -L 100%PVS -nvar_lib_mysql sys_vg /dev/sdb1
[/cc]
Дело за малым:
[cc lang="bash"]
mkreiserfs /dev/mapper/sys_vg-var_lib_mysql
mount /dev/mapper/sys_vg-var_lib_mysql /mnt
/etc/init.d/mysql stop
mv /var/lib/mysql/* /mnt/
mv /var/lib/mysql/.* /mnt/
umount /mnt
mount /dev/mapper/sys_vg-var_lib_mysql /var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
/etc/init.d/mysql start
[/cc]
Вот собственно и почти все. Последний штрих - прописать монтирование раздела в fstab, дабы это происходило при загрузке автоматом. Можно скучно сделать это через blkid, увидеть там нужный UUID (например, f6946e54-c7d6-4688-8fac-05dcb1bf9973), скопировать его, открыть /etc/fstab и вставить туда строку вида:
[cc lang="bash"]
UUID=f6946e54-c7d6-4688-8fac-05dcb1bf9973 /var/lib/mysql reiserfs defaults 0 2
[/cc]
а можно сделать так:
[cc lang="bash"]
printf "\nUUID=`blkid | grep sys_vg-var_lib_mysql | sed -r 's/.*UUID="([^"]*).*/\1/i'`\t/var/lib/mysql reiserfs defaults 0 2\n" >> /etc/fstab
[/cc]
Да, если сделать umount /var/lib/mysql && mount /var/lib/mysql до ребута - то /dev/disk/by-uuid/f6946e54-c7d6-4688-8fac-05dcb1bf9973 (или какой там получится) там еще не будет. Для того чтоб появился до ребута надо перезапустить udev:
[cc lang="bash"]
/etc/init.d/udev restart
[/cc]
Part2. Resizing...
Как я говорил раньше, с опозданием пришла мысль о том, что неплохо бы вынести и статические файлы на этот же винт. И сделать это совсем просто! Для этого от того lv что был создан раньше (и именуется var_lib_mysql) откусим немного места.
Сначала остановим все службы (говорят, reiserfs увеличивается/уменьшается без проблем налету, но я этого пока не пробовал на себе):
[cc lang="bash"]
/etc/init.d/mysql stop
umount /var/lib/mysql
[/cc]
Затем уменьшим файловую систему, а затем и lv на 20ГБ:
[cc lang="bash"]
resize_reiserfs -s-20G /dev/mapper/sys_vg-var_lib_mysql
lvreduce -L-20G /dev/mapper/sys_vg-var_lib_mysql
[/cc]
На всякий случай я предпочел проверить фс на ошибки (а вдруг!):
[cc lang="bash"]
reiserfsck /dev/mapper/sys_vg-var_lib_mysql
[/cc]
Ну и возвращаем обратно MySQL:
[cc lang="bash"]
mount /var/lib/mysql
/etc/init.d/mysql start
[/cc]
Теперь создадим lv для веб-файлов, и так как их намного меньше 20ГБ, я решил оставить 5ГБ про запас, никому их не присвоив. Потом можно будет налету добавить туда где закончится место.
[cc lang="bash"]
lvcreate -L 15G -nvar_www sys_vg
mkreiserfs /dev/mapper/sys_vg-var_www
[/cc]
Далее - перенос файлов:
[cc lang="bash"]
/etc/init.d/nginx stop
/etc/init.d/apache2 stop
mount /dev/mapper/sys_vg-var_www /mnt
mv /var/www/* /mnt/
mv /var/www/.* /mnt/
umount /mnt
mount /dev/mapper/sys_vg-var_www /var/www
/etc/init.d/apache2 start
/etc/init.d/nginx start
[/cc]
И опять не забываем про fstab:
[cc lang="bash"]
printf "\nUUID=`blkid | grep sys_vg-var_www | sed -r 's/.*UUID="([^"]*).*/\1/i'`\t/var/lib/mysql reiserfs defaults 0 2\n" >> /etc/fstab
[/cc]
По материалам:
- http://wiki.linuxquestions.org/wiki/LVM#example
- http://www.tldp.org/HOWTO/LVM-HOWTO/reducelv.html
PS: после изменения размера мог измениться UUID для lv var_lib_mysql, хотя я и не уверен в этом. Но проверить не помешает.
PS2: если работаете удаленно - не забывайте про
screen.
PS3: писалось по памяти, так что могут быть некоторые неточности. Тупой копипаст без вовлечения мыслительного процесса чреват боком. Я предупредил ;)