Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Backups con RSYNC y ZFS

Última Actualización: 28 de octubre de 2009 - Miércoles

Llevo unos cuantos años usando "rdiff-backup" para hacer la copia diaria de mis sistemas contra mi servidor de backup. En general la experiencia ha sido buena, pero "rdiff-backup" tiene una serie de problemas serios:

  • En rendimiento cuando el servidor de backup y el servidor a copiar están en diferentes redes (especialmente, si hay una WAN por medio) es muy malo. Es decir, la latencia de la red le hace mucha pupa.

  • Si por cualquier causa un volcado se aborta a mitad de proceso (disco lleno, control+c, reinicio de unos de los extremos, etc), el backup puede corromperse y es necesario eliminarlo por completo, incluyendo todos los históricos, y empezar de nuevo.

  • Si el backup se interrumpe por cualquier causa, si tenemos suerte y no se ha corrompido (ver punto anterior), "rdiff-backup" hará un "rollback" de los cambios al nivel del backup anterior que se haya completado con éxito. Este proceso puede ser muy lento. Luego, empezará el volcado desde el principio, sin tener en cuenta lo ya descargado. Es decir, cortar un backup no solo supone riesgo de corrupción, sino que, en el mejor de los casos, el programa perderá bastante tiempo borrando el backup incompleto, para empezar luego de nuevo desde cero.

  • Borrar versiones antiguas de un backup puede ser un proceso bastante lento.

  • Recuperar una versión antigua de un fichero, no la del último backup, puede ser un proceso lento.

  • Las versiones se deben borrar por orden. Es decir, no podemos borrar la versión "X" si existe una versión "X-1". Por ejemplo, no podemos realizar un backup diario y, a medida que envejecen, ir eliminando versiones aisladas hasta dejar solo una a la semana y luego una al mes, por ejemplo.

  • Ver lo que ocupa cada histórico (versión) de un backup es un proceso lento.

Debido a estos problemas, actualmente restrinjo "rdiff-backup" a los backups diarios, de directorios seleccionados (no discos completos, aunque son backups bastante extensivos). Esto es así porque esos backups se usan como protección contra errores, pero no nos interesan para conservar de forma indefinida, así que borrarlos de vez en cuando por alguna inconsistencia no me supone ningún problema.

Tengo un segundo nivel de backup, realizado mensualmente, usando "rsync" y la funcionalidad añadida recientemente de "--link-dest". Básicamente con esa opción, creamos un segundo directorio en el que los ficheros que no hayan cambiado respecto a otro directorio simplemente se enlazan con un "hardlink".

Algunas ventajas son:

  • "rsync", sobre todo las versiones recientes, funcionan bastante bien incluso con redes con latencia.

  • Si un backup se corta, no afecta al resto en absoluto.

  • Si reiniciamos un backup parcial, sigue donde lo había dejado.

  • Podemos borrar cualquier versión, sin afectar al resto. Así, podemos usar cualquier criterio de conservación de versiones.

  • Recuperar una versión antigua de un fichero es inmediato. Basta con ir al directorio que se corresponde a la versión que nos interesa.

  • Es posible borrar ficheros concretos de versiones antiguas. Por ejemplo, si necesitamos espacio en el disco de backup, podemos borrar los ficheros de correo de una versión antigua, sin afectar al resto del contenido de esa versión.

Pero este sistema tiene también sus desventajas:

  • No tenemos ni idea de cuánto ocupa cada versión. Por eso es difícil decidir qué borrar cuando se llena el disco.

  • El borrado de una versión es un proceso bastante lento.

  • Crear una nueva versión consume bastante ancho de banda de disco, aunque no haya cambios, ya que hay que crear enlaces "hard" a todos los ficheros, aunque no haya cambiado ninguno.

  • Si un fichero cambia, se graba una versión completa entera. Es decir, si un fichero de una base de datos de 10 gigas se cambia en un byte, se crea en el disco un fichero nuevo de 10 gigas, exactamente igual al antiguo excepto en ese byte cambiado.

Además, todos estos sistemas de backup requieren revisar el disco duro entero, aunque no haya habido ningún cambio.

