Cómo clonar un box Linux a Amazon EC2

LINUX TO EC2 CLONATION

Cómo clonar un box Linux a Amazon EC2

Probablemente muchos de los que hayáis leído el título de este artículo habréis pensado: “¿Para qué quiero hacer eso? En EC2 tengo un montón de imágenes preconfiguradas de casi cualquier distro de Linux, así que simplemente lanzo una instancia, instalo lo que necesite, y ya está”.

Se me ocurren varias razones para crear un “clon” (ahora se ha puesto de moda llamar a esto P2V). Cito un par de ellas:

  • Tengo un servidor Linux que llevo años “tuneando” exactamente a mi gusto, he instalado (y configurado) un montón de software (Gnome, NxServer, Samba, compiladores, etc.), así como aplicaciones de mi empresa, bases de datos, etc. A efectos de contingencia ante desastres, necesito un equipo de respaldo en la nube. Me da muchísima pereza tener que volver a instalar y configurar todo desde cero, así que sería estupendo poder generar un clon.
  • Para hacer pruebas, quiero montar un entorno distribuido, o un grid de máquinas idénticas, todo ello en la nube (no quiero comprar hardware simplemente para unas pruebas). Si pudiese preparar una primera máquina con todo lo que necesito, estaría bien exportar la imagen a EC2 y poder generar todas las instancias que me hagan falta.

 

Pues vamos a ver un procedimiento para hacer esto, además utilizando sólo herramientas de código abierto o gratuitas.

Equipo origen

Vamos a partir de un equipo con las siguientes características:

  • Dell PowerEdge R415
  • 2x AMD Opteron 4184 (12 núcleos en total)
  • 32 GB RAM
  • 2x 300 GB discos SAS a 15.000 RPM en RAID1
  • CentOS 6.9
  • Gnome 2.28.2

 

¿Qué vamos a hacer?

Hay varias herramientas para Windows que nos permiten generar y clonar a EC2 una imagen de nuestro sistema. Por desgracia, en el momento en que escribo esto, no existe nada similar para Linux (VMConverter de VMWare hace algo parecido, pero con muchísimas limitaciones, y desde luego no es código abierto), así que el procedimiento va a ser un pelín complicado, en resumen vamos a:

  • Generar una imagen ISO de nuestro sistema, con la parte de nuestros discos que nos interese.
  • Arrancar una máquina virtual en VirtualBox desde la imagen ISO, y restaurarla.
  • Convertir nuestra VM a un formato neutro.
  • Subir la imagen en formato neutro a Amazon S3.
  • Importar la imagen a EC2 en forma de AMI.
  • Y lanzar una instancia de esta AMI.

 

Generar imagen ISO

Para esta fase hemos decidido usar la herramienta “Mondo Rescue”. Es complicadilla de manejar, pero muy potente y versátil. Lo primero que tenemos que hacer es instalarla en nuestra máquina origen. Empezamos creando el repositorio de Mondo (cuidado, a partir de ahora debemos ser root):

# cd /etc/yum.repos.d
# wget ftp://ftp.mondorescue.org/rhel/6/x86_64/mondorescue.repo

(Nótese que hemos escogido el repositorio correspondiente a RedHat 6, que es compatible con CentOS 6. Si tuviésemos otra versión de Linux, utilizaríamos el repositorio correspondiente).

A continuación, instalamos “mondo” y todas sus dependencias (yum las resuelve en automático):

# yum install mondo

Si todo ha ido bien, y antes de generar la imagen ISO, hay que realizar algunas tareas previas:

Crear (si no existe) el directorio donde se van a generar las imágenes. En nuestro caso “/home/sysimg”.

Nuestro equipo utiliza discos SAS (Serial Attached Scsi), mientras que, probablemente, el destino use SATA o AHCI. Por esta razón, debemos “forzar” a mondo para que incluya los drivers requeridos. Para ello, editamos el archivo “/usr/sbin/mindi”, localizamos una línea que comienza con “FORCE_MODS” y la cambiamos del siguiente modo:

FORCE_MODS=”ahci mptsas mptspi”

Ahora ya podemos ejecutar el backup. Este es un ejemplo del comando a ejecutar (cuidado, es una sola línea):

# nohup mondoarchive -z -O -V -N -G -i -s 8960m -l GRUB -d /home/sysimg -I / -E "/home/comunytek|/home/sysimg" -9 <&- >mondo.log 2>&1 &

Como se puede ver, hemos ejecutado el comando en background, dado que tarda un par de horas. Si queremos ir viendo cómo progresa, podemos entrar:

# tail -f mondo.log

Si alguien está interesado en los detalles del comando “mondoarchive”, está descrito en el siguiente link:

http://www.mondorescue.org/docs/mondorescue-howto.html

La mayor parte de las opciones que hemos usado son casi autoexplicativas, pero menciono algunas que son importantes:

-z: Fuerza a mondo a incluir los packages necesarios para restaurar SELinux.

-N: No incluye en el backup ningún mount NFS.

-s 8960m: Define el tamaño máximo de cada imagen ISO. Para evitar generar más de un ISO, ponemos un tamaño aproximadamente el doble del estándar de un DVD.

-E “/home/comunytek|/home/sysimg”: excluye del backup los directorios que no nos resulten imprescindibles y, sobre todo, el directorio donde vamos a generar el ISO.

Crear una máquina virtual

Vamos a utilizar el entorno de virtualización Oracle VirtualBox (gratuito), instalado en un equipo Windows. Es bastante intuitivo, sin embargo, vamos a indicar algunos pasos importantes:

  • Crear una VM del tipo “Linux/Red Hat 64 bits”.
  • Asignarle suficiente memoria, pero no hace falta asignarle los 32 GB de la máquina origen, sino algo “razonable” para que pueda hacer boot (p.e. 2 GB).
  • Crear un disco con crecimiento dinámico y suficiente espacio para poder “clonar” nuestra máquina origen. En nuestro caso hemos estimado que necesitamos no más de 60 GB. Más adelante se explica el porqué.
  • En Configuración/Almacenamiento, agregar un DVD IDE, apuntando a la imagen ISO (que previamente habremos copiado a nuestro disco local).
  • En Redes, seleccionar “Adaptador puente”, y el NIC físico que queremos usar.

Antes de arrancar nuestra nueva VM, debemos planificar cuidadosamente cómo vamos a particionar nuestro disco virtual. Debemos mantener exactamente la misma nomenclatura de particiones que en la máquina original, pero nos debemos “adaptar” al nuevo tamaño de disco. Nuestra máquina origen tiene 300 GB, pero los discos no están llenos, ni mucho menos. Además, habrá directorios que no nos interesen (logs, archivos de trabajo, etc.). En nuestro caso, las particiones originales son:

Disposit. Inicio    Comienzo      Fin      Bloques  Id  Sistema
/dev/sda1               1           5       32812   de  Utilidad Dell
/dev/sda2   *           5         266     2097152    b  W95 FAT32
/dev/sda3             266        4345    32768000   83  Linux
/dev/sda4            4345       36405   257522688    5  Extendida
/dev/sda5            4345        8425    32768000   82  Linux swap / Solaris
/dev/sda6            8425       36405   224752640   83  Linux

Pero las particiones importantes (/dev/sda3 y /dev/sda6) no están llenas, como vemos con el comando “df -h”:

Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              31G   11G   19G  35% /
tmpfs                  16G  133M   16G   1% /dev/shm
/dev/sda6             211G   47G  154G  24% /home
192.168.0.115:/nfs/SysImages 1,8T  736G  1,1T  41% /mnt/wdnas

De modo que podemos calcular los tamaños que vamos a necesitar en el disco destino, y anotarlos.

Ahora podemos arrancar la máquina virtual, que hará boot desde la imagen ISO, e iniciará el proceso de recuperación.

Restaurar con mondorestore

Cuando la VM arranca, aparece el prompt de mondorestore:

boot:

Aquí debemos entrar “expert” (si usamos cualquier otro modo, sencillamente no funcionará, por las peculiaridades del servidor origen Dell). Mondorestore cargará un micro-kernel Linux y nos dejará en el prompt del sistema. A continuación, debemos particionar el disco usando “fdisk /dev/sda”. El detalle de cómo se emplea este comando está fuera del alcance de este documento. En nuestro caso, debemos terminar con un particionado similar al siguiente:

Device      Start End   Blocks      Id    System
/dev/sda1   1     6     48163+      de    Dell utility
/dev/sda2   7     307   2417782+    b     W95 FAT32
/dev/sda3   308   2308  16073032+   83    Linux
/dev/sda4   2309  7832  44371530    5     Extended
/dev/sda5   2309  2440  1060258+    82    Linux swap
/dev/sda6   2441  7832  43311208+   83    Linux

 

