Tutorial Logical Volume Manager (LVM) en Linux

¿Qué es LVM y por qué se usa en Linux?

Logical Volume Manager o LVM por sus siglas (Gestión del Volumen Lógico)), consiste en una arquitectura lógica que agrupa varios discos de sistema que suman todo su tamaño para conformar un único espacio sobre el que se pueden crear diferentes filesystem, cada uno con su tamaño específico.

Es decir, podemos tener un disco de 50GB y otro de 100 para agruparlos en un único espacio de 150GB. A esta estructura se la llama Volume Group. Con ella, podríamos crear un filesystem de 20GB, otro de 100 y otro de 30, si quisiéramos.

La flexibilidad que presenta LVM frente al sistema clásico de particionamiento de disco es mucho más ventajosa. Podemos crear snapshots de un volumen lógico a modo de copia de seguridad o clonación de datos, ampliar filesystems en caliente usando un disco nuevo asignado al VG o, incluso, podemos mover los datos de un disco a otro del mismo VG sin afectar al servicio, pues no requiere parada alguna.

Esta funcionalidad es muy útil en los entornos profesionales en los que es habitual migrar los discos de una cabina a otra más moderna o menos saturada.

A continuación, vamos a ver más ventajas de LVM y cómo utilizarlo.

Estructura básica de LVM

La estructura básica de LVM consiste en:

  • Physical Volume (PV): Son los discos físicos o LUNs.
  • Volume Group (VG): Es la agrupación de discos.
  • Logical Volume (LV): Es el espacio reservado dentro de la arquitectura LVM sobre el cuál crearemos un filesystem.
LVM
Ejemplo de estructura LVM

Ahora nos conectamos al sistema operativo para visualizar una estructura LVM:

  • Nombre de los VGs que hay definidos:
# vgs
 VG #PV #LV #SN Attr VSize VFree 
 vg00 1 12 0 wz--n- 99.80g 37.32g
 vgMySQL 1 1 0 wz--n- 499.99g 0 
 vgall01 2 1 0 wz--n- 1.46t 85.98g
 vgrear 4 2 0 wz--n- 3.91t 497.00g
#
  • Nombre de los PVS que forman cada VG:
# pvs
 PV VG Fmt Attr PSize PFree 
 /dev/sda2 vg00 lvm2 a--u 99.80g 37.32g
 /dev/sdb1 vgall01 lvm2 a--u 999.99g 0 
 /dev/sdc1 vgrear lvm2 a--u 999.99g 0 
 /dev/sdd1 vgrear lvm2 a--u 999.99g 497.00g
 /dev/sde1 vgMySQL lvm2 a--u 499.99g 0 
 /dev/sdf1 vgrear lvm2 a--u 999.99g 0 
 /dev/sdg1 vgall01 lvm2 a--u 499.99g 85.98g
 /dev/sdh1 vgrear lvm2 a--u 999.99g 0 
#
  • LVs definidos en cada VG:
# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 auditvol vg00 -wi-ao---- 1.50g 
 homevol vg00 -wi-ao---- 4.00g 
 lvISO vg00 -wi-ao---- 22.00g 
 lvplanific vg00 -wi-ao---- 500.00m 
 lvstats vg00 -wi-ao---- 500.00m 
 nbupdates vg00 -wi-ao---- 5.00g 
 optvol vg00 -wi-ao---- 2.00g 
 rhomevol vg00 -wi-ao---- 2.00g 
 rootvol vg00 -wi-ao---- 7.00g 
 swapvol vg00 -wi-ao---- 2.00g 
 tmpvol vg00 -wi-ao---- 6.00g 
 varvol vg00 -wi-ao---- 10.00g 
 lvbackupmysql vgMySQL -wi-ao---- 499.99g 
 lvall01 vgall01 -wi-ao---- 1.38t 
 lvcg2html vgrear -wi-ao---- 3.00g 
 lvrear vgrear -wi-ao---- 3.42t 
#

Toda la información anterior también la podemos sacar con un solo comando:

# vgdisplay -v vgrear
 Using volume group(s) on command line.
 --- Volume group ---
 VG Name vgrear
 System ID 
 Format lvm2
 Metadata Areas 4
 Metadata Sequence No 73
 VG Access read/write
 VG Status resizable
 MAX LV 0
 Cur LV 2
 Open LV 2
 Max PV 0
 Cur PV 4
 Act PV 4
 VG Size 3.91 TiB
 PE Size 4.00 MiB
 Total PE 1023992
 Alloc PE / Size 896760 / 3.42 TiB
 Free PE / Size 127232 / 497.00 GiB
 VG UUID Mt4umD-nrUM-YdJW-DjzH-bnO9-TkH3-fbfOAH
