Migración de datos entre volúmenes físicos en LVM
Un punto importante de los sistemas en producción es el uso de los discos y su ocupación. Como no siempre trabajamos en arquitecturas desplegadas en proveedores que permiten modificar los discos en caliente, nosotros optamos por usar LVM para gestionar los puntos de montaje que requieren estar siempre montados, minimizando así pérdidas de servicio en operaciones sobre los mismos.
La forma más fácil y cómoda en estos casos es asignar un disco extra sobre la máquina y añadirlo al LVM para ampliar su capacidad. Pero esto, con el paso del tiempo ocasiona tener una gran cantidad de discos de diferentes tamaños e incluso de diferente rendimientos que puede afectar al performance de nuestro servicio o trabajos que requieran el uso de estos dispositivos de almacenamiento.
Como en nuestro día a día nos hemos encontrado con esta situación, máquinas con volúmenes lógicos compuestos por diferentes tipos de disco y tamaño, investigamos la forma de unificar en 1 único disco los datos repartidos en los diferentes discos sin requerir una parada de servicio.
El escenario en el que nos encontramos es una máquina con sistema operativo Ubuntu la cual dispone de un LVM montado en /__testMOVE con el siguiente contenido:
# Punto de montaje de nuestro LVM.
local>>mount -l | grep testMOVE
/dev/mapper/testMOVE-testMOVE on /___testMOVE type ext4 (rw,relatime)
# Mostrar contenido de nuestro LVM.
local>>find /___testMOVE/. -type f| sort -n
/___testMOVE/./1/1.txt
/___testMOVE/./1/2/2.txt
/___testMOVE/./1/2/3/3.txt
/___testMOVE/./1/2/3/4/4.txt
/___testMOVE/./1/2/3/4/5/5.txt
/___testMOVE/./1/2/3/4/5/6/6.txt
/___testMOVE/./1/2/3/4/5/6/7/7.txt
El LVM tiene una capacidad de 6GB y está formado por 3 discos de 2GB cada uno:
# Visualizamos los LV que tenemos
# para seleccionar el que queremos migrar los datos
local>>lvdisplay
--- Logical volume ---
LV Path /dev/testMOVE/testMOVE
LV Name testMOVE
VG Name testMOVE
LV UUID BiWtL7-23XA-Ekgl-2Xmx-Ch9J-CN3Q-5ZZ7ev
LV Write Access read/write
LV Creation host, time strUbuntu18, 2022-05-28 12:46:54 +0200
LV Status available
# open 1
LV Size <5,99 GiB
Current LE 1533
Segments 3
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:0
# Visualizamos los VG que tenemos
# para seleccionar el que queremos migrar los datos
local>>vgdisplay
--- Volume group ---
VG Name testMOVE
System ID
Format lvm2
Metadata Areas 3
Metadata Sequence No 2
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 3
Act PV 3
VG Size <5,99 GiB
PE Size 4,00 MiB
Total PE 1533
Alloc PE / Size 1533 / <5,99 GiB
Free PE / Size 0 / 0
VG UUID 5NK94D-5Z7P-0egW-9DOQ-IxIG-uFQN-jj6sJf
# Visualizamos los PV que tenemos
# para poder seleccionar el que queremos migrar los datos
local>>pvs
PV VG Fmt Attr PSize PFree
/dev/sdb testMOVE lvm2 a-- <2,00g 0
/dev/sdc testMOVE lvm2 a-- <2,00g 0
/dev/sdd testMOVE lvm2 a-- <2,00g 0
Bien, ahora lo que vamos a hacer es unificar los datos repartidos en estos 3 discos en 1.
NOTA
Tenemos que tener en cuenta que el nuevo disco tiene que ser de la misma capacidad o superior
En nuestro caso vamos a usar un disco de 10GB:
local>>fdisk -l | grep sd | grep -v sda
Disco /dev/sdb: 2 GiB, 2147483648 bytes, 4194304 sectores # En uso
Disco /dev/sdc: 2 GiB, 2147483648 bytes, 4194304 sectores # En uso
Disco /dev/sdd: 2 GiB, 2147483648 bytes, 4194304 sectores # En uso
Disco /dev/sde: 10 GiB, 10737418240 bytes, 20971520 sectores # Nuevo
Pasos a realizar:
1. Preparamos el disco para migrar los datos. Para ello usamos el siguiente comando:
local>>pvcreate /dev/sde
Physical volume "/dev/sde" successfully created.
2. Añadimos el disco que acabamos de crear al grupo del LVM que queremos unificar los datos:
# Visualizamos los grupos para seleccionar el que necesitamos
local>>vgs
VG #PV #LV #SN Attr VSize VFree
testMOVE 3 1 0 wz--n- <5,99g 0
# Añadimos el disco al VG
local>>vgextend testMOVE /dev/sde
Volume group "testMOVE" successfully extended
# Visualizamos de nuevo los grupos de LVM
# para comprobar que disponemos de 10G de espacio libre
local>>vgs
VG #PV #LV #SN Attr VSize VFree
testMOVE 4 1 0 wz--n- 15,98g <10,00g
3. Con esto ya tenemos el LVM preparado para migrar los datos de los 3 discos a 1. Los pasos a seguir son los siguientes:
# Mostramos los discos que tenemos en LVM
local>>pvs | grep testMOVE
/dev/sdb testMOVE lvm2 a-- <2,00g 0
/dev/sdc testMOVE lvm2 a-- <2,00g 0
/dev/sdd testMOVE lvm2 a-- <2,00g 0
/dev/sde testMOVE lvm2 a-- <10,00g <10,00g
# Visualizamos los discos que están actualmente en el LVM
local>>lvs -a -o+devices | grep testMOVE
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdb(0)
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdc(0)
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdd(0)
ADVERTENCIA
Antes de realizar los siguientes pasos asegurar que disponemos de un backup de los datos por lo que pudiese pasar.
Realizar los pasos de 1 en 1 con pvmove para asegurar la integridad de los datos.
# Migramos los datos del primer disco
local>>pvmove /dev/sdb /dev/sde
/dev/sdb: Moved: 1,57%
/dev/sdb: Moved: 100,00%
# Mostramos el LV para asegurarnos que se ha migrado
local>>lvs -a -o+devices | grep testMOVE
testMOVE testMOVE -wi-ao---- <5,99g /dev/sde(0)
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdc(0)
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdd(0)
# Migramos los datos del segundo disco
local>>pvmove -i1 /dev/sdc /dev/sde
/dev/sdc: Moved: 2,15%
/dev/sdc: Moved: 55,77%
/dev/sdc: Moved: 100,00%
# Mostramos el LV para asegurarnos que se ha migrado
local>>lvs -a -o+devices | grep testMOVE
WARNING: Cannot find matching striped segment for testMOVE/testMOVE.
testMOVE testMOVE -wi-XX--X- <5,99g /dev/sde(0)
testMOVE testMOVE -wi-ao---- <5,99g /dev/sdd(0)
# Migramos los datos del tercer y último disco
local>>pvmove -i1 /dev/sdd /dev/sde
/dev/sdd: Moved: 4,70%
/dev/sdd: Moved: 58,51%
/dev/sdd: Moved: 100,00%
# Mostramos el LV para asegurarnos que se ha migrado
local>>lvs -a -o+devices | grep testMOVE
WARNING: Cannot find matching striped segment for testMOVE/testMOVE.
testMOVE testMOVE -wi-XX--X- <5,99g /dev/sde(0)
# Vemos que ha aparecido un WARNING:
# no detecta correctamente los segmentos de nuestro LVM
# Forzamos el refresco de nuestro VG
# para que localice los segmentos
local>>vgchange --refresh testMOVE
# Ya no aparece el Warning
# El contenido está migrado al nuevo disco
local>>lvs -a -o+devices | grep testMOVE
testMOVE testMOVE -wi-ao---- <5,99g /dev/sde(0)
Ya tendríamos los datos de los discos migrados a la nueva ubicación y ya podríamos liberar los otros discos del grupo por si queremos utilizarlos para otro cometido o incluso eliminarlos.
Ya que hemos añadido un disco más grande en este ejemplo, vamos a aprovechar a asignar el espacio total al LVM y eliminaremos los otros 3 discos:
- Ampliamos el LVM hasta los 10GB:
# Extendemos el LV con la totalidad del espacio libre
# Usando para ello el disco /dev/sde
local>>lvextend /dev/testMOVE/testMOVE /dev/sde
Size of logical volume testMOVE/testMOVE changed
from <5,99 GiB (1533 extents) to <10,00 GiB (2559 extents).
Logical volume testMOVE/testMOVE successfully resized.
# Comprobamos que se ha ampliado correctamente
local>>lvs -a -o+devices | grep testMOVE
testMOVE testMOVE -wi-ao---- <10,00g /dev/sde(0)
# La capacidad de nuestro LVM sigue siendo de 6GB
local>>df -h | grep testMOVE
/dev/mapper/testMOVE-testMOVE 5,9G 24M 5,5G 1% /___testMOVE
# Realizamos el resize de nuestro LVM
# Con esto el sistema detectará la capacidad real
local>>resize2fs /dev/mapper/testMOVE-testMOVE
resize2fs 1.44.1 (24-Mar-2018)
El sistema de ficheros de /dev/mapper/testMOVE-testMOVE
está montado en /___testMOVE; hace falta cambiar el tamaño en línea
old_desc_blocks = 1, new_desc_blocks = 2
El sistema de ficheros en /dev/mapper/testMOVE-testMOVE tiene ahora
2620416 bloques (de 4k).
# Comprobamos que ya tiene la capacidad correcta
local>>df -h | grep testMOVE
/dev/mapper/testMOVE-testMOVE 9,8G 27M 9,3G 1% /___testMOVE
- Liberamos los 3 discos que ya no contienen datos del VG testMOVE:
# Mostramos los PV asignados a nuestro VG
local>>pvs | grep testMOVE
/dev/sdb testMOVE lvm2 a-- <2,00g <2,00g
/dev/sdc testMOVE lvm2 a-- <2,00g <2,00g
/dev/sdd testMOVE lvm2 a-- <2,00g <2,00g
/dev/sde testMOVE lvm2 a-- <10,00g 0
# Eliminamos del VG los discos que ya no están en uso
local>>vgreduce testMOVE /dev/sdb /dev/sdc /dev/sdd
Removed "/dev/sdb" from volume group "testMOVE"
Removed "/dev/sdc" from volume group "testMOVE"
Removed "/dev/sdd" from volume group "testMOVE"
# Comprobamos que ya no están asignados a nuestro VG
local>>pvs
PV VG Fmt Attr PSize PFree
/dev/sdb lvm2 --- 2,00g 2,00g
/dev/sdc lvm2 --- 2,00g 2,00g
/dev/sdd lvm2 --- 2,00g 2,00g
/dev/sde testMOVE lvm2 a-- <10,00g 0
- Eliminamos los discos del LVM:
# Eliminamos los discos que ya no pertenecen a ningún VG
local>>pvremove /dev/sdb /dev/sdc /dev/sdd
Labels on physical volume "/dev/sdb" successfully wiped.
Labels on physical volume "/dev/sdc" successfully wiped.
Labels on physical volume "/dev/sdd" successfully wiped.
# Comprobamos que se han eliminado correctamente
local>>pvs
PV VG Fmt Attr PSize PFree
/dev/sde testMOVE lvm2 a-- <10,00g 0
# Seguimos teniendo nuestro disco montado
local>>mount -l | grep testMOVE
/dev/mapper/testMOVE-testMOVE on /___testMOVE type ext4 (rw,relatime)
# Con la capacidad que hemos añadido y migrado al nuevo disco
local>>df -h | grep testMOVE
/dev/mapper/testMOVE-testMOVE 9,8G 27M 9,3G 1% /___testMOVE
# Y nuestro contenido
local>>find /___testMOVE/. -type f| sort -n
/___testMOVE/./1/1.txt
/___testMOVE/./1/2/2.txt
/___testMOVE/./1/2/3/3.txt
/___testMOVE/./1/2/3/4/4.txt
/___testMOVE/./1/2/3/4/5/5.txt
/___testMOVE/./1/2/3/4/5/6/6.txt
/___testMOVE/./1/2/3/4/5/6/7/7.txt
Con estos pasos hemos pasado de tener 3 discos de 2GB con un total de 6GB a un sólo disco de 10GB en nuestro volumen lógico facilitando así migraciones, snapshots y la gestión del volumen.