Nótese que se han respetado las particiones /dev/sda1 y /dev/sda2 que los servidores Dell siempre emplean. Si no existen, nuestra máquina virtual no arrancará (no me preguntéis por qué, no lo sé, pero esa es mi experiencia). Notar también que las cifras que aparecen como Start y End están medidas en cilindros, mientras que la columna “Blocks” indica el tamaño en KB.

Ahora ya podemos lanzar el restore. Simplemente entramos “mondorestore” y vamos respondiendo a las preguntas del siguiente modo (básicamente no queremos que particione nuestro disco, pero sí que formatee y restaure el contenido del ISO):

Mode: Interactive
Origin: DVD
Editing Mountlist <OK>
Continue anyway? YES
Partition hard disks? NO
Format hard drives? YES
Restore all of your data? YES
Initialize the bootloader? YES
Regenerate initrd? YES
..rebuild..your initrd..? OK

 

Aquí mondorestore nos vuelve a mostrar el prompt del Sistema. Para regenerar nuestro initrd tenemos que hacer lo siguiente:

# cd /boot
# ls (para ver las imágenes de que disponemos)
# mkinitrd –force initramfs-2.6.32-696.xxx.img 2.6.32-696.xxx (usar siempre las imágenes más recientes)
# exit

Con esto volvemos a mondorestore, y nos preguntará si hemos modificado el mountlist. Contestamos YES, y nos explicará que vamos a editar ciertos ficheros del Sistema. Volvemos a decir YES, y nos irá presentando sucesivamente un editor para que retoquemos (si queremos) una serie de archivos. El editor es autoexplicativo. En principio, sólo tenemos que modificar los archivos “fstab” y “mntab”, eliminando las líneas que contengan un mountpoint NFS (si es que las hay).

Al acabar de editar, parecerá que hemos terminado, pero debemos esperar unos segundos, y aparecerá una ventana indicando que el bootloader “grub” se ha inicializado. Entramos OK y mondorestore hará una limpieza final y nos dejará en el prompt del Sistema. Hemos terminado de restaurar, así que ahora debemos apagar la máquina virtual.

Limpiar la máquina virtual

Una vez apagada la VM, vamos a “Configuración/Almacenamiento” y eliminamos la conexión con la imagen ISO. Ahora volvemos a arrancar la VM, que debería hacer boot con CentOS hasta presentarnos la pantalla de login de GNOME. Entramos con nuestro usuario habitual, y abrimos una ventana de terminal. Es importante “limpiar” lo siguiente (todo esto hay que hacerlo como root):

  • Desinstalar aplicaciones o utilidades que no vayamos a necesitar en la nube.
  • Cambiar el hostname, para evitar conflictos de nombres. Para ello, editar el archivo “/etc/sysconfig/network” y cambiar “HOSTNAME=xxxx” por “HOSTNAME=xxx-bak” (o lo que se desee). A continuación, entrar “hostname xxx-bak”. Por último, editar el archivo “/etc/hosts” para asegurarnos de que se ha cambiado el nombre de host y de que no hay conflicto de direcciones IP.
  • Conviene dar un repaso al contenido de “/home” por si nos hemos dejado cosas innecesarias, que conviene borrar (recuérdese que nuestro disco virtual es 5 veces más pequeño que el original).
  • Comprobar que todo nos funciona correctamente, que no nos falta nada importante, etc. y apagar la VM.

 

Convertir la máquina virtual a un formato neutro

La utilidad VMImport de Amazon EC2 permite importar imágenes de varios tipos pero, por el momento, no soporta los formatos de VirtualBox. Así que tenemos que convertir nuestra máquina virtual a un formato compatible con VMImport. En nuestro caso, vamos a usar el formato neutro OVA. Por suerte, este proceso es muy sencillo:

  • En VirtualBox, seleccionamos “Archivo/Exportar servicio virtualizado”.
  • Seleccionamos la máquina virtual que queremos exportar.
  • Entramos el path completo del archivo de salida, por ejemplo “d:\VirtualBox\xxx-bak.ova”.
  • Tardará un rato en hacer la conversión, pero finalmente tendremos una imagen OVA.

 

Subir el archivo OVA a Amazon S3

Por supuesto, debemos tener una cuenta en AWS, y habremos creado algún bucket donde podamos guardar nuestra imagen. Ahora podemos usar la herramienta que nos resulte más cómoda para subir nuestra imagen. Yo suelo emplear “s3browser”, que funciona muy bien. Conviene crear un directorio nuevo para nuestra imagen en el bucket de destino. Lo podemos llamar “VM” o algo así, y haremos upload de la imagen OVA a este directorio.

Instalar la herramienta de línea de comandos de AWS (CLI)

Las herramientas de export/import de EC2 no tienen una interfaz gráfica (por el momento), así que hay que usar la interfaz de línea de comandos. En Windows, se instala muy fácil, descargando un archivo “msi”, por ejemplo desde:

http://docs.aws.amazon.com/cli/latest/userguide/awscli-install-windows.html

Una vez instalada, el primer paso es hacer una configuración básica de nuestra cuenta AWS. Para eso, en una ventana “cmd”, entramos “aws configure”. Respondemos a las preguntas (claves, región, etc.) y ya podemos ejecutar comandos AWS.

Importar la imagen a una instancia de EC2

Para poder importar nuestra imagen OVA, debemos crear (en el mismo directorio donde tenemos la imagen), un archivo “xxx.json” siendo xxx el nombre de la imagen, con un contenido similar al siguiente:

[
  {
    "Description": "Mi maquina OVA",
    "Format": "ova",
    "UserBucket": {
        "S3Bucket": "vuestro_bucket",
        "S3Key": "VM/vuestra_imagen.ova"
    }
  }         
]

A continuación, ejecutamos el comando de importación (cuidado, es una sola línea):

D:\VirtualBox> aws ec2 import-image –description “Clon from OVA” –license-type BYOL –role-name vmimport –disk-containers file://xxx.json

Es importante que anotemos el id de la tarea de importación, porque nos hará falta más adelante.

IMPORTANTE: el role vmimport debe estar creado previamente. Consultar cómo se hace en la documentación de IAM:

http://docs.aws.amazon.com/vm-import/latest/userguide/vmimport-image-import.html

El comando se ejecuta de forma remota en EC2, y tarda bastante, así que paciencia. Si en cualquier momento queremos consultar el estado de la tarea, usaremos el siguiente comando:

aws ec2 describe-import-image-tasks –import-task-ids import-ami-xxx

Donde xxx es el id de la tarea de importación que antes hemos anotado.

Una vez finalizada la importación, podemos proceder a lanzar una instancia en EC2.

Lanzar la AMI en EC2

Este paso hemos de hacerlo en la consola de AWS, y es muy sencillo:

  • Vamos al servicio EC2 y pinchamos en AMIs. Debería aparecernos una nueva AMI correspondiente a nuestro import. En la columna “AMI Name” aparecerá el nombre de la tarea de import que hemos anotado antes.
  • Para no liarnos en el futuro, conviene que le cambiemos el “alias”. Basta con pasar el ratón sobre la columna “Name”, aparecerá un signo de edición, lo pulsamos y entramos un nombre explicativo, p.e. “milinux-bak”.
  • Pulsamos “Launch”. Se ejecutará un wizard que nos irá preguntando el tipo de instancia, el role IAM, el SecurityGroup, el tamaño de disco EBS que necesitamos (en nuestro caso 60GB), etc. (asumo que el lector está familiarizado con Amazon EC2).
  • Una vez lanzada, la instancia estará inicialmente en estado “stopped”. En la consola EC2, si pinchamos en “Instances”, podemos seleccionarla, y pulsar “Actions/Instance State/Start”. Debemos esperar hasta que esté completamente arrancada. En la parte inferior de la ventana veremos todos los detalles de nuestra nueva instancia, incluyendo la IP pública que EC2 le ha asignado (inicialmente esta IP es volátil). Ya deberíamos poder conectarnos con Putty o Nomachine, e incluso acceder por Samba (depende de nuestro servidor original).

 

Asignar una IP pública estática

Este último paso es opcional. La idea es asignarle a la instancia una IP pública que se mantenga constante, independientemente de que la VM esté arrancada o detenida. Para ello vamos a usar una “Elastic IP”:

  • Detenemos la instancia, y esperamos hasta que esté completamente detenida.
  • Pinchamos en “Elastic IPs”.
  • Pinchamos en “Allocate new address”. Nos generará una nueva IP.
  • Asociamos esta nueva IP con nuestra instancia.
  • Por último, arrancamos de nuevo la instancia, que aparecerá ya siempre con esta IP pública.

 

Y ya está, ya tenemos entorno de contingencia en EC2. Que lo disfrutéis!