Administrador de Volúmenes Lógicos de Linux (LVM2)

La gestión de volúmenes Lógicos de Linux (LVM) es un software diseñado para añadir una capa entre los discos reales y la vista que hace el sistema operativo de los mismos para facilitar su administración, reemplazo y ampliación. Suele usarse en los centros de datos que usan hardware de actualización de discos, además de replicar datos para evitar pérdidas. Existen, por supuesto, alternativas: el hardware RAID es mejor en cuanto a rendimiento, pero más restrictivo: por ejemplo, no puedes reemplazar limpiamente un disco en un RAID0; luego está el mdadm, o software RAID, que es una implementación de software (nivel del sistema operativo) de RAID, pero tiene deficiencias similares. LVM es más flexible, permite una configuración que RAID no puede hacer. Dicho esto, como se trata de una mera solución de software (compuesta por módulos kernel y daemons de espacio de usuario), implica una cierta pérdida de rendimiento, bajará algo la velocidad con respecto al uso de discos de forma nativa.

El wiki de Debian explica bastante bien los conceptos básicos, de modo que no le voy a hacer la competencia, mira esto: https://wiki.debian.org/LVM. Si quieres un tutorial más detallado sobre LVM, recurre al excelente manual de RedHat en https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Cluster_Logical_Volume_Manager/ch_Introduction-CLVM.html.

Los conceptos básicos que usaré en este artículo son:

  • PV - volumen físico
  • VG - grupo de volumen
  • LV - volumen lógico

Todos los comandos LVM usan estas iniciales para referirse a los conceptos anteriores.

Instalación

Si estás ejecutando alguna de las imágenes oficiales de Ubuntu del repositorio de Hardkernel, esto es todo lo que necesitas hacer:

$ sudo apt install lvm2
Esto instalará los paquetes del kernel, el daemon del espacio de usuario y todo lo demás que necesitas para trabajar con LVM.

Cloudshell2

Cloudshell2 ofrece RAID por hardware con 2 discos, pero la capacidad de actualizar tu disco está algo limitada a menos que tenga una forma de clonar la matriz cada vez que quieras actualizar. La Wiki ODROID explica cómo configurar el controlador JMicron en https://wiki.odroid.com/accessory/add-on_boards/xu4_cloudshell2/raid_setting. Si quieres usar LVM, necesitarás utilizar la configuración JBOD. También puedes ejecutar LVM sobre una configuración RAID hw como RAID0 o RAID1 pero creo que el contexto de tan solo 2 discos es lo que elimina cualquier ventaja que el LVM pueda aportar. Después de conectar tus discos, querrás particionarlos. Los documentos LVM recomiendan no utilizar discos raw como los PVs (volúmenes físicos) y usar particiones en su lugar, incluso si se trata de una partición que se extiende a lo largo de todo el disco. En mi configuración hice esto, utilicé 2 HDDs de 3TB que contienen una partición que cubre todo el disco.

Una forma rápida de particionar tu disco es usar los siguientes comandos:

$ sudo fdisk /dev/sda
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-621, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-621, default 621):
w
Para obtener más información sobre el particionado de discos, consulta https://www.tldp.org/HOWTO/Partition/fdisk_partitioning.html.

Una de las mejores cosas que tiene el LVM es que puedes planificar y simular tu configuración con dispositivos en un circuito cerrado antes de llegar a implementarla realmente. La siguiente sección detalla la configuración con 2 discos de tamaño idéntico utilizados para 2 volúmenes seccionados (por rendimiento, no por seguridad). Como paso adicional, también vamos a simular la actualización de uno de los discos con un disco nuevo, dos veces su tamaño, esto también lo hice, simulé y luego implementé. En esta parte final del escenario, tu volumen ya no se seccionará porque los discos ya no tienen el mismo tamaño.

Configurar dispositivos en circuito cerrado

$ dd if=/dev/zero of=/tmp/hdd1.img bs=1G count=1
$ dd if=/dev/zero of=/tmp/hdd2.img bs=1G count=1
# twice the space
$ dd if=/dev/zero of=/tmp/hdd3.img bs=1G count=2

$ losetup -f

$ losetup /dev/loop0 /tmp/hdd1.img
$ losetup /dev/loop1 /tmp/hdd2.img
$ losetup /dev/loop2 /tmp/hdd3.img
Así que hemos creado 3 discos: dos discos de 1GB y un disco de 2GB, puedes usar las dimensiones que desees, son las proporciones las que importan y no los tamaños reales. Crea los volúmenes físicos (PV). $ pvcreate /dev/loop0 $ pvcreate /dev/loop1 $ pvcreate /dev/loop2

Lo que esto ha hecho es decirle a LVM que planeamos usar estos discos como soporte físico para nuestros futuros volúmenes lógicos. Lo que tenemos que recordar es que a cada PV se le asigna un ID único que se escribe en el disco para que, incluso si mueves los discos de tu sistema, LVM los encuentre en función de sus ID. Esto nos será muy útil cuando vayamos a actualizar nuestros discos de la carcasa Cloudshell2 y uno de los discos nuevos se conectará a través de USB 3.0 y luego se intercambiará con uno de los discos de la carcasa.