Mi ideal sería utilizar ZFS de forma nativa, ya que una de sus incontables ventajas es su capacidad para identificar instantáneamente los cambios realizados desde la última copia de seguridad, independientemente del volumen de datos de los discos duros. En un mundo de discos duros de terabytes, esta funcionalidad es impagable.

Lamentablemente tengo muchas máquinas que no trabajan bajo Solaris, y necesito acomodarlas en mi sistema de backup. Así que hace unos meses decidí emplear una estrategia mixta: rsync junto a ZFS. La idea es la siguiente:

  • Por cada backup que nos interesa, creamos un "dataset" en un "pool" ZFS.

  • Hacemos un "rsync" al "dataset". Es un "rsync" normal, no con la opción "--link-dest". Usamos la opción "--inplace", eso sí.

    Normalmente "rsync", cuando detecta que un fichero ha cambiado, empieza a descargar la versión nueva de forma incremental, usando para ello el fichero ya existente. Pero dicha versión nueva se descarga con otro nombre y, cuando la descarga se ha completado, se renombra para ocupar el lugar del fichero original.

    Usando "--inplace", le decimos a "rsync" que queremos que sobreescriba el fichero original, en vez de crear un fichero nuevo y renombrarlo al final. De esta forma aprovechamos mucho mejor la potencia de los "snapshots" de ZFS.

  • Si el backup se corta o da cualquier error, lo repetimos otra vez. Gracias a "rsync", el backup seguirá donde iba, sin necesitar empezar desde el principio.

  • Una vez que un backup se ha completado con éxito, hacemos un "snapshot" del "dataset". De esa forma guardamos la versión en un "dataset" de solo-lectura.

Las ventajas son muchas:

  • Estamos usando "rsync", con todas sus ventajas: si reiniciamos un backup parcial sigue donde iba, buen rendimiento en redes con latencia, si un fichero cambia se regenera incrementalmente aprovechando lo posible de la versión vieja del fichero que ya tenemos, etc.

  • Ver lo que ocupa cada "snapshot" ZFS es una operación instantanea.

  • Eliminar un "snapshot" ZFS es una operación rápida, con un tiempo proporcional al volumen de datos cambiados, no al volumen de datos en sí.

  • Se puede borrar cualquier "snapshot" ZFS, en cualquier orden. Osea, podemos mantener los que nos interesan.

  • Los "snapshots" ZFS son "solo lectura", así que podemos acceder a ellos sin miedo a alterarlos de forma inadvertida.

  • Gracias al uso de "snapshots" ZFS y a la opción "--inplace" de RSYNC, la ocupación de cada "snapshopt" se corresponde con el volumen de cambios reales, no con el tamaño de los datos o con el número de ficheros que hayan cambiado. Al menos si el cambio está alineado en un bloque (por ejemplo, bases de datos) o el cambio se localiza al final de un fichero (un "append" a un log, por ejemplo).

  • Si usamos compresión en el "dataset", estamos comprimiendo los datos de forma transparente. Si estamos volcando datos no comprimibles (por ejemplo, imágenes JPEG) y no queremos quemar CPU intentando comprimir sin éxito, podemos configurar ese "dataset" concreto para que no se realice compresión.

  • Al ser ZFS, podemos crear tantos "datasets" como deseemos, de forma dinámica y en cualquier momento.

  • Si un fichero no cambia, no se toca el disco duro de backup. Con el uso anterior de "rsync" con la opción de "--link-dest", aunque un fichero no cambie, hay que crear un enlace "hard" al mismo. Y hay que recrear la estructura de directorios en sí. Eso lleva tiempo y espacio (poco) de disco. Con "--inplace" nos ahorramos ese trabajo y ese espacio.