--- Logical volume ---
 LV Path /dev/vgrear/lvrear
 LV Name lvrear
 VG Name vgrear
 LV UUID ewn6LF-j6Z4-fiN0-22Py-eSWB-i73L-PBXzDn
 LV Write Access read/write
 LV Creation host, time lhpilox01, 2015-05-21 08:09:11 +0200
 LV Status available
 # open 1
 LV Size 3.42 TiB
 Current LE 895992
 Segments 14
 Allocation inherit
 Read ahead sectors auto
 - currently set to 256
 Block device 253:3
--- Logical volume ---
 LV Path /dev/vgrear/lvcg2html
 LV Name lvcg2html
 VG Name vgrear
 LV UUID 85fOnD-cKgv-vRLI-5SXJ-zd9J-siZq-jb3MgD
 LV Write Access read/write
 LV Creation host, time lhpilox01, 2017-05-04 10:55:25 +0200
 LV Status available
 # open 1
 LV Size 3.00 GiB
 Current LE 768
 Segments 1
 Allocation inherit
 Read ahead sectors auto
 - currently set to 256
 Block device 253:4
--- Physical volumes ---
 PV Name /dev/sdh1 
 PV UUID KWD76w-fCCp-OjPC-RVG1-pcuS-H1rs-zVZCST
 PV Status allocatable
 Total PE / Free PE 255998 / 0
PV Name /dev/sdc1 
 PV UUID 0b2nTr-JtxA-3u4y-jFSv-O7db-G16u-TD9387
 PV Status allocatable
 Total PE / Free PE 255998 / 0
PV Name /dev/sdf1 
 PV UUID Hyog2W-uisc-bZLG-1Gyo-SxA3-2fJJ-lD6c0Q
 PV Status allocatable
 Total PE / Free PE 255998 / 0
PV Name /dev/sdd1 
 PV UUID UhOknb-6uvu-aKRk-qt3p-oKof-E6xd-Odqza0
 PV Status allocatable
 Total PE / Free PE 255998 / 127232
#

Si miramos cómo están montados los filesystems, nos daremos cuenta de que cada filesystem apunta a un LV distinto:

# mount |grep mapper
/dev/mapper/vg00-rootvol on / type ext3 (rw)
/dev/mapper/vg00-homevol on /home type ext3 (rw,nosuid,nodev)
/dev/mapper/vg00-optvol on /opt type ext3 (rw,nodev)
/dev/mapper/vg00-rhomevol on /root/home type ext3 (rw,nosuid,nodev)
/dev/mapper/vg00-tmpvol on /tmp type ext3 (rw,nosuid,nodev)
/dev/mapper/vg00-varvol on /var type ext3 (rw,nodev)
/dev/mapper/vg00-auditvol on /var/log/audit type ext3 (rw,noexec,nosuid,nodev)
/dev/mapper/vgall01-lvall01 on /AL type ext4 (rw,acl)
/dev/mapper/vg00-lvstats on /stats type ext4 (rw)
/dev/mapper/vg00-lvplanific on /planific type ext4 (rw)
/dev/mapper/vgrear-lvrear on /REAR type ext4 (rw)
/dev/mapper/vgMySQL-lvbackupmysql on /Backup_MySQL type ext4 (rw)
/dev/mapper/vg00-lvISO on /ISO type ext4 (rw)
/dev/mapper/vg00-nbupdates on /usr/openv/nbupdates type ext3 (rw,nodev)
/dev/mapper/vgrear-lvcg2html on /cfg2html type ext4 (rw)
#

Cómo crear un Volume Group de LVM

Ahora que ya sabemos qué es Logical Volume Manager y para qué sirve, vamos a crear una estructura LVM con un physical volume, un volume group, un logical volume y, para finalizar, la creación de un filesystem.

Physical Volume

Con pvcreate «disco» indicamos que un determinado disco, por ejemplo, el /dev/sdb va a ser utilizado en LVM, es decir, le damos formato LVM. En el caso de RedHat, cuando creamos el VG ya ejecuta pvcreate automáticamente, pero en otros sistemas UNIX, como HP-UX, no es así.

De hecho, en RedHat ya se crea automáticamente el dispositivo y el directorio del VG (mknod y mkdir /dev/vg).

Volume Group

Una vez que ya tenemos claro los discos que vamos a utilizar para crear un VG, lo creamos:

vgcreate Nombre_del_VG disco1 disco2 discoN

Por ejemplo:

vgcreate vgMySQL /dev/sdb /dev/sdc

Logical Volume

Finalmente, creamos los volúmenes lógicos (lv) que necesitemos dentro de la estructura del VG:

lvcreate -n Nombre_del_LV -LTamaño VG

Por ejemplo:

lvcreate -n lvMySQL -L10G vgMySQL

Filesystem

Una vez creada la estructura LVM, podemos crear un filesystem sobre ella del formato que queramos. Por ejemplo:

mkfs.xfs /dev/vgMySQL/lvMySQL

Unificar dos VGs (vgmerge)

Si queremos unificar dos volume groups en uno solo, utilizaremos el comando vgmerge. Hay que tener en cuenta que el nombre de los logical volumes no puede coincidir y que el tamaño de extent (pv extent) deber ser idéntico en ambos VGs.