Tendremos que poner nuestros PVs en un Grupo de volumen antes de usarlos para crear volúmenes lógicos, este es un paso obligatorio, también ten en cuenta que no es posible crear volúmenes lógicos utilizando PVs desde diferentes VGs.

$ vgcreate vgtest /dev/loop0 /dev/loop1
Ahora que hemos creado un VG usando nuestros 2 discos simulados de 1GB, podemos verificar el estado de nuestra configuración en cualquier momento usando estos comandos
$ pvs
$ vgs

$ pvdisplay
$ lvdisplay

Crear volúmenes lógicos (LV)

Ahora crearemos nuestros volúmenes que se convertirán en las unidades que el sistema operativo considera utilizables. En este contexto, estoy creando 2 volúmenes seccionados, uno de 1 GB y otro que simplemente se llenara con el espacio restante.

$ lvcreate -i2 -I4 -L1G -nlvdata1 vgtest
$ lvcreate -i2 -I4 -l100%FREE -nlvdata2 vgtest
Los parámetros son:

  • -i2 : tira este volumen entre 2 PVs
  • -I4 : amplía el tamaño (el equivalente de un bloque en el lenguaje LVM) será de 4 MB
  • -n : qué nombre el volumen

El último parámetro es el grupo de volumen para operar. El tamaño se especifica con la opción -L o -l, -L requiere tamaños específicos, mientras que -l permite porcentajes y otros especificadores. Al final, tendremos 2 volúmenes que están distribuidos uniformemente en nuestros 2 PV en franjas, similar a un RAID0 (en realidad, 2 RAID0s, uno para cada volumen lógico o LV). Llegados a este punto, también tendremos que formatear nuestros nuevos volúmenes lógicos con el sistema de archivos que queremos utilizar, ejecuta los siguientes comandos:

$ mkfs.ext4 /dev/mapper/vgtest-lvdata1
$ mkfs.ext4 /dev/mapper/vgtest-lvdata2
Al igual que en cualquier partición normal, excepto en la ruta de los dispositivos, estos dispositivos lógicos están expuestos por LVM. Para mayor seguridad, monta estos discos y escribe algunos archivos de prueba, como si montaras un disco normal. Esto te permitirá probar la integridad al final.

Una vez que lo domines, puedes implementar el escenario anterior con discos reales en lugar de usar un circuito cerrado. Simplemente reemplaza /dev/loop0 y /dev/loop1 por /dev/sda y /dev/sdb y ajusta los tamaños de tus LVs.

Actualizar tus discos

Ahora, aquí es donde LVM realmente brilla por su ausencia; a diferencia del hardware RAID, que puede ser bastante rígido en cuanto a la capacidad de actualización (a menos que se use una configuración duplicada), LVM permite todo tipo de configuraciones de discos. Esta parte está basada en el genial tutorial de https://www.funtoo.org/LVM_Fun.

El escenario que vamos a implementar es el siguiente: reemplazaremos uno de los discos de la configuración por uno que tenga el doble de capacidad que el original, por ejemplo, si tenemos discos de 2x2GB, reemplazaremos uno de ellos por un disco de 4GB. Para identificar los discos, usa este comando:

$ sudo smartctl -i /dev/sda1
$ sudo smartctl -i /dev/sdb1
Asegúrate de ejecutar esto en las particiones y no en los discos. Debido al controlador JMicron que hay delante de nuestros discos, no recibirán ninguna información de los discos. El comando anterior te devolverá el código del producto, como ST2000DM para un Seagate Barracuda de 2TB. Esto to ayudará a decidir qué disco físico deseas reemplazar.

El procedimiento completo es:

  • Conectar el nuevo disco de repuesto en el segundo puerto USB3.0 utilizando una carcasa externa (el cloudshell solo admite 2 unidades SATA y ambos puertos ya están ocupados de momento)
  • Crear un PV (volumen físico) en el nuevo disco
  • Agregar nuevo PV al VG existente (grupo de volumen)
  • Desmontar todos los volúmenes de VG y/o congelar la asignación en el PV para migrar
  • Pvmove uno de los 2 PV existentes en este nuevo PV
  • Dejarlo trabajar toda la noche ya que se va a copiar un disco de 2tb sector por sector
  • Reducir VG eliminando el PV anterior (el que se movió en el paso anterior)
  • Apagar y cambiar el disco viejo por uno nuevo
  • Arrancar y comprobar que los LVs (volúmenes lógicos) están asignados correctamente a los PVs

Ten en cuenta que no todas las carcasas USB3.0 externas serán compatibles con el controlador UAS. Yo utilicé una de la marca ORICO.

Al igual que ocurre con todas las cosas de LVM, puedes (y deberías) simular la actualización antes de ejecutarla.

Conectar el nuevo PV

En primer lugar, conectemos el tercer dispositivo del bucle que hemos creado anteriormente (el de 2GB) a nuestro VG existente:

$ vgextend vgtest /dev/loop2

Migrar el viejo PV al nuevo PV

En este paso, migramos el disco viejo al disco nuevo:

$ pvmove --atomic -v -A y /dev/loop1 /dev/loop2
Aquí tenemos 2 parámetros importantes:

  • - --atomic: el movimiento se realizará de forma transaccional, si falla en algún punto, simplemente se revierte, no se pierde la información.
  • -A y: realiza automáticamente una copia de seguridad de la configuración de LVM para restaurar en caso de que algo salga mal. La herramienta que necesitarás usar despues es vgcfgrestore.

Si interrumpes el proceso o experimentas una pérdida de energía, puede reiniciar el proceso ejecutando el siguiente comando:

$ pvmove
Aunque, te sugiero abortar y empezar de nuevo:
$ pvmove --abort
Debido a que nuestro pvmove era atomic, esta interrupción lo restaurará todo a su estado original (si no usáramos -atomic entonces algunas PE - extensiones físicas se moverían y otras seguirían estando asignadas al volumen anterior y tendríamos que moverlas manualmente). En el mundo real, este paso lleva bastante tiempo, y normalmente lo dejo trabajar durante toda la noche (estamos moviendo 2 TB de datos).

Redimensionar el nuevo PV

Ahora necesitamos cambiar el tamaño del PV recientemente movido para incluir el espacio libre adicional en el disco, esto simplemente se hace con el siguiente comando:

$ pvresize /dev/loop2

Redimensionar el volumen lógico

Ahora podemos aprovechar ese nuevo espacio en disco y ampliar uno de nuestros LV para incluirlo. Debido a que nuestra configuración utiliza franjas, y debido a que este nuevo espacio libre está solo en un PV, no podremos hacer que el nuevo espacio tenga franjas, de modo que necesitaremos usar este comando:

$ lvextend -i1 -l +100%FREE /dev/vgtest/lvdata2
El parámetro -i1 le dice a LVM que estamos reduciendo a solo 1 franja. Esto dará como resultado un rendimiento de impacto general, ya que los datos escritos en esta parte del volumen estarán en un solo disco. Al ejecutar el comando "lvdisplay -m", podemos revisar nuestra configuración resultante:
$ lvdisplay -m /dev/vgtest/lvdata2
  --- Logical volume ---
  LV Path              /dev/vgtest/lvdata2
  LV Name              lvdata2
  VG Name              vgtest
  LV UUID              vDefWQ-1ugy-1Sp5-T1JL-8RQo-BWqJ-Sldyr2
  LV Write Access      read/write
  LV Creation host, time odroid, 2018-03-06 17:43:44 +0000
  LV Status            available
  # open               0
  LV Size              1.99 GiB
  Current LE           510
  Segments             2
  Allocation           inherit
  Read ahead sectors   auto
  - currently set to   256
  Block device         254:2

  --- Segments ---
  Logical extents 0 to 253:
  Type              striped
  Stripes           2
  Stripe size       4.00 KiB
  Stripe 0:
    Physical volume   /dev/loop0
    Physical extents  128 to 254
  Stripe 1:
    Physical volume   /dev/loop2
    Physical extents  128 to 254

  Logical extents 254 to 509:
  Type              linear
  Physical volume   /dev/loop2
  Physical extents  255 to 510
Como puede ver, el segundo LV contiene un segmento lineal al final, ese es el nuevo espacio que acabamos de agregar y que no se puede franjear. En teoría, si también reemplazas el segundo disco, puedes volver a franjearlo, pero aún no he encontrado una forma segura de hacerlo. Si lo hago, escribiré otro artículo sobre ello.

Reciclar el disco de repuesto

Ahora es el momento de eliminar el disco que migramos desde nuestra configuración:

$ vgreduce vgtest /dev/loop1
Esto solo lo elimina del grupo de volúmenes. Si quieres también puedes usar pvremove para borrar la etiqueta LVM. También vamos a simular la eliminación física del disco:
$ losetup -d /dev/loop1
Ahora, vamos a simular la parte en la que apagamos el sistema y colocamos el nuevo disco directamente en Cloudshell2 (recuerda que lo teníamos en una carcasa externa), reemplazando efectivamente el anterior. En este paso, el disco 3 se desconectará y luego volverá como un nuevo disco:
$ losetup -d /dev/loop2
$ losetup /dev/loop1 /tmp/hdd3.img
Si ejecutas pvs, vgs y lvs, deberían indicar que tus volúmenes están intactos:
  PV       VG       Fmt  Attr PSize  PFree
  /dev/loop0 vgtest   lvm2 a--  1020.00m  0
  /dev/loop1 vgtest   lvm2 a--   2.00g  0
Finalmente, monta los volúmenes y verifica que los archivos de prueba todavía estén allí. Para comentarios, preguntas y sugerencias, visita el artículo original en https://www.cristiansandu.ro/2018/03/06/lvm-fun-swap-out-disk-in-lvm2-stripe/.

Be the first to comment

Leave a Reply