Algunas desventajas son:

  • Estamos usando ZFS, así que necesitas un sistema que lo soporte. Actualmente sería Solaris, OpenSolaris o un *BSD moderno.

  • En este momento la opción "--inplace" es incompatible con ficheros "sparse". Es decir, los ficheros "sparse" se "expanden" a su tamaño real. Esto no tiene porque ser un problema, ya que se suele tratar de ficheros poco frecuentes y, además, esos ceros "implícitos" se comprimen muy bien con la compresión nativa de ZFS.

  • Dado que los "snapshot" ZFS son "solo lectura", no es posible borrar versiones viejas de ficheros grandes, de forma aislada. Pero dado que crear "datasets" es simple y se puede hacer en cualquier momento, el enfoque más lógico sería que esos ficheros con una política de conservación diferente fuesen a otro "dataset" cuyos "snapshots" se pueden borrar con otros criterios.

  • Al contrario que usando comandos como "zfs send", usar "rsync" supone tener que revisar todo el disco duro, aunque no haya cambios. Es un problema comparado con "zfs send", pero algo inherente a cualquier sistema de backup "normal" que no use los detalles internos de ZFS.

  • Al contrario que "ZFS send", "rsync" no es capaz de detectar que un fichero o directorio se ha movido o cambiado de nombre. Es decir, se volverá a volcar. Ésto ocurre con todos los sistemas de backup "normales". No pasa con "ZFS send", pero no lo puedo usar porque tengo máquinas no ZFS integradas con mi sistema de backup.

Ejemplo

En mi backup mensual tengo un disco externo USB, que está desconectado y en un cajón de mi casa (por si cae un rayo, o hay un incendio o lo que sea). Una vez al mes lo traigo a la oficina (con cuidado) y lo enchufo a mi servidor de backup Solaris. Lo monto como

[root@tesalia /]# zpool import
  pool: backup
    id: 15905228473802620720
 state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:

        backup      ONLINE
          c3t0d0    ONLINE
[root@tesalia /]# zpool import backup

Eso me crea un directorio "/backup" en mi jerarquía de ficheros. Seguidamente ejecuto los scripts de backup mensuales para mis máquinas. Por ejemplo, el script de mi máquina personal es:

rsync --numeric-ids -a -H --inplace --delete --delete-excluded --stats --progress -v --itemize-changes \
      --rsync-path=/usr/local/bin/rsync \
      --exclude "/proc/**" \
      --exclude "/sys/**" \
      --exclude "/media/*/**" \
      --exclude "/tmp/**" \
      --exclude "/home/jcea/.thumbnails/**" \
      --exclude "/home/jcea/.googleearth/Cache/*" \
      --exclude "/home/jcea/.mozilla/firefox/**/Cache/*" \
      --exclude "/home/jcea/mnt/particion_1/k3b_image.iso" \
      --exclude "/home/jcea/mnt/particion_1/*.ecc" \
      --exclude "/home/jcea/mnt/amule/**" \
      --exclude "/home/jcea/mnt/Yolco/**" \
      --exclude "/home/jcea/mnt/Cólquide/**" \
      --exclude "/home/jcea/mnt/Tesalia/**" \
      --exclude "/var/tmp/**" \
      / SERVIDOR.BACKUP:/backup/castor/

Esto sincroniza mi disco duro, salvo unos directorios que no me interesan, en el directorio "/backup/castor" del servidor (en realidad, un "dataset"), que se corresponde al disco duro externo. Ese directorio está compuesto, además, por diferentes "datasets": sistema, mi "home", el directorio de imágenes de disco de "virtualBox" y mi directorio de correo. De esta forma, manteniendo "datasets" separados, puedo borrar "snapshots" viejos de mi correo, manteniendo en cambio las imágenes mensuales de "VirtualBox", por ejemplo (que solo ocupan lo que hayan cambiado).

Tener "datasets" separados me permite también, por ejemplo, el desactivar la compresión en el "dataset" de imágenes "VirtualBox", ya que se comprime poco y mal y no quiero consumir CPU para nada. En cambio la compresión es muy útil en mi correo electrónico, por ejemplo. ¡¡Usa varios "datasets" según su perfil de uso y tus necesidades de conservación!!.

Una vez que el backup se ha completado (si se corta o lo que sea, se puede relanzar sin problemas), hacemos un "snapshot" ZFS en el sistema con:

# zfs snapshot -r backup/castor@20091028

Cuando se nos llena el disco duro y hay que borrar "snapshots" antiguos, tiramos de nuestra política particular. En mi caso los backups recientes me interesa quedarme con uno al mes, y los antiguos con uno cada tres meses o, incluso, con uno al año. Por supuesto, cada "dataset" es un caso distinto. No hace falta conservar un histórico detallado del correo electrónico si eres de los que no borra nada, porque en cada versión nueva se mantendrán también los mensajes anteriores.

A la hora de decidir qué backup eliminar, puede ser muy conveniente ver cuánto ocupa cada uno. Lo normal es borrar los más grandes:

# zfs list -r -o name,compressratio,used -s used backup | grep -i @

Una vez que completamos todos los backups, desmontamos/exportamos el disco de backup, lo desenchufamos y nos lo llevamos a casa de nuevo.

# zpool export backup

A la hora de recuperar ficheros puntuales, basta con enchufar el disco duro, importar el "pool" y acceder al "snapshot" ZFS que nos interesa.

Si lo que queremos es recuperar particiones enteras, podemos seguir las instrucciones de indicadas hace tres años.

Migración de los backups antiguos

Como ya he dicho, tengo dos sistemas de backup (en realidad más, pero no son relevantes): diario y mensual. El diario va con "rdiff-backup" y conservo el último par de semanas o así. El mensual iba antes con "rsync" con la opción de "--link-dest", y ahora va con "rsync" con "--inplace" y ZFS. Me interesa migrar estos backups antiguos al sistema nuevo.

El disco de backup mide 500 GB, y me acabo de poner un disco duro de 750 GB en mi máquina, así que puedo copiar los datos de un lado a otro sin problema. Pero copiar 500 gigas en cientos de millones de ficheros enlazados con enlaces "hard" es un proceso que consume mucho tiempo y memoria (el "rsync" debe mantener los inodes en memoria, para localizar los enlaces "hard"), así que decido hacerlo de otra manera:

En vez de copiar los ficheros en el backup externo a mi disco duro interno mediante "cp" o similar (perdiendo la información de enlaces "hard" y expandiendo los datos varios órdenes de magnitud) o mediante "rsync" (que mantiene los enlaces "hard" a costa de gastar memoria para llevar "la cuenta" de los mismos), decido -aprovechando que uso LVM (Logical Volume Manager) en mi Linux- crear un nuevo volumen lógico y copiar el disco duro externo sector a sector. Esto es mucho más rápido que leer fichero a fichero, y no pierde ninguna información:

castor:/home/jcea/mnt/rdiff-backup # fdisk /dev/sdb

The number of cylinders for this disk is set to 60563.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/sdb: 500.1 GB, 500107862016 bytes
256 heads, 63 sectors/track, 60563 cylinders
Units = cylinders of 16128 * 512 = 8257536 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       60563   488380000+  83  Linux

Command (m for help): q

castor:/home/jcea/mnt/rdiff-backup # lvcreate -L510G --name backup LVM2
  Logical volume "backup" created

castor:/home/jcea/mnt/rdiff-backup # dd if=/dev/sdb1 of=/dev/LVM2/backup bs=65536
7630937+1 records in
7630937+1 records out
500101120512 bytes (500 GB) copied, 26824.6 seconds, 18.6 MB/s