El procedimiento es muy sencillo:

[root@server1 ~]# umount /Backup_MySQL
[root@server1 ~]# umount /BackupPostgreSQL
[root@server1 ~]# vgchange -an vgPostreSQL
  0 logical volume(s) in volume group "vgPostreSQL" now active
[root@server1 ~]# vgmerge vgMySQL vgPostreSQL
  Volume group "vgPostreSQL" successfully merged into "vgMySQL"
You have new mail in /var/spool/mail/root
[root@server1 ~]# lvchange -a y vgMySQL/lvbackuppostgres
You have new mail in /var/spool/mail/root
[root@server1 ~]#

Comandos más utilizados en LVM

Ampliar un filesystem

lvextend -L512M /dev/VolGroup00/LogVol02
resize2fs /dev/VolGroup00/LogVol02

resize2fs es el comando que se utiliza para ampliar filesystems de tipo ext4 pero cada sistema de archivos tiene su propio comando de ampliación. Por ejemplo, en XFS, el comando a utilizar sería xfs_grow /dev/VolGroup00/LogVol02.

Con el comando anterior, hemos dejado el LV (y luego el FS) con un tamaño total de 512MB pero si lo que queremos es añadir 512MB al tamaño que ya tiene el FS, utilizaríamos:

lvextend -L+512M /dev/VolGroup00/LogVol02

Podrías necesitar incrementar el tamaño de journal del filesystem si no tienes bloques suficientes para la amplicación.

Reducir el tamaño de un filesystem

No todos los filesystems permiten reducir su tamaño. Por ejemplo, EXT4 sí lo permite. Se haría de la siguiente manera:

#Reducimos el FS a 95G, hace el umount+fsck+reducción
# resize2fs -M /dev/mapper/vgdml-lvdml
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/mapper/vgdml-lvdml to 23444391 (4k) blocks.
The filesystem on /dev/mapper/vgdml-lvdml is now 23444391 blocks long.
#Reducimos el disco a 95G, hace el umount+fsck+reducción
# lvreduce -r -L95G /dev/mapper/vgdml-lvdml
Do you want to unmount "/DML_OLD"? [Y|n] y
fsck from util-linux-ng 2.17.2
/dev/mapper/vgdml-lvdml: 29296/6553600 files (0.3% non-contiguous), 23397618/26214400 blocks
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/mapper/vgdml-lvdml to 24903680 (4k) blocks.
The filesystem on /dev/mapper/vgdml-lvdml is now 24903680 blocks long.
Reducing logical volume lvdml to 95.00 GiB
 Logical volume lvdml successfully resized
#

Eliminar un volúmen lógico (lv)

Para poder eliminar un LV, éste, debe estar en desuso, es decir, el FS debe estar desmontado. Luego, ya podemos eliminar el LV:

lvremove /dev/VolGroup00/LogVol02

Creación de un mirror de un volúmen lógico

Si no tenemos configurado el RAID de discos a nivel hardware, podremos configurar LVM para que haga el mirror de cada LV si tenemos espacio suficiente en el VG y en diferentes discos.

lvextend -m 1 /dev/VolGroup00/LogVol02

En las versiones más recientes de RedHat ya no se usa lvextend para crear mirrors, sino lvconvert.

lvconvert -m1 /dev/VolGroup00/LogVol02 /dev/sdae

Con m0 eliminamos el mirrror.

¿Qué tal si elaboramos un poco más la creación de un mirror, eliminamos uno de los discos y lo rehacemos?

Cuando no tenemos discos en cabinas, sino que son locales, es útil crear un mirror para no perder nuestros datos en caso de que tengamos alguna avería hardware en alguno de los discos.

Con LVM (Logical Volume Manager) podemos crear los mirrors. A continuación, se explica cómo crear un logical volume en mirror y cómo crear el mirror de un logical volume que actualmente no lo tiene configurado:

[root@cnt6tst ~]# uname -a
 Linux cnt6tst 2.6.32-696.20.1.el6.x86_64 #1 SMP Fri Jan 26 17:51:45 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 [root@cnt6tst ~]#

Listado de discos disponibles en el sistema

[root@cnt6tst ~]# fdisk -l |grep dev |grep -v mapper
 Disk /dev/sda: 12.9 GB, 12884901888 bytes
 /dev/sda1 * 1 39 307200 83 Linux
 /dev/sda2 39 1410 11017216 83 Linux
 /dev/sda3 1410 1567 1257472 82 Linux swap / Solaris
 Disk /dev/sdb: 5368 MB, 5368709120 bytes
 Disk /dev/sdc: 5368 MB, 5368709120 bytes
 [root@cnt6tst ~]#

Creamos un volume group nuevo

[root@cnt6tst ~]# vgcreate vgtest /dev/sdb /dev/sdc
 Physical volume "/dev/sdb" successfully created
 Physical volume "/dev/sdc" successfully created
 Volume group "vgtest" successfully created
 [root@cnt6tst ~]#

