LVM: gestión de volúmenes lógicos en Linux

La mayoría de los problemas graves de almacenamiento en producción ocurren cuando el espacio se agota en una partición fija que no puedes redimensionar sin parar el servicio. LVM (Logical Volume Manager) existe exactamente para romper esa rigidez: interpone una capa de indirección entre el hardware físico y el sistema de archivos, de modo que puedes mover, ampliar, reducir o instantánear el almacenamiento sin que el kernel ni las aplicaciones tengan que saber nada del hardware subyacente.

La jerarquía tiene tres niveles que conviene tener claros antes de tocar ningún comando. Un Physical Volume (PV) es un disco o partición que le has dicho a LVM que puede gestionar; internamente, LVM escribe metadatos al principio del dispositivo y lo divide en Physical Extents (PE), que son la unidad mínima de asignación (4 MiB por defecto). Un Volume Group (VG) es el pool que agrupa uno o más PVs; desde fuera parece un gran espacio continuo aunque por debajo haya tres discos distintos. Un Logical Volume (LV) es la “partición” virtual que creas dentro del VG y que el sistema ve como un dispositivo de bloque normal en /dev/nombre_vg/nombre_lv. El LV se formatea y monta exactamente igual que cualquier /dev/sdb1.

El diseño tiene una consecuencia directa: puedes añadir un PV a un VG existente y ese espacio queda disponible inmediatamente para extender cualquier LV del grupo, sin reiniciar ni desmontar. Esto es lo que hace que LVM sea indispensable en servidores bare metal y on-premise con discos adicionales, mientras que en cloud los proveedores ya resuelven este problema una capa más arriba (con snapshots y resize de volúmenes EBS, persistent disks, etc.) y LVM añade complejidad sin beneficio proporcional.

Si te equivocas en la jerarquía —por ejemplo, intentas extender un LV más allá del espacio libre del VG, o ejecutas resize2fs antes de lvextend— el resultado va desde un error limpio hasta corrupción del filesystem si el orden de operaciones fue incorrecto. El caso más peligroso es reducir un LV con lvreduce sin haber reducido primero el sistema de archivos: LVM reducirá el dispositivo de bloque y el kernel truncará datos que el filesystem todavía consideraba suyos.

Ejemplo completo: crear, extender y hacer snapshot de un LV

El escenario: tienes dos discos nuevos (/dev/sdb y /dev/sdc) en un servidor Debian Bookworm y quieres crear un volumen para datos de aplicación, luego extenderlo en caliente añadiendo el segundo disco, y finalmente tomar un snapshot consistente antes de un despliegue.

# Instalar las herramientas si no están presentes
apt install lvm2

# ── 1. CREAR LOS PVs ──────────────────────────────────────────────────
# pvcreate escribe la cabecera LVM al inicio de cada dispositivo.
# Usar el disco entero (sin tabla de particiones) es perfectamente válido.
pvcreate /dev/sdb /dev/sdc

# Verificar: muestra tamaño, PE size y espacio libre por PV
pvdisplay /dev/sdb

# ── 2. CREAR EL VG CON UN SOLO PV POR AHORA ──────────────────────────
# Nombramos el VG "appdata". Empezamos solo con /dev/sdb.
vgcreate appdata /dev/sdb

vgdisplay appdata   # fíjate en "Free PE / Size" — todo el disco disponible

# ── 3. CREAR EL LV ───────────────────────────────────────────────────
# -L 20G: tamaño inicial. -n datos: nombre del LV.
lvcreate -L 20G -n datos appdata

# El kernel ya expone el dispositivo en ambas rutas (son enlaces al mismo nodo):
#   /dev/appdata/datos
#   /dev/mapper/appdata-datos
ls -l /dev/appdata/datos

# ── 4. FORMATEAR Y MONTAR ────────────────────────────────────────────
mkfs.ext4 /dev/appdata/datos
mkdir -p /srv/appdata

# Entrada en fstab usando el dispositivo LVM directamente
echo '/dev/appdata/datos  /srv/appdata  ext4  defaults  0 2' >> /etc/fstab
mount /srv/appdata

df -h /srv/appdata   # confirma montaje y espacio disponible

# ── 5. AMPLIAR EL VG CON EL SEGUNDO DISCO ────────────────────────────
# Añadir /dev/sdc al VG existente; no hay downtime.
vgextend appdata /dev/sdc