castor:/home/jcea/mnt/rdiff-backup # mount /dev/LVM2/backup /mnt
castor:/home/jcea/mnt/rdiff-backup # cd /mnt/snapshots/
castor:/mnt/snapshots # dir
total 73
drwxr-xr-x  72 jcea users 2432 Mar 17 19:10 .
drwxrwxrwx   5 root root   160 Mar 17 17:33 ..
drwxr-xr-x  22 root root   584 Apr  8  2007 20070410-castor
drwxr-xr-x  25 root root   752 Apr  9  2007 20070410-colquide
drwxr-xr-x  47 root root  2272 Mar 26  2007 20070410-tesalia
drwxr-xr-x  22 root root   648 Jan 18  2007 20070410-yolco
drwxr-xr-x  22 root root   584 May 28  2007 20070601-castor
drwxr-xr-x  24 root root   728 May 29  2007 20070601-colquide
drwxr-xr-x  50 root root  2264 May 30  2007 20070601-tesalia
drwxr-xr-x  22 root root   648 May 31  2007 20070601-yolco
drwxr-xr-x  22 root root   584 Jun 26  2007 20070701-castor
drwxr-xr-x  24 root root   728 Jun 23  2007 20070701-colquide
drwxr-xr-x  49 root root  2264 Jun 28  2007 20070701-tesalia
drwxr-xr-x  22 root root   648 Jun 22  2007 20070701-yolco
drwxr-xr-x  22 root root   584 Sep  3  2007 20070903-castor
drwxr-xr-x  24 root root   728 Aug  6  2007 20070903-colquide
drwxr-xr-x  49 root root  2304 Jul 31  2007 20070903-tesalia
drwxr-xr-x  22 root root   648 Sep  3  2007 20070903-yolco
drwxr-xr-x  22 root root   584 Oct  1  2007 20071001-castor
drwxr-xr-x  24 root root   728 Aug  6  2007 20071001-colquide
drwxr-xr-x  49 root root  2552 Sep 28  2007 20071001-tesalia
drwxr-xr-x  22 root root   648 Sep  3  2007 20071001-yolco
drwxr-xr-x  22 root root   584 Jan  2  2008 20080103-castor
drwxr-xr-x  24 root root   728 Oct 16  2007 20080103-colquide
drwxr-xr-x  50 root root  2656 Dec 28  2007 20080103-tesalia
drwxr-xr-x  22 root root   648 Dec  4  2007 20080103-yolco
drwxr-xr-x  22 root root   584 Jan 25  2008 20080201-castor
drwxr-xr-x  24 root root   728 Jan 10  2008 20080201-colquide
drwxr-xr-x  51 root root  2704 Feb  1  2008 20080201-tesalia
drwxr-xr-x  22 root root   648 Jan  3  2008 20080201-yolco
drwxr-xr-x  22 root root   584 Feb 13  2008 20080301-castor
drwxr-xr-x  24 root root   728 Jan 10  2008 20080301-colquide
drwxr-xr-x  52 root root  2656 Feb 28  2008 20080301-tesalia
drwxr-xr-x  22 root root   648 Jan  3  2008 20080301-yolco
drwxr-xr-x  22 root root   584 Mar 24  2008 20080401-castor
drwxr-xr-x  25 root root   760 Mar 16  2008 20080401-colquide
drwxr-xr-x  52 root root  2824 Mar 31  2008 20080401-tesalia
drwxr-xr-x  23 root root   680 Mar 15  2008 20080401-yolco
drwxr-xr-x  22 root root   584 Apr  4  2008 20080505-castor
drwxr-xr-x  25 root root   760 Mar 16  2008 20080505-colquide
drwxr-xr-x  52 root root  2880 May  1  2008 20080505-tesalia
drwxr-xr-x  23 root root   680 Mar 15  2008 20080505-yolco
drwxr-xr-x  22 root root   584 Apr  4  2008 20080602-castor
drwxr-xr-x  25 root root   760 May 14  2008 20080602-colquide
drwxr-xr-x  54 root root  2896 Jun  1  2008 20080602-tesalia
drwxr-xr-x  23 root root   680 May 14  2008 20080602-yolco
drwxr-xr-x  22 root root   584 Jun 25  2008 20080701-castor
drwxr-xr-x  25 root root   736 Jun 23  2008 20080701-colquide
drwxr-xr-x  54 root root  2992 Jun 30  2008 20080701-tesalia
drwxr-xr-x  23 root root   680 Jun 12  2008 20080701-yolco
drwxr-xr-x  22 root root   584 Sep  1  2008 20080905-castor
drwxr-xr-x  25 root root   736 Aug  7  2008 20080905-colquide
drwxr-xr-x  54 root root  3080 Sep  3  2008 20080905-tesalia
drwxr-xr-x  23 root root   680 Sep  1  2008 20080905-yolco
drwxr-xr-x  22 root root   584 Nov  4 19:47 20081104-castor
drwxr-xr-x  25 root root   736 Oct  6 21:43 20081104-colquide
drwxr-xr-x  54 root root  3408 Nov  4 20:54 20081104-tesalia
drwxr-xr-x  23 root root   680 Oct  2 22:43 20081104-yolco
drwxr-xr-x  22 root root   584 Nov  4 19:47 20081201-castor
drwxr-xr-x  25 root root   736 Oct  6 21:43 20081201-colquide
drwxr-xr-x  56 root root  3552 Nov 24 18:04 20081201-tesalia
drwxr-xr-x  23 root root   680 Oct  2 22:43 20081201-yolco
drwxr-xr-x  22 root root   584 Dec  9 00:50 20090102-castor
drwxr-xr-x  25 root root   736 Dec 12 01:13 20090102-colquide
drwxr-xr-x  56 root root  3552 Dec 29 18:37 20090102-tesalia
drwxr-xr-x  23 root root   680 Dec 12 02:26 20090102-yolco
drwxr-xr-x  22 root root   584 Dec  9 00:50 20090202-castor
drwxr-xr-x  25 root root   736 Dec 12 01:13 20090202-colquide
drwxr-xr-x  56 root root  3552 Feb  2 17:44 20090202-tesalia
drwxr-xr-x  23 root root   680 Dec 12 02:26 20090202-yolco

