Al utilizar máquinas virtuales, puede ser frecuente la necesidad de redimensionar un disco. Esto se debe a que la mayoría de las tecnologías de virtualización otorgan la flexibilidad de asignar recursos de manera dinámica. Esta capacidad de modificar tamaños de discos de manera simple y rápida, hace que los administradores de sistemas sean un tanto "austeros" al momento de asignar recursos. Por ello surge luego la necesidad de aumentar tamaños de disco, memoria, etc. Más aún cuando se trata de sistemas pasando de su fase de desarrollo/testing hacia producción.

Ahora bien, lo que ocurre cuando se modifica el hardware de una máquina virtual (algo que no es tan simple con hardware físico, ya que no es posible modificar el tamaño de un disco duro, por ejemplo) es que generalmente se debe reiniciar el sistema operativo guest, para que éste "vea" los cambios (detecte la modificación o el nuevo hardware). Sin embargo, a veces es posible lograr que el núcleo del sistema operativo guest (en este caso Linux) detecte el cambio realizado, forzando un reescaneo (rescan) del hardware en cuestión (en este caso un disco SCSI). Esto evita la necesidad de reiniciar el sistema operativo guest, con lo que ello implica, especialmente en sistemas en producción.

Este artículo explica cómo detectar un cambio en un disco SCSI en Linux sin necesidad de reiniciar el sistema.



En este caso la tecnología de virtualización subyacente es VMware. Luego de haber redimensionado uno de los discos SCSI (correspondiente al dispositivo /dev/sdb) de una máquina virtual, el sistema operativo guest (Linux) no detecta este cambio de manera automática. Se ha pasado de 5 a 10 GB, aunque Linux aún ve al disco con su tamaño original (5368 MB):

root@debian:~# fdisk -l /dev/sdb

Disk /dev/sdb: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 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

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

De acuerdo a los mensajes de inicio del kernel Linux (salida de dmesg), se observa que se trata efectivamente de un disco SCSI:

root@debian:~# grep "SCSI" /var/log/dmesg
[    1.024323] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[    1.688609] SCSI subsystem initialized
[    2.253201] scsi target2:0:0: FAST-40 WIDE SCSI 80.0 MB/s ST (25 ns, offset 127)
[    2.254588] scsi target2:0:1: FAST-40 WIDE SCSI 80.0 MB/s ST (25 ns, offset 127)
[    2.271620] sd 2:0:1:0: [sdb] Attached SCSI disk
[    2.274328] sd 2:0:0:0: [sda] Attached SCSI disk
[    2.536297] VMware PVSCSI driver - version 1.0.1.0-k

Además se desprende que el disco /dev/sdb corresponde con el dispositivo SCSI 2:0:1:0.

root@debian:~# ll /sys/class/scsi_device/
total 0
drwxr-xr-x  2 root root 0 Jul 12 09:12 .
drwxr-xr-x 31 root root 0 Jul 12 09:00 ..
lrwxrwxrwx  1 root root 0 Jul 12 09:12 2:0:0:0 -> ../../devices/pci0000:00/0000:00:10.0/host2/target2:0:0/2:0:0:0/scsi_device/2:0:0:0
lrwxrwxrwx  1 root root 0 Jul 12 09:12 2:0:1:0 -> ../../devices/pci0000:00/0000:00:10.0/host2/target2:0:1/2:0:1:0/scsi_device/2:0:1:0

El kernel Linux permite reescanear un disco SCSI a través del filesystem /sys, el cual exporta estructuras de datos del kernel, a través de la interfaz device/rescan dentro de cada dispositivo SCSI:

root@debian:~# echo 1 > /sys/class/scsi_device/2\:0\:1\:0/device/rescan

Simplemente reescaneando el dispositivo SCSI se detecta el nuevo tamaño del disco rígido de la máquina virtual, sin necesidad de reiniciar el sistema operativo:

root@debian:~# fdisk -l /dev/sdb

Disk /dev/sdb: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 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

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

El resto sigue tal como he explicado anteriormente en mi artículo Redimensionar volúmenes físicos, volúmenes lógicos y grupos en LVM.

Primero es necesario detectar el cambio del volumen físico LVM:

root@debian:~# pvs
  PV         VG   Fmt  Attr PSize PFree
  /dev/sda5  raiz lvm2 a-   4.76g    0 
  /dev/sdb   apps lvm2 a-   5.00g    0 
root@debian:~# pvresize /dev/sdb
  Physical volume "/dev/sdb" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized
root@debian:~# pvs
  PV         VG   Fmt  Attr PSize  PFree
  /dev/sda5  raiz lvm2 a-    4.76g    0 
  /dev/sdb   apps lvm2 a-   10.00g 5.00g
root@debian:~# vgs
  VG   #PV #LV #SN Attr   VSize  VFree
  raiz   1   4   0 wz--n-  4.76g    0 
  apps   1   1   0 wz--n- 10.00g 5.00g

De esta forma se redimensiona el volumen físico /dev/sdb asociado al grupo "apps".

Luego es necesario expandir el volumen lógico deseado, utilizando el nuevo espacio disponible en el volumen físico redimensionado en el paso anterior. En este caso se desea redimensionar el volumen lógico "usrlocal" perteneciente al grupo "apps":

root@debian:~# lvs
  LV               VG              Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  raiz             raiz -wi-ao   2.17g                                      
  swap             raiz -wi-ao 732.00m                                      
  tmp              raiz -wi-ao 488.00m                                      
  var              raiz -wi-ao   1.39g                                      
  usrlocal         apps -wi-ao   5.00g                                      
root@debian:~# lvextend -l+100%FREE /dev/apps/usrlocal
  Extending logical volume usrlocal to 10.00 GiB
  Logical volume usrlocal successfully resized
root@debian:~# lvs
  LV               VG              Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  raiz             raiz -wi-ao   2.17g                                      
  swap             raiz -wi-ao 732.00m                                      
  tmp              raiz -wi-ao 488.00m                                      
  var              raiz -wi-ao   1.39g                                      
  usrlocal         apps -wi-ao  10.00g                                      

Finalmente, es necesario expandir el sistema de archivos del volumen físico (partición). Esta tarea requiere desmontar el sistema de archivos:

root@debian:~# mount | grep apps
/dev/mapper/apps-usrlocal on /usr/local type ext4 (rw,nosuid,nodev,noatime)

Se observa que el dispositivo (partición) /dev/mapper/apps-usrlocal está montado en /usr/local. Antes de desmontarlo, es necesario determinar si algún proceso posee archivos abiertos dentro de dicho filesystem:

root@debian:~# lsof | grep /usr/local | cut -d' ' -f1 | sort | uniq
postgres

Si existen archivos abiertos lógicamente no es posible desmontarlo:

root@debian:~# umount /usr/local
umount: /usr/local: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))

Tal como se observa en la salida de lsof, se debe detener el servicio postgres (servidor de bases de datos relacionales).

En este caso en particular, al tratarse de un servidor de bases de datos, es recomendable antes detener el/los servicio/s o aplicaciones que lo utilizan para evitar inconsistencias en los datos (por ejemplo Apache, Nginx, etc.):

# service apache2 stop
# service postgresql stop

De esta forma es posible desmontar y redimensionar el sistema de archivos:

root@debian:~# umount /usr/local
root@debian:~# resize2fs /dev/mapper/apps-usrlocal
resize2fs 1.41.12 (17-May-2010)
Please run 'e2fsck -f /dev/mapper/apps-usrlocal' first.

La expansión de un filesystem de tipo ext2/ext3/ext4 requiere previamente una verificación:

root@debian:~# e2fsck -f /dev/mapper/apps-usrlocals
e2fsck 1.41.12 (17-May-2010)
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
/dev/mapper/apps-usrlocal: 45456/327680 files (0.9% non-contiguous), 1160696/1309696 blocks
root@debian:~# resize2fs /dev/mapper/apps-usrlocal 
resize2fs 1.41.12 (17-May-2010)
Resizing the filesystem on /dev/mapper/apps-usrlocal to 2620416 (4k) blocks.
The filesystem on /dev/mapper/apps-usrlocal is now 2620416 blocks long.

Finalmente, montar el sistema de archivos redimensionado y levantar los servicios afectados:

root@debian:~# mount -a
# service postgresql start
# service apache2 start

Así se logra detectar el cambio de tamaño en el disco, redimensionar el volúmen físico y lógico, y expandir el sistema de archivos deseado, todo sin necesidad de reiniciar el sistema operativo:

root@debian:~# df -h /usr/local/
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/apps-usrlocal 9.9G  4.4G  5.0G  47% /usr/local

Sólo se requiere desmontar el sistema de archivos, pero el downtime es de apenas unos segundos (dependiendo del tamaño del sistema de archivos a redimensionar) en comparación al tiempo que requiere reiniciar el sistema operativo guest. Recuerden que, para un SysAdmin, reiniciar el sistema operativo es uno de los peores pecados, algo tan malo como pegarle a la madre.

Referencias

man fdisk
man dmesg
man lvm
man pvs
man pvresize
man vgs
man lvs
man lvextend
man mount
man lsof
man umount
man resize2fs
man e2fsck
man df

LWN.net - detect online disk resize

sysfs - _The_ filesystem for exporting kernel objects


Tal vez pueda interesarte


Compartí este artículo