Creamos un logical volume en mirror y un filesystem

[root@cnt6tst ~]# lvcreate -n lvtest -m1 -L 4500M vgtest
 Logical volume "lvtest" created.
[root@cnt6tst ~]#

Observamos que la sincronización de ambos discos está en marcha:

[root@cnt6tst ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 lvtest vgtest mwi-a-m--- 4.39g [lvtest_mlog] 13.96
[root@cnt6tst ~]#

Podemos crear un filesystem en paralelo:

[root@cnt6tst ~]# mkfs.ext4 /dev/vgtest/lvtest
 mke2fs 1.41.12 (17-May-2010)
 Filesystem label=
 OS type: Linux
 Block size=4096 (log=2)
 Fragment size=4096 (log=2)
 Stride=0 blocks, Stripe width=0 blocks
 288000 inodes, 1152000 blocks
 57600 blocks (5.00%) reserved for the super user
 First data block=0
 Maximum filesystem blocks=1182793728
 36 block groups
 32768 blocks per group, 32768 fragments per group
 8000 inodes per group
 Superblock backups stored on blocks:
 32768, 98304, 163840, 229376, 294912, 819200, 884736
Writing inode tables: done
 Creating journal (32768 blocks): done
 Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 33 mounts or
 180 days, whichever comes first. Use tune2fs -c or -i to override.
[root@cnt6tst ~]#

[root@cnt6tst ~]# mount /dev/vgtest/lvtest /test
 [root@cnt6tst ~]# df -hP /test
 Filesystem Size Used Avail Use% Mounted on
 /dev/mapper/vgtest-lvtest 4.3G 8.9M 4.0G 1% /test
[root@cnt6tst ~]#

Copiamos un archivo

[root@cnt6tst ~]# cp -p /mnt/hgfs/Centos/CentOS-6.9-x86_64-bin-DVD1.iso /test
 [root@cnt6tst ~]# ls -lh /test
 total 3.7G
 -rwxrwxrwx. 1 root root 3.7G Mar 10 21:46 CentOS-6.9-x86_64-bin-DVD1.iso
 drwx------. 2 root root 16K Mar 13 06:38 lost+found
 [root@cnt6tst ~]#

También veo que ha finalizado la sincronización del mirror:

[root@cnt6tst ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 lvtest vgtest mwi-aom--- 4.39g [lvtest_mlog] 100.00
 [root@cnt6tst ~]#

Eliminamos del mirror uno de los discos

[root@cnt6tst ~]# lvconvert -m0 /dev/vgtest/lvtest
 Logical volume lvtest converted.
 [root@cnt6tst ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 lvtest vgtest -wi-ao---- 4.39g
 [root@cnt6tst ~]#

Esto me permite eliminar uno de los discos del volume group:

[root@cnt6tst ~]# pvs
 PV VG Fmt Attr PSize PFree
 /dev/sdb vgtest lvm2 a--u 5.00g 616.00m
 /dev/sdc vgtest lvm2 a--u 5.00g 5.00g
[root@cnt6tst ~]#

[root@cnt6tst ~]# vgreduce vgtest /dev/sdc
 Removed "/dev/sdc" from volume group "vgtest"
[root@cnt6tst ~]#

[root@cnt6tst ~]# pvs
 PV VG Fmt Attr PSize PFree
 /dev/sdb vgtest lvm2 a--u 5.00g 616.00m
 /dev/sdc lvm2 ---- 5.00g 5.00g
[root@cnt6tst ~]#

Rehacemos el mirror

Ahora vamos a rehacer el mirror pero no el logical volume, ya que lo hemos creado previamente:

[root@cnt6tst ~]# vgextend vgtest /dev/sdc
 Volume group "vgtest" successfully extended
 [root@cnt6tst ~]# lvconvert -m1 /dev/vgtest/lvtest
 vgtest/lvtest: Converted: 0.0%
 vgtest/lvtest: Converted: 11.8%
 vgtest/lvtest: Converted: 23.7%
 vgtest/lvtest: Converted: 35.4%
 vgtest/lvtest: Converted: 47.7%
 vgtest/lvtest: Converted: 60.5%
 vgtest/lvtest: Converted: 72.4%
 vgtest/lvtest: Converted: 84.4%
 vgtest/lvtest: Converted: 97.1%
 vgtest/lvtest: Converted: 100.0%
 [root@cnt6tst ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 lvtest vgtest mwi-aom--- 4.39g [lvtest_mlog] 100.00
 [root@cnt6tst ~]#

Comprobación del estado de los datos

Como vemos, nuestros datos siguen intactos:

[root@cnt6tst ~]# ls -lh /test
 total 3.7G
 -rwxrwxrwx. 1 root root 3.7G Mar 10 21:46 CentOS-6.9-x86_64-bin-DVD1.iso
 drwx------. 2 root root 16K Mar 13 06:38 lost+found
 [root@cnt6tst ~]#

Mover datos de un disco a otro del mismo VG (pvmove)

A veces nos interesa sustituir un disco de un VG por otro. Esto es típico en la administración de sistemas de grandes empresas cuando compran una cabina de discos nueva y han de mover los datos del disco antiguo al nuevo sin afectar al servicio. Esto se hace en tres pasos:

1. Incorprar los discos de la cabina nueva al VG (vgextend Nombre_VG disco_nuevo).

2. Moviendo los datos del disco viejo al nuevo (pvmove disco_viejo disco_nuevo). Por ejemplo: pvmove /dev/sdb /dev/sdc.

# pvmove /dev/sdg1 /dev/sdk1
 /dev/sdg1: Moved: 0.0%
 /dev/sdg1: Moved: 2.0%
 /dev/sdg1: Moved: 4.0%
…
/dev/sdg1: Moved: 94.7%
 /dev/sdg1: Moved: 98.8%
 /dev/sdg1: Moved: 100.0%
#

3. Eliminando del VG los discos viejos. Por ejemplo: vgreduce Nombre_VG /dev/sdb.

Activar o desactivar un VG

Esto se utiliza más cuando estamos configurando clusters. En realidad, es el propio cluster quien activa el VG en el nodo correspondiente pero, si nos interesara activar o desactivar un VG manualmente, lo haríamos con el siguiente comando:

vgchange -a y Nombre VG
vgchange -a n Nombre VG

Escanear VGs

Cuando estamos montando clusters vemos los mismos discos en todos los servidores que van a formar el cluster para que cualquier servidor pueda montar los filesystems en caso de incidencia. Por lo tanto, también debe ver los mismos VGs con la misma estructura de datos.

Con el comando vgscan cada servidor escaneará la estructura LVM. Es decir, si creamos un VG en uno de los servidores del cluster, al ejecutar vgscan en otro de los servidores, tendrá visibilidad sobre el mismo VG.

Crear un snapshot de un filesystem con LVM

Crear un snapshot de un filesystem puede ser útil para hacer marcha atrás de un cambio. Por ejemplo, hemos actualizado el sistema operativo y hay algo que no funciona como esperábamos. Con un snapshot del filesystem de sistema podríamos restaurar el estado original.

Ocurriría lo mismo con cualquier otra aplicación.

Si los cambios han funcionado correctamente, podemos dejarlos permanentes y eliminar el snapshot.

Veamos como funciona:

  • Versión del sistema operativo donde voy a hacer la prueba:
[root@centostst1 ~]# lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.3.1611 (Core) 
Release: 7.3.1611
Codename: Core
[root@centostst1 ~]# 
  • Creo un fichero en el filesystem del que voy a hacer el snapshot:
[root@centostst1 ~]# df -hP /test
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vgtest-lvtest 477M 2.3M 445M 1% /test
[root@centostst1 ~]# echo "Primer fichero" > /test/fichero1.txt
[root@centostst1 ~]# ll /test
total 13
-rw-r--r-- 1 root root 15 Apr 13 13:26 fichero1.txt
drwx------ 2 root root 12288 Apr 13 13:25 lost+found
[root@centostst1 ~]#
  • Hago el snapshot:
[root@centostst1 ~]# lvcreate -s -n lvtest_snapshot -L 100M /dev/vgtest/lvtest
 Using default stripesize 64.00 KiB.
 Logical volume "lvtest_snapshot" created.
[root@centostst1 ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 root vg00 -wi-ao---- 10.80g 
 swap vg00 -wi-ao---- 3.42g 
 lvtest vgtest owi-aos--- 500.00m 
 lvtest_snapshot vgtest swi-a-s--- 100.00m lvtest 0.01 
[root@centostst1 ~]#
  • Ahora creo un segundo fichero en el filesystem /test, para guardar un cambio en el filesystem:
[root@centostst1 ~]# echo "Segundo fichero" > /test/fichero2.txt
[root@centostst1 ~]# ll /test
total 14
-rw-r--r-- 1 root root 15 Apr 13 13:26 fichero1.txt
-rw-r--r-- 1 root root 16 Apr 13 13:29 fichero2.txt
drwx------ 2 root root 12288 Apr 13 13:25 lost+found
[root@centostst1 ~]#
  • Pero, por aquellas circunstancias de la vida, deseo hacer marcha atrás del cambio:
[root@centostst1 ~]# umount /test
[root@centostst1 ~]# lvconvert --merge /dev/vgtest/lvtest_snapshot 
 Merging of volume vgtest/lvtest_snapshot started.
 lvtest: Merged: 100.00%
[root@centostst1 ~]# mount /test
[root@centostst1 ~]# ll /test
total 13
-rw-r--r-- 1 root root 15 Apr 13 13:26 fichero1.txt
drwx------ 2 root root 12288 Apr 13 13:25 lost+found
[root@centostst1 ~]# 
  • Ahora vuelvo a realizar un nuevo cambio y esta vez quiero conservarlo. Simplemente, elimino el snapshot:
[root@centostst1 ~]# lvremove /dev/vgtest/lvtest_snapshot 
Do you really want to remove active logical volume vgtest/lvtest_snapshot? [y/n]: y
 Logical volume "lvtest_snapshot" successfully removed
[root@centostst1 ~]# lvs
 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
 root vg00 -wi-ao---- 10.80g 
 swap vg00 -wi-ao---- 3.42g 
 lvtest vgtest -wi-ao---- 500.00m 
[root@centostst1 ~]# ll /test
total 14
-rw-r--r-- 1 root root 15 Apr 13 13:26 fichero1.txt
-rw-r--r-- 1 root root 16 Apr 13 13:37 fichero2.txt
drwx------ 2 root root 12288 Apr 13 13:25 lost+found
[root@centostst1 ~]# umount /test
[root@centostst1 ~]# mount /test
[root@centostst1 ~]# ll /test
total 14
-rw-r--r-- 1 root root 15 Apr 13 13:26 fichero1.txt
-rw-r--r-- 1 root root 16 Apr 13 13:37 fichero2.txt
drwx------ 2 root root 12288 Apr 13 13:25 lost+found
[root@centostst1 ~]#

Mover una base de datos a una cabina de discos más rápida con LVM

Alguna vez os he hablado de las incidencias que suelen reportar los usuarios de una aplicación con mensajes poco aclaratorios como «la aplicación me va lenta» y casi nunca pasa nada en los servidores a nivel de sistema operativo, que es lo que administro yo. Suele ser una consulta de Oracle que no va por índice, un problema de memory leak, garbage collector de Java, faltan incorporar nuevos servidores de aplicaciones, alguna operativa que ha lanzando un usuario cuando no tocaba y estaba machacando la base de datos… Pueden ser mil cosas y hay que analizarlo todo.

¿Por qué estoy migrando la base de datos a otra SAN?

Pues esta vez el problema estaba en la cabina de discos. Resulta que revisando las métricas de Average Service Time, que te da el tiempo que tarda un disco en responder, en los peores tiempos, el sistema enviaba una petición de lectura o escritura al disco y la cabina tardaba un minuto en responder, cuando lo normal tiene que ser menos de diez milisegundos.

Resultado: La base de datos se quedaba todo el rato esperando respuesta del disco. Venían nuevas peticiones de los usuarios que se encolaban por disco que se convirtieron en una bola de nieve que fue creciendo hasta colapsar el servidor. Load alto, etc.

Así que tuvimos que tomar medidas:

  • El equipo de Storage tendría que analizar el estado de la cabina de discos y optimizar su rendimiento.
  • En paralelo, para solucionar la incidencia, quedamos en que moveríamos los datos a otra cabina que estuviera más descargada y pudiese darnos los tiempos habituales de respuesta (menos de 10ms).

¿Cómo estoy migrando una base de datos Oracle a otra cabina de discos sin afectar al servicio?

El escenario de alta disponibilidad de disco de este entorno consiste en utilizar dos discos de dos cabinas diferentes y crear un mirror por software entre ambos. De esta manera, si cae una cabina de discos, los datos siguen accesibles por el disco de la otra cabina. No es el mejor sistema de HA pero es el que hay configurado en este entorno.

A nivel de sistema operativo, utilizamos Logical Volume Manager o LVM, lo que significa que dentro del volume group (VG) incorporamos los mirrors (Physical Volumes) que contienen los datos de la base de datos.

La gracia de LVM consiste en que permite mover datos en caliente de un disco a otro. Esto se consigue con el comando pvmove. Por lo tanto, la intervención o RFC (Request for change) la he programado de la siguiente manera:

  • Solicito nuevos discos en las cabinas rápidas.
  • Configuro el multipath. Esto se hace añadiendo las siguientes líneas en el fichero /etc/multipath.conf (RedHat 6). El WWID es el identificador del disco que me ha proporcionado el equipo de Storage.
 multipath {
                wwid 360002ac0000000000000009c000206ca
                alias md16_rem_1
        }

         multipath {
                wwid 360002ac0000000000000012d0002090f
                alias md16_rem_2
        }

         multipath {
                wwid 360002ac0000000000000009d000206ca
                alias md17_rem_1
        }

         multipath {
                wwid 360002ac0000000000000012c0002090f
                alias md17_rem_2
        }

  • Creo los mirrors por software apuntando al nombre del multipath.
mdadm --create --verbose /dev/md16 --name=0 --level=1 --raid-devices=2  /dev/mapper/md16_rem_1 /dev/mapper/md16_rem_2
mdadm -Db /dev/md16 >>  /etc/mdadm.conf 

mdadm --create --verbose /dev/md17 --name=0 --level=1 --raid-devices=2  /dev/mapper/md17_rem_1 /dev/mapper/md17_rem_2
mdadm -Db /dev/md17 >>  /etc/mdadm.conf
  • Incorporo los mirrors al VG actual de la base de datos.
vgextend vg_rem /dev/md16 /dev/md17
  • Muevo los datos desde los discos de la cabina actual a la nueva con pvmove. Para ello, lanzo con nohup el siguiente script:
nohup pvmoves.sh &


cat pvmoves.sh
# Disco 500GB
pvmove -i 300 /dev/md6 /dev/md16
# Disco 500GB
pvmove -i 300 /dev/md8 /dev/md17
# Disco 200GB
pvmove -i 300 /dev/md15 /dev/md16
# Disco 100GB
pvmove -i 300 /dev/md10 /dev/md17
# Disco 100GB
pvmove -i 300 /dev/md12 /dev/md17
# Disco 150GB
pvmove -i 300 /dev/md2 /dev/md16
# Disco 50GB
pvmove -i 300 /dev/md9 /dev/md17
  • Elimino del VG los discos en desuso para no volver a utilizar la cabina lenta.
vgreduce vg_rem /dev/md10 /dev/md12 /dev/md15 /dev/md2 /dev/md6 /dev/md8 /dev/md9

Por último, reconfiguro el cluster de ServiceGuard para que el paquete de servicio levante los nuevos mirrors. Pero de este producto hablo en el artículo Configuración de un cluster de ServiceGuard 12 en Linux RedHat 6.

¿Cuál es el mejor momento para mover datos de una cabina a otra?

No sé si hace falta decirlo, pero este tipo de intervenciones hay que realizarlas fuera de horario de servicio por dos motivos:

  1. Representa un riesgo evidente para el servicio que podría afectar a los usuarios.
  2. El pvmove lee discos de una cabina, los escribe en la nueva y los borra en la antigua, de manera continua, lo que representa mucha actividad de IO que va a afectar al rendimiento de la aplicación.

Uso de una LUN ampliada en RedHat y LVM sin rebotar el sistema

Cuando necesitamos ampliar un filesystem en RedHat, normalmente solicitamos una nueva LUN con el tamaño que necesitamos y la añadimos a la estructura LVM.

Sin embargo, me he encontrado casos en los que bien desde la cabina de discos, bien a nivel de VMWare, amplían la LUN que ya estaba utilizando.

En este segundo caso, para poder utilizar el nuevo espacio de la LUN sin tener que rebotar el servidor, seguiremos los siguientes pasos:

Rescaneamos los discos del sistema

find /sys/devices -name rescan |awk '{print echo "echo 1 > " $1}' |sh

En el log del sistema (/var/log/messages), detectamos el cambio de tamaño de la LUN:

Aug 26 11:25:49 sgdsrmdlh001 kernel: sdl: detected capacity change from 10737418240 to 42949672960

Lo podemos comprobar con un fdisk, por ejemplo:

 Disk /dev/sdl: 42.9 GB, 42949672960 bytes
 255 heads, 63 sectors/track, 5221 cylinders
 Units = cylinders of 16065 * 512 = 8225280 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes
 Disk identifier: 0x00000000

Ampliamos el physical volume (PV)

 pvs |grep sdl
 /dev/sdl vg_sybase lvm2 a-- 10.00g 0
 pvresize /dev/sdl
 Physical volume "/dev/sdl" changed
 1 physical volume(s) resized / 0 physical volume(s) not resized
 pvs |grep sdl
 /dev/sdl vg_sybase lvm2 a-- 40.00g 30.00g

Ampliar el logical volume (LV) y filesystem

Ahora ya podemos extender el logical volume y ampliar el filesystem como lo hacemos habitualmente:

lvextend -n NombreLV -L+30G
xfs_growfs /dev/NombreVG/NombreLV

Problemas con LVM

En esta sección detallaré algunas de las incidencias relevantes con las que me he topado.

Cannot archive volume group metadata for vgopt to read-only filesystem

Esta mañana me he quedado perplejo cuando estaba intentado ampliar un physical volume de una LUN ampliada de un servidor virtual porque decía que el filesystem estaba presentado en modo lectura, pero no veía ningún FS del volume group vgopt montado en modo lectura.

[root@lgekdpx0 ~]# pvresize /dev/sdb1
  Cannot archive volume group metadata for vgopt to read-only filesystem.
  0 physical volume(s) resized / 1 physical volume(s) not resized
[root@lgekdpx0 ~]# pvs
  PV         VG    Fmt  Attr PSize   PFree
  /dev/sda2  vg00  lvm2 a--   99.51g 120.00m
  /dev/sdb1  vgopt lvm2 a--   50.00g      0
  /dev/sdc1  vgopt lvm2 a--  100.00g   9.99g
  /dev/sdd1  vgopt lvm2 a--  100.00g      0
[root@lgekdpx0 ~]#


[root@lgekdpx0 ~]# mount |grep vgopt
/dev/mapper/vgopt-lvoptdata on /opt/PostgresqlDataGEFACT type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqllog on /opt/PostgresqlLog type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvoptscript on /opt/PostgresqlScriptsGEFACT type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqlbackup on /opt/PostgresqlBackupGEEC type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvoptback on /opt/PostgresqlBackupGEFACT type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqldata on /opt/PostgresqlDataGEEC type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqlwalcompr on /opt/PostgresqlWalComprGEEC type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqlxlog on /opt/PostgresqlXlogGEEC type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvoptcom on /opt/PostgresqlWalComprGEFACT type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvoptxlog on /opt/PostgresqlXlogGEFACT type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/vgopt-lvpostgresqlscripts on /opt/PostgresqlScriptsGEEC type xfs (rw,relatime,attr2,inode64,noquota)
[root@lgekdpx0 ~]#

Así, que pensé que había ocurrido algo a nivel de VMWare y el disco que me habían presentado estaba en modo lectura, ya que no era la primera vez que me había ocurrido. Pero nada de eso, resulta que el filesystem raíz estaba montado en modo lectura. De hecho, para mi sorpresa, ni siquiera estaba configurado en el fichero /etc/fstab!!!!

El problema quedó resuelto tras remontarlo con permisos de lectura y escritura.

[root@lgekdpx0 ~]# mount |grep -v rw
/dev/mapper/vg00-rootvol on / type xfs (ro,relatime,attr2,inode64,noquota)
[root@lgekdpx0 ~]# mount -o remount,rw /dev/mapper/vg00-rootvol
[root@lgekdpx0 ~]# pvresize /dev/sdb1
  Physical volume "/dev/sdb1" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized
[root@lgekdpx0 ~]# pvs |grep sdb1
  /dev/sdb1  vgopt lvm2 a--  100.00g  50.00g
[root@lgekdpx0 ~]#

Esto me ocurrió en un Linux RedHat 7.3.

Volume «VG_Name» is not active locally

Este error me ha ocurrido en un entorno con un cluster de ServiceGuard. Tengo algunos VGs que los activa el propio ServiceGuards pero este error me dio en un VG local que no me dejaba activar:

[root ~]# lvcreate -n openv -l+100%FREE vgopenv
  Volume "vgopenv/openv" is not active locally.
  Aborting. Failed to wipe start of new LV.
[root ~]# 

La solución fue añadir este VG local en la directiva volume_list del fichero /etc/lvm/lvm.conf:

[root ~]# grep -i volume_list /etc/lvm/lvm.conf |grep -v "#"
      volume_list = [ "vg00" "vgopenv"]
[root ~]#

En el propio fichero lvm.conf viene un poco de información acerda de esta directiva:

# If volume_list is defined, each LV is only activated if there is a match against the list.
lvm.conf

Devices file sys_wwid eui.194931df14b96e2c000c296999b11a28 PVID Qn1sf7s8Z6vIBZQ59h2OpVAaHTyHjsk4 last seen on /dev/nvme0n1p2 not found

En el error del título anterior, podemos ver como LVM no encuentra el physical volume, a pesar de que sí existe en el sistema:

[root@rhel9casa lvm]# pvs
  Devices file sys_wwid eui.194931df14b96e2c000c296999b11a28 PVID Qn1sf7s8Z6vIBZQ59h2OpVAaHTyHjsk4 last seen on /dev/nvme0n1p2 not found.
  Devices file sys_wwid eui.09014718d126ac0a000c29607ed81a01 PVID 1DdcV6JwdF0ffE7NtJ6bhm0zVkhA8GrB last seen on /dev/nvme0n2 not found.
[root@rhel9casa lvm]#

El problema estaba en una entrada que había en el fichero /etc/lvm/devices/system.devices:

[root@rhel9casa lvm]# cat /etc/lvm/devices/system.devices
# LVM uses devices listed in this file.
# Created by LVM command vgcreate pid 14646 at Wed Jan 25 15:29:23 2023
#VERSION=1.1.3
#IDTYPE=sys_wwid IDNAME=eui.194931df14b96e2c000c296999b11a28 DEVNAME=/dev/nvme0n1p2 PVID=Qn1sf7s8Z6vIBZQ59h2OpVAaHTyHjsk4 PART=2
#IDTYPE=sys_wwid IDNAME=eui.09014718d126ac0a000c29607ed81a01 DEVNAME=/dev/nvme0n2 PVID=1DdcV6JwdF0ffE7NtJ6bhm0zVkhA8GrB
[root@rhel9casa lvm]#

Al comentar esa entrada, el comando pvs ya responde con normalidad:

[root@rhel9casa lvm]# pvs
  PV             VG   Fmt  Attr PSize   PFree
  /dev/nvme0n1p2 vg00 lvm2 a--  <24.00g    0 
[root@rhel9casa lvm]#

El propósito principal de /etc/lvm/devices/system.devices es proporcionar un mecanismo para controlar qué dispositivos de almacenamiento (como discos duros, particiones, etc.) pueden ser usados por LVM. Esto es útil en situaciones donde quieres evitar que LVM interactúe con ciertos dispositivos por razones de rendimiento, seguridad, o para evitar conflictos con otros sistemas de almacenamiento o particiones.

Te puede interesar

COMPÁRTEME

Deja un comentario