vgdisplay appdata   # "Free PE / Size" ahora incluye el espacio de sdc

# ── 6. EXTENDER EL LV EN CALIENTE ────────────────────────────────────
# Añadir 30G más al LV (el filesystem sigue montado).
lvextend -L +30G /dev/appdata/datos

# lvextend solo amplía el dispositivo de bloque; el filesystem aún no sabe.
# resize2fs lee el nuevo tamaño del dispositivo y expande la estructura ext4.
# Sin -p lvextend ya devolvió el control; resize2fs no necesita -f aquí.
resize2fs /dev/appdata/datos

df -h /srv/appdata   # el filesystem ahora muestra ~50G

# ── 7. SNAPSHOT ANTES DEL DESPLIEGUE ─────────────────────────────────
# -s: snapshot. -L 2G: espacio para el CoW (copy-on-write).
# El snapshot captura el estado exacto del LV en este instante.
# 2G es suficiente si el despliegue no escribe más de 2G de bloques nuevos
# antes de que lo elimines; si se llena, el snapshot se invalida.
lvcreate -L 2G -s -n datos_snap /dev/appdata/datos

lvdisplay /dev/appdata/datos_snap   # "LV snapshot status: active destination for datos"

# Si el despliegue falla, revertir:
#   lvconvert --merge /dev/appdata/datos_snap
# (requiere desmontar el LV origen o reiniciar si está en uso)

# Si el despliegue va bien, eliminar el snapshot para liberar espacio:
lvremove /dev/appdata/datos_snap

Qué está pasando en cada decisión

pvcreate sobre el disco entero escribe una cabecera de 512 bytes con un UUID único y los metadatos del PV. Usar el dispositivo sin particionar (/dev/sdb) en lugar de /dev/sdb1 es perfectamente soportado y elimina una capa innecesaria; la única razón para usar una partición es coexistencia con otro sistema de arranque o dual-boot.

vgcreate appdata /dev/sdb establece el PE size (4 MiB por defecto). Todos los LVs creados en este VG asignan espacio en múltiplos de 4 MiB. Si cambias el PE size con -s en el momento de crear el VG, afecta al tamaño máximo del LV soportado y a la granularidad de los snapshots; para la mayoría de cargas, el defecto es correcto.

vgextend appdata /dev/sdc añade los Physical Extents de /dev/sdc al pool del VG sin tocar ningún LV existente. El LV datos sigue mapeado exactamente a los mismos PEs de /dev/sdb; el espacio de /dev/sdc está libre para cualquier lvcreate o lvextend posterior. Si quisieras que LVM distribuyera los datos del LV entre los dos discos por rendimiento, tendrías que usar --type striped en el momento de crear o extender, lo cual es una decisión diferente con sus propias implicaciones de resiliencia.

El orden lvextendresize2fs es crítico. lvextend opera sobre el dispositivo de bloque; el filesystem ni se entera. resize2fs lee el nuevo tamaño del bloque device y extiende las estructuras internas de ext4. Si ejecutas resize2fs primero, fallará porque el filesystem ya ocupa todo el espacio disponible. Si ejecutas solo lvextend y olvidas resize2fs, df seguirá mostrando el tamaño anterior aunque el dispositivo sea más grande.

[Ubuntu]: En Ubuntu, lvextend -r -L +30G /dev/appdata/datos combina el resize del filesystem en el mismo comando (-r llama a resize2fs internamente). En Debian el flag -r también existe en las versiones modernas de lvm2, pero la secuencia explícita hace más visible lo que ocurre en cada capa.

El snapshot con -s -L 2G funciona mediante Copy-on-Write: cuando el LV origen escribe un bloque, LVM copia el bloque original al snapshot antes de sobreescribirlo. El snapshot solo almacena los bloques que han cambiado desde su creación. Si el espacio de CoW (2 GiB en el ejemplo) se agota antes de que elimines el snapshot, LVM lo marca como inválido y lo descarta automáticamente. Dimensionar el snapshot requiere estimar cuántos datos únicos va a modificar el despliegue; para despliegues pequeños, 10-20 % del LV origen suele ser suficiente.

lvdisplay, vgdisplay y pvdisplay son los comandos de diagnóstico fundamentales. Para una vista compacta y scriptable, pvs, vgs y lvs devuelven exactamente los mismos datos en formato tabular de una línea por objeto, lo cual es mucho más útil en monitoring y en pipes.

89

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio