Ir al contenido principal
BlogLinuxDía del lanzamiento: Automatizar la distribución de Linux (con Ubuntu 20.04)

El día de la liberación: Automatización del Linux Distro (con Ubuntu 20.04)

automatizar-distribuciones

Hola a todos. Soy Brad, ingeniero de sistemas en Linode. Hoy es un día lleno de acontecimientos en el mundo de Linux con el lanzamiento de Ubuntu 20.04, la próxima versión LTS (soporte a largo plazo) de una de las distribuciones más populares. Al igual que con Ubuntu 18.04 hace dos años, esperamos que esta se convierta en nuestra imagen más extendida, que ya está disponible para todos los clientes de Linode .

La disponibilidad de las distribuciones en el mismo día se ha convertido en la norma aquí en Linode, gracias a la automatización que hemos desarrollado en torno a la construcción, prueba y despliegue de nuevas imágenes. Pero, ¿qué es una imagen (o una plantilla, como se denomina a veces) y qué se necesita para crearla? Para responder a esta pregunta, empezaremos por ver cómo funcionan normalmente las instalaciones del sistema operativo.

Instalación de un sistema operativo

Puede que estés familiarizado con el proceso de instalación manual de un sistema operativo en un ordenador doméstico o en un servidor. Suele consistir en descargar una ISO de instalación, grabarla en un CD o una unidad USB y arrancar el sistema desde ella. A partir de ahí, se suele pasar por una serie de menús (o, a veces, comandos manuales) que permiten controlar varios aspectos de la instalación, como el disco duro en el que se va a instalar, el software o los paquetes que se quieren incluir y, tal vez, alguna personalización como el establecimiento de un nombre de usuario y una contraseña. Cuando todo haya terminado, tendrás un sistema operativo (con suerte) que funcionará completamente y que podrás arrancar y empezar a utilizar.

Este proceso funciona bastante bien para usuarios individuales que realizan instalaciones puntuales, pero si necesitas instalar más de un pequeño puñado de sistemas, el proceso de instalación manual es simplemente inviable. Aquí es donde entran en juego las imágenes.

¿Qué es una imagen?

Una imagen es esencialmente un sistema operativo preinstalado que puedes desplegar en tantos sistemas como necesites. Funciona realizando una instalación normal una vez y luego haciendo una copia de esa instalación que luego puedes "pegar" en otro sistema. Hay una gran variedad de formas y formatos en los que se pueden almacenar las imágenes para su uso posterior, pero en su mayor parte son copias exactas, byte a byte, de la instalación original.

Ahora sólo tenemos que realizar una instalación manual una vez, y podemos reutilizarla en cualquier otro sitio. Pero aún podemos hacerlo mejor. Linode soporta una amplia variedad de distribuciones, que van desde los sospechosos habituales (Debian, Ubuntu, CentOS, OpenSUSE) hasta algunos que no se encuentran en otros proveedores (Alpine, Arch, e incluso Gentoo). Cada uno de ellos tiene su propio calendario de lanzamientos y su vida útil de soporte. Realizar instalaciones manuales para todas nuestras distros soportadas (aunque sea una sola vez) y tomarse el tiempo para asegurar que las imágenes resultantes funcionen y no contengan ningún error tomaría una enorme cantidad de tiempo y sería muy propenso a los accidentes. Así que hemos optado por automatizar el proceso de creación de imágenes, con la ayuda de una maravillosa herramienta llamada Packer, creada por HashiCorp.

Automatización de la construcción

Aunque todas las distribuciones de Linux comparten una base común (a saber, el núcleo de Linux), todas son muy diferentes entre sí, incluida la forma en que se instalan. Algunas distros utilizan instrucciones de línea de comandos, otras utilizan interfaces de menú, y otras incluyen formas de navegar y suministrar respuestas automáticamente a esos menús. Afortunadamente, Packer es una herramienta muy versátil y puede manejar todos estos casos de uso.

