LVM no Linux, o que é e como utilizar

Caso você já tenha passado por uma situação onde era necessária a repartição do seu HD (ou criação de link simbólico) por que sua partição estava cheia, nunca se perguntou “Poxa, como seria bom se eu pude-se apenas redimensionar as partições…”? Ou você tem um monte de HD sobrando de 80Gb e pensa: “Será que eu consigo juntar todos em um só ou tenho que ter uma partição/diretório para cada um deles e colocar meus dados bem separados?”, ou ainda, comprou aquele super ultra-hd de 320GB e quer trocar seu antigo HD de 80GB, mas pensa a mesma coisa, “Será que eu não consigo apenas juntar os dois?”. Pois bem, com o LVM você pode fazer tudo isso sem ter RAID via hardware (atenção LVM não é uma alternativa ao RAID, ele apenas apresenta algumas características similares), e muito mais (como clonagem de hd para backup, ou stripping por exemplo), vou mostrar em um sistema Slackware recem-instalado (não full-install, porém com as ferramentas necessárias que existem em praticamente todas as distribuições) como fazer um array de dados básico em um HD, e depois adicionar um HD para o mesmo array sem perder os dados.

Pré-requisitos

Últimamente a grande maioria dos sistemas Linux já possuem o LVM2 instalado por default, isso por que você pode fazer a sua partição /home em LVM por exemplo, mas caso a sua não possua, você deve instalar o LVM seguindos os passas apresentados na documentação oficial. Novamente reforço que isso será bem difícil de acontecer.

Vantagens/Desvantagens

Algumas vantagens que podemos listar:

  • Redimensionamento de partições em tempo real
  • Junção de várias partições em uma única
  • Junção de vários HDs para um grande espaço interno
  • Stripping
  • Criação de imagens de backup
  • Mirroring

Como desvantagens (nada é perfeito):

  • Acoplado ao Kernel (sem LVM para /boot por exemplo, e não recomendado fazer para /)
  • Acesso mais lento

Primeiros passos

Antes de mais nada devemos definir algumas nomenclaturas:

Volume Group (VG): É o grupo que contém o LVM em sí
Physical Volume (PV): O HD físico
Physical Extent (PE): Divisão de cada PV em chuncks (pedaços)
Logical Volume (LV): É o volume lógico que você pode utilizar (sua nova “partição”)
Logical Extent (LE): A divisão de cada LV em chuncks (pedaços)

O funcionamento pode ser demonstrado por esse ASCII art pego da documentação oficial:

+-- 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 |	 |
|    +----------------------------------------+	 |
|                                                |
+------------------------------------------------+

Utilização básica (array de dados)

Vamos lá então, LVM instalado e sabendo o que é cada nomenclatura, vamos inicializar o nosso Slackware e adicionar dois HDs de 1GB cada para criar uma partição lógica de 2GB (simples, sem stripping).

Inicialmente, precisamos rodar o comando vgscan, para que o sistema guarde as informações do LVM

root@Slackware:~# vgscan

Com Slackware inicializado e os HDs instalados, vamos particionar os mesmos, antes de mais nada vamos descobrir onde estão os HDs, caso você não saiba:

root@Slackware:~# fdisk -l
Disk /dev/hda: 8589 MB, 8589934592 bytes
16 heads, 63 sectors/track, 16644 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Disk identifier: 0x9fc2e51d

 Device Boot      Start         End      Blocks   Id  System
/dev/hda1               1        1041      524632+  82  Linux swap
Partition 1 does not end on cylinder boundary.
/dev/hda2            1042       16644     7863912   83  Linux
Partition 2 does not end on cylinder boundary.

Disk /dev/sda: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000

Disk /dev/sda doesn't contain a valid partition table

Disk /dev/sdb: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000000

Disk /dev/sdb doesn't contain a valid partition table

Ok, então temos nosso Slackware em /dev/hda e nossos dois hds em /dev/sda e /dev/sdb, vamos particioná-los, pessoalmente eu gosto do fdisk, mas qualquer ferramenta de particionamento funciona, basta criar uma partição ocupado o HD todo do tipo 8E (Linux LVM), faria para apenas um HD, para o outro o procedimento é o mesmo:

root@Slackware:~# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x82ae3dd8.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help):n 
Command action
 e   extended
 p   primary partition (1-4) p
Partition number (1-4): First cylinder (1-130, default 1): Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-130, default 130): Using default value 130

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 8e
Changed system type of partition 1 to 8e (Linux LVM)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

Temos agora a partição /dev/sdb1 e após efetuarmos o mesmo para o HD sda teremos /dev/sda1, ambos do tipo 8E (Linux LVM), vamos então criar o PV com 1 dos HDs, para demonstrar como efetuar um resize com um outro HD depois

root@Slackware:~# pvcreate /dev/sda1
  Physical volume "/dev/sda1" successfully created

Agora vamos criar um grupo (VG)

root@Slackware:~# vgcreate lvm /dev/sda1
  Volume "lvm" created successfully

Uma nota, o nome lvm pode ser qualquer coisa que facilite a administração, pessoalmente eu prefiro lvm, ele irá criar um diretório em /dev de nome lvm, onde irá guardar o volume lógico ex: /dev/lvm/data_array. Vamos verificar (e extrair uma informação muito útil) o volume:

root@Slackware:~# vgdisplay
--- Volume group ---
 VG Name               lvm
 System ID             
 Format                lvm2
 Metadata Areas        1
 Metadata Sequence No  1
 VG Access             read/write
 VG Status             resizable
 MAX LV                0
 Cur LV                0
 Open LV               0
 Max PV                0
 Cur PV                1
 Act PV                1
 VG Size               1016.00 MB
 PE Size               4.00 MB
 Total PE              254
 Alloc PE / Size       0 / 0   
 Free  PE / Size       254 / 1016.00 MB
 VG UUID               KpGi1R-xIkN-49gD-7nDC-y4HR-zUCh-2gLF7r

Tudo correto, e temos a informação importante que nos interessa agora, o total de PE livre, 254, vamos então criar um volume lógico com esse espaço livre:

root@Slackware:~# lvcreate -l 254 -n lvm data_array
  Logical volume "data_array" created

Agora, se formos ver em /dev/lvm, iremos encontrar o device data_array, que é uma partição lógica, ainda sem formatação, então vamos formatá-la como faríamos a qualquer outra partição, criar um diretório e montá-la nesse diretório:

root@Slackware:~# mkfs.ext4 /dev/lvm/data_array
.......
root@Slackware:~# mkdir /mnt/data_array
root@Slackware:~# mount /dev/lvm/data_array /mnt/data_array
root@Slackware:~# df -h /mnt/data_array
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/lvm-data_array
 1001M   18M  932M   2% /mnt/data_array

A escolha do EXT4 foi por pura preferência, se você precisa utilizar JFS,XFS,EXT2,EXT3,Reiserfs, etc, fique a vontade. Apenas fique atento à possibilidade de resize do sistema de arquivos que você escolher.
Sim, você pode utilizar essa partição normalmente, alias, até é uma boa idéia adicionar a mesma no /etc/fstab para montar automáticamente não? Adicione essa linha no /etc/fstab:

/dev/lvm/data_array    /mnt/data_array        ext4    defaults    0    0

Vamos criar um arquivo vazio de 524MB para teste:

root@Slackware:~# dd if=/dev/zero of=/mnt/data_array/file count=1024000
1024000+0 records in
1024000+0 records out
524288000 bytes (524 MB) copied, 165.452 s, 3.2 MB/s

Gostaria de reforçar que estou utilizando uma máquina virtual, então 3.2 MB/s não refletem a velocidade do sistema, isso pode (e vai) variar de sistema para sistema, a única certeza é que será mais lento.

Enfim, temos ~50% utilizado de nossa partição /mnt/data_array, e temos mais um HD de 1GB livre para utilizar, vamos efetuar o mesmo procedimento, porém vamos extender a partição lógica, no lugar de criar uma nova, vou explicar apenas os novos passos ok?

ATENÇÃO: A PARTIÇÃO A SER REDIMENSSIONADA DEVE SER DESMONTADA!!!

root@Slackware:~# umount /mnt/data_array
root@Slackware:~# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created
root@Slackware:~# vgextend lvm /dev/sdb1
  Volume group "lvm" successfully extended

Antes de continuar, o vgextend faz exatamente isso, ele extende o VG passado (lvm) para um novo PV (/dev/sdb1), como não utilizamos stripping, ele concatena no final. Continuando:

root@Slackware:~# vgdisplay lvm
--- Volume group ---
 VG Name               lvm
 System ID             
 Format                lvm2
 Metadata Areas        2
 Metadata Sequence No  7
 VG Access             read/write
 VG Status             resizable
 MAX LV                0
 Cur LV                1
 Open LV               0
 Max PV                0
 Cur PV                2
 Act PV                2
 VG Size               1.98 GB
 PE Size               4.00 MB
 Total PE              508
 Alloc PE / Size       254 / 1016.00 MB
 Free  PE / Size       254 / 1016.00 MB
 VG UUID               KpGi1R-xIkN-49gD-7nDC-y4HR-zUCh-2gLF7r
root@Slackware:~# lvresize -l +254 /dev/lvm/data_array
  Extending logical volume data_array to 1.98 GB
  Logical volume data_array successfully resized
root@Slackware:~# e2fsck -f /dev/lvm/data_array
e2fsck 1.41.8 (11-July-2009)
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
root@Slackware:~# resize2fs /dev/lvm/data_array
resize2fs 1.41.8 (11-July-2009)
Resizing the filesystem on /dev/lvm/data_array to 520192 (4k) blocks.
The filesystem on /dev/lvm/data_array is now 520192 blocks long.

root@Slackware:~# mount /mnt/data_array/
root@Slackware:~# df -h /mnt/data_array/
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/lvm-data_array
 2.0G  518M  1.4G  28% /mnt/data_array

Ok, passa a passo:

  1. Checar quanto temos de PE free com vgdisplay (no nosso caso 254)
  2. Aumentar o volume lógico /dev/lvm/data_array em 254 PE (vgresize -l +254 /dev/lvm/data_array)
  3. Checar a consistência do novo volume (pré-requisito para o comando resize2fs)
  4. Efetuar o resize utilizando resize2fs
  5. Utilizar o nosso array

Simples não? Vamos testar…

root@Slackware:~# dd if=/dev/zero of=/mnt/data_array/file2 bs=1024000 count=750
750+0 records in
750+0 records out
768000000 bytes (768 MB) copied, 227.653 s, 3.4 MB/s
root@Slackware:~# df -h /mnt/data_array/
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/lvm-data_array
 2.0G  1.3G  649M  66% /mnt/data_array

Olha que lindo, ele passou os dados de forma continua entre os dois HDs ;)

Mais informações

Além de obviamente a documentação oficial, um bom site que encontrei (agora que estou testando mirroring) é esse, vale a pena criar uma máquina virtual para brincar com isso ;)

About Zarnick

Programer, sysadmin, guitarrist, and Italian. That's what I am. Plain simple.
OpenSource, Stuffs, Tips, Tutorials , , ,