Aquí podemos ver que comprobamos el tamaño del disco duro externo, seguidamente creamos un volumen lógico lo bastante grande como para contenerlo, y luego copiamos el disco "a lo bestia", sector a sector. Por último comprobamos que, efectivamente, los datos están en el disco duro.

A continuación desenchufamos el disco duro externo de backup y lo conectamos al servidor de backup. Hay que localizarlo en sus USBs:

[root@tesalia z2]# cfgadm
Ap_Id                          Type         Receptacle   Occupant     Condition
sata0/0::dsk/c1d0              disk         connected    configured   ok
sata0/1::dsk/c5t1d0            disk         connected    configured   ok
sata1/0                        sata-port    empty        unconfigured ok
sata1/1                        sata-port    empty        unconfigured ok
usb0/1                         unknown      empty        unconfigured ok
usb0/2                         unknown      empty        unconfigured ok
usb0/3                         unknown      empty        unconfigured ok
usb0/4                         unknown      empty        unconfigured ok
usb0/5                         unknown      empty        unconfigured ok
usb0/6                         unknown      empty        unconfigured ok
usb0/7                         unknown      empty        unconfigured ok
usb0/8                         unknown      empty        unconfigured ok
usb1/1                         unknown      empty        unconfigured ok
usb1/2                         unknown      empty        unconfigured ok
usb1/3                         unknown      empty        unconfigured ok
usb1/4                         unknown      empty        unconfigured ok
usb1/5                         unknown      empty        unconfigured ok
usb1/6                         unknown      empty        unconfigured ok
usb1/7                         usb-storage  connected    configured   ok
usb1/8                         unknown      empty        unconfigured ok

[root@tesalia /]# iostat -En
c0t0d0           Soft Errors: 2 Hard Errors: 0 Transport Errors: 0
Vendor: MATSHITA Product: DVD-ROM SR-8178  Revision: PZ16 Serial No:
Size: 0.00GB <0 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 2 Predictive Failure Analysis: 0
c3t0d0           Soft Errors: 2 Hard Errors: 0 Transport Errors: 0
Vendor: ST350063 Product: 0AS              Revision:  Serial No:
Size: 500.11GB <500107862016 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 2 Predictive Failure Analysis: 0
c5t0d0           Soft Errors: 8 Hard Errors: 0 Transport Errors: 0
Vendor: ATA      Product: ST3250823AS      Revision: 3.03 Serial No:
Size: 250.06GB <250059349504 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 8 Predictive Failure Analysis: 0
c5t1d0           Soft Errors: 8 Hard Errors: 0 Transport Errors: 0
Vendor: ATA      Product: WDC WD7500AAKS-0 Revision: 4G30 Serial No:
Size: 750.16GB <750156373504 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 8 Predictive Failure Analysis: 0

[root@tesalia /]# rmformat
Looking for devices...
     1. Logical Node: /dev/rdsk/c0t0d0p0
        Physical Node: /pci@0,0/pci-ide@6/ide@0/sd@0,0
        Connected Device: MATSHITA DVD-ROM SR-8178  PZ16
        Device Type: DVD Reader
     2. Logical Node: /dev/rdsk/c3t0d0p0
        Physical Node: /pci@0,0/pci108e,5348@2,1/storage@7/disk@0,0
        Connected Device: ST350063 0AS
        Device Type: Removable