Lo primero que hacemos es instruir a Packer para que cree una máquina virtual (o VM) que se parezca lo más posible a un Linode . Esto significa emular el mismo "hardware" y características que utilizamos para los Linodes reales. De esta manera, la instalación se realizará en un entorno que se asemeja mucho al entorno de ejecución final. Imagina instalar un sistema operativo en una unidad USB y luego usar esa unidad para arrancar un ordenador completamente diferente. Si tienes suerte, puede que las cosas funcionen, pero lo más frecuente es que no se detecte algún dispositivo de hardware o que no arranque en absoluto. Al tener un entorno de instalación que coincide con el entorno real de funcionamiento, eliminamos estos problemas.

Una vez creada la VM, Packer la arrancará desde la ISO de instalación de la distribución, que obtiene de una URL especificada. El proceso a partir de aquí varía mucho entre las distros. En el caso de las distribuciones basadas en comandos, como Arch, se introduce un script bash que realiza una instalación básica. Para las distribuciones basadas en menús, como Ubuntu, utilizamos el método preferido de la distribución para proporcionar respuestas al instalador (normalmente, Preseed en las distribuciones similares a Debian o Kickstart en las distribuciones similares a RHEL). Además de nuestra VM, Packer también crea un pequeño servidor HTTP que permite transferir cualquier archivo necesario a la VM.

Todo esto se controla a través de un archivo JSON que define la configuración y las opciones de compilación que utilizará Packer. Para iniciar una construcción, simplemente tenemos que ejecutar (por ejemplo): packer build ubuntu-20.04.json.

Personalización

En la mayoría de los casos, realizamos instalaciones lo más sencillas posible. Esto significa instalar los paquetes que la distro considera "por defecto" (a veces denominados "base" o "estándar"). Además de estos paquetes por defecto, también instalamos un pequeño puñado de lo que llamamos paquetes de "soporte": utilidades básicas como iotop, mtr y sysstat que pueden ayudar a depurar cualquier problema que pueda surgir. Por lo tanto, el equipo de soporte de Linode también puede asumir razonablemente que estas herramientas están instaladas mientras asiste a los clientes.

Una vez finalizada la instalación, pero antes de apagar la máquina virtual, realizamos algunas personalizaciones finales para garantizar el correcto funcionamiento de todas las características de la plataforma Linode . Por ejemplo, nos aseguramos de que el cargador de arranque esté configurado con los ajustes correctos para LISH (nuestra herramienta para el acceso a la consola fuera de banda). En general, sin embargo, tratamos de mantener las cosas lo más cerca posible de sus valores predeterminados. De esta manera, un usuario que prefiere una distribución específica obtendrá lo que le resulta familiar y no se sentirá como si condujera el coche de otra persona.

Embalaje

Una vez terminada la instalación y la configuración, Packer apaga la máquina virtual y exporta su imagen de disco a un archivo. Puede parecer que hemos terminado, pero aún quedan algunos pasos. El disco duro de un ordenador típico comenzará con una tabla de particiones (ya sea MBR, o GPT en los sistemas más nuevos). Los linodes son un poco únicos en el sentido de que el propio gestor de arranque GRUB vive en nuestros hosts, en lugar de en cada Linode (sin embargo, la configuración se sigue leyendo de Linode ). Esto significa que podemos eliminar la tabla de particiones por completo, dejándonos con una sola partición.

Para ello, ejecutamos fdisk -l disk.img en la imagen del disco para determinar dónde empieza y termina la partición, y cuál es el tamaño del bloque. A continuación, utilizamos dd if=disk.img of=part.img bs=### skip=### count=### para "forklift" la partición usando el desplazamiento inicial de nuestro comando anterior. Más específicamente, cada "###" en ese comando es reemplazado por la salida de nuestro comando anterior fdisk comando.

Al igual que en un ordenador nuevo, la mayor parte del espacio de la unidad estará vacío, y esto se reflejará en nuestra imagen de disco. Sería una tontería copiar todos estos bytes "vacíos", así que lo siguiente que hacemos es desinflar la imagen (más tarde, cuando despliegue una imagen en su Linode, nos re-inflar para llenar el espacio disponible en su instancia). Como todas nuestras imágenes utilizan particiones ext4, podemos ejecutar resize2fs -M part.imgque reducirá automáticamente nuestra imagen al menor tamaño posible eliminando el espacio vacío. Por último, para garantizar la integridad de la imagen resultante, realizamos una última fsck antes de comprimirlo con gzip.

Prueba

Una vez construida y preparada la imagen, el siguiente paso del proceso es asegurarse de que realmente funciona. Nuestra imagen recién creada se despliega en un entorno de pruebas, en el que se aprovisionan varias instancias de Linode a partir de la imagen en una serie de configuraciones diferentes. Hemos desarrollado un conjunto de pruebas automatizadas que comprueban todo tipo de cosas diferentes, como la conectividad de la red y un gestor de paquetes que funcione, así como varias características de la plataforma Linode , como las copias de seguridad y el cambio de tamaño del disco; lanzamos el libro a estas instancias. Si alguna comprobación falla, el proceso es inmediatamente abortado y la construcción falla, junto con algunos detalles sobre qué comprobación falló y por qué.

Construir y probar de forma automatizada como ésta permite ciclos de desarrollo rápidos que, a su vez, nos permiten lanzar mejores imágenes, más rápido. Hemos estructurado nuestro proceso de pruebas de tal manera que añadir nuevas comprobaciones es trivial. Si un cliente nos informa de un problema con una de nuestras imágenes, podemos publicar rápidamente una corrección y añadir otro elemento a nuestra creciente lista de comprobaciones, casi como un sistema inmunológico.

Lo mismo, pero diferente

El despliegue masivo de sistemas a partir de una imagen común está muy bien, pero ¿qué pasa con las cosas que son únicas para una instancia específica, como la contraseña de root o la configuración de red? Nuestras imágenes están configuradas para utilizar DHCP, lo que hará que su sistema reciba automáticamente su dirección IP y un nombre de host único de nuestros servidores DHCP. Sin embargo, también proporcionamos una variedad de "ayudantes" como Network Helper (que configurará automáticamente la red estática en su Linode), y nuestra herramienta de restablecimiento de la contraseña de root (que establece su contraseña de root inicial y que también puede utilizar en caso de emergencia si necesita restablecerla). Estas herramientas permiten aplicar información específica de la instancia a su Linode sobre la imagen base.

Por supuesto, no todas las distribuciones manejan estas tareas de la misma manera, por lo que nuestras herramientas tienen que ser conscientes de cómo hacer estas cosas en todas nuestras distribuciones compatibles. Las nuevas versiones principales de una distro normalmente requerirán algunas actualizaciones de estos sistemas para que las cosas funcionen completamente. Por ejemplo, Debian tradicionalmente configura la red en /etc/network/interfaces, mientras que CentOS coloca las configuraciones de red en /etc/sysconfig/network-scripts. Afortunadamente, la mayoría de las distribuciones ofrecen versiones beta con antelación, lo que nos da mucho tiempo para realizar estos cambios y asegurarnos de que todo esté listo para el día del lanzamiento.

Conclusión

Como puedes ver, hay muchas cosas que se necesitan para dar soporte a una nueva distribución, así que ¿cuál es el beneficio real de automatizar este proceso? Bueno, hace años, antes de que tuviéramos el proceso que tenemos hoy, un lanzamiento típico de una distro (desde la construcción hasta las pruebas y la disponibilidad) llevaría, en el mejor de los casos, un día entero, pero normalmente varios días, y muchas personas estarían involucradas. En comparación, el lanzamiento de hoy de Ubuntu 20.04 sólo requirió 5 líneas de cambios en el código y llevó menos de una hora de principio a fin. Si tienes alguna sugerencia o algo que te gustaría ver, dínoslo. Me encuentro en el IRC como blaboon en OFTC y lblaboon en Freenode. Si estás interesado en probar Packer por ti mismo, tienen una gran documentación que se puede encontrar aquí. También tenemos nuestro propio constructorLinode para Packer, que puedes utilizar para crear tus propias imágenes personalizadas en nuestra plataforma. Puedes encontrar más documentación sobre el uso del constructor Linode para Packer en nuestra biblioteca de Guías y Tutoriales aquí.


¿No es cliente de Linode ? Regístrese aquí con un crédito de 20 dólares.


Comentarios (4)

  1. Author Photo

    This is brilliant and very timely (for me) as I happened to spend some of last weekend to “reverse engineer” the build process (and discovered the GRUB config quirks) while tried to test migrating a Linode VM over to a on-premises (lab) VM Host and vice versa. Maybe this would be a good write-up, if you are searching for tutorial/blog topics. Many thanks for publishing this!

  2. Nathan Melehan

    Hey A. –

    That sounds like a cool topic! If you’re interested, we actually have a paid freelance contributor program for our documentation library called Write For Linode. You can learn more about the program and apply to it here: https://www.linode.com/lp/write-for-linode/

    • Author Photo

      Hi Nathan
      Thanks for this, it looks very tempting. I started to work on the process for the first migration but I was stopped by Grub2. As described in the Packaging section above, the stripped out boot partition stops me to boot up the the image in my VM Host and I haven’t been able boot up the image dd’d out of Linode. If I create a vanilla VM image with the same Ubuntu version as in my Linode VM, the (virtual) disk is partitioned with two partitions, sda1 hosting grub (I assume this is what you strip out in the build process) and sda2, which is “/”. The image “exported” out of Linode, on the other hand has only a single partition as described above. Is there any documentation describing how to undu the stripping out of sda1, or how insert a new boot (sda1) partition back into the image? Many thanks, A

      • Author Photo

        Ok, I managed to get through booting my local clone in the end and it turns out that the startup process didn’t crash (as I thought), it was just slow*. It is because (unsurprisingly) it has a hard-coded static IP address which now lives on the wrong network, so I had to wait until the network config time-out* during the boot-up process.

        That’s easy enough I’ll just change the config in /etc/network/interfaces (the default/standard place in Ubuntu, and as also mentioned in this article). Looking at the “interfaces” file it, is blank with a note that things have moved on (since I last had to deal with linux networking) and it is now handled by something called “netplan”. [grrrrr….]

        No matter, it can’t be that hard, let’s see what /etc/netplan says. Well, the yaml file says my ethernet interface should be called `enp0s3` and should be getting the address from dhcp. But my actual interface name is `eth0` and has a static address. Where is this coming from?! [&$#^%#]

        Time to “brute force” search the entire config.
        `find /etc/ -exec grep ‘12.34.56.78’ {} \; 2>/dev/null` results in 3 hits, one is by an application so there are only two potential places to change, it might be easy enough to check**:

        `grep -Rn ‘12.34.56.78’ * 2>/dev/null`

        systemd/network/05-eth0.network
        systemd/network/.05-eth0.network

        It was auto-generated by Linode’s Network Helper (as described in the article) which is not available in my lab, unsurprisingly, so let’s just copy back the original config:

        `cp 05-eth0.network 05-eth0.network.bak`
        `cp .05-eth0.network 05-eth0.network`
        `shutdown -r now`

        Bingo!!! The VM came up with a new dynamic IP address and I can ping and nslookup to my heart content!!! I haven’t checked if the actual web application survived the extraction, and what else may have broken in the process.

        *and probably a lot more linode specific configs that are inaccessible to my local clone.
        **The actual IP address is not this

        Lessons learned: It is a lot more complicated to migrate out of Linode to a local VM or different cloud and require a lot of effort to fix/adapt the extracted application and the OS, it would be a lot faster just to build the lab up from the ground up. It might be a simpler process to move the other way around (i.e. develop in my own lab and pull the result into Linode) but wouldn’t hold my breath trying.

        Not sure if my experience warrants an article beyond this (chain of) comment(s). But it was a great weekend project and an inspirational learning exercise, many thanks, Linode!

Dejar una respuesta

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