[root@tesalia /]# zpool create backup c3t0d0
[root@tesalia /]# zpool list backup
NAME     SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
backup   464G    94K   464G     0%  ONLINE  -

[root@tesalia backup]# zfs set compression=gzip-9 backup
[root@tesalia colquide]# zfs set atime=off backup
[root@tesalia colquide]# zfs create backup/reserva_de_espacio-NO_USAR
[root@tesalia colquide]# zfs set reservation=64M backup/reserva_de_espacio-NO_USAR

Localizamos el disco duro externo y creamos el "pool" ZFS "backup" en él. Obviamente estos pasos solo son necesarios la primera vez. Una vez creado el "pool", lo activamos y desactivamos con "zpool import" y "zpool export", y Solaris ya se encarga de buscar el "pool" en cuestión entre todos los discos duros conectados, locales o externos.

Activamos la compresión más agresiva y desactivamos el "atime", que no tiene sentido para backups y que nos permitirá ahorrar algo de espacio (si el "atime" no se modifica, no hace falta guardar una copia en los "snapshots") y de tiempo al hacer el backup (porque no hay que actualizar los "atimes" en el disco duro).

Obsérvese que creo un "dataset" con una reserva de espacio. Esto es así porque ZFS es un sistema de ficheros COW (Copy On Write), y requiere espacio extra (durante un momento) para cosas como borrar un fichero. Es decir, que si tenemos el disco absolutamente lleno y queremos borrar un fichero, no podremos, porque no tenemos espacio para el COW correspondiente. Reservando un poco de espacio (despreciable frente al total) desde el principio, nos despreocupamos de ésto. Es posible que las versiones recientes de ZFS ya no tengan este problema, pero mejor curarse en salud.

A continuación crearíamos los "datasets" correspondientes, en este caso uno por máquina protegida:

[root@tesalia backup]# zfs create backup/tesalia
[root@tesalia backup]# zfs create backup/yolco
[root@tesalia backup]# zfs create backup/colquide

Mi máquina personal es un caso especial, porque me interesa tener diferentes "datasets" con diferentes políticas:

[root@tesalia backup]# zfs create backup/castor
[root@tesalia backup]# zfs create backup/castor/jcea
[root@tesalia backup]# zfs mountpoint=/backup/castor/home/jcea backup/castor/jcea
[root@tesalia backup]# zfs create backup/castor/jcea/correo
[root@tesalia backup]# zfs mountpoint=/backup/castor/home/jcea/.thunderbird backup/castor/jcea/correo
[root@tesalia backup]# zfs create backup/castor/jcea/virtualbox
[root@tesalia backup]# zfs set mountpoint=/backup/castor/home/jcea/mnt/virtualbox backup/castor/jcea/virtualbox
[root@tesalia backup]# zfs set compression=off backup/castor/jcea/virtualbox

Una vez creada la estructura, copiamos los backups viejos, en mi ordenador, al sistema nuevo. Usamos "rsync":

castor:/mnt/snapshots # rsync -a -H --delete --numeric-ids --stats --progress \
                                 --force --rsync-path=/usr/local/bin/rsync \
                                 --exclude rdiff-backup-data --inplace \
                                 20070410-colquide/ SERVIDOR.BACKUP:/backup/colquide/

A medida que vamos moviendo cada versión vieja de los backups, hacemos "snapshot" ZFS en el servidor:

[root@tesalia backup]# zfs snapshot -r backup/colquide@20070410

Una vez que terminamos de mover todos los backups, desmontamos el "pool":

[root@tesalia /]# zpool export backup

En mi máquina destruyo el volumen lógico que contiene el backup histórico que ya hemos convertido:

castor:/ # lvremove /dev/LVM2/backup
Do you really want to remove active logical volume "backup"? [y/n]: y
  Logical volume "backup" successfully removed


Historia

  • 28/oct/09: Primera versión de esta página.



Python Zope ©2009 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS