Aplicaciones multi-contenedor en un clúster con Swarm
Ya has pasado de la fase de tener una aplicación en un solo contenedor a trabajar con aplicaciones multi-contenedor con docker-compose. Sin embargo, hasta ahora, todo se está ejecutando en una sola máquina y con una sola réplica por contenedor, lo cual hace que tu aplicación no sea ni lo suficientemente escalable ni tolerante a fallos. Hoy vamos a dar un paso más viendo cómo puedes trabajar con aplicaciones en Docker repartidas por varias máquinas de un clúster, utilizando Swarm.
Swarm o “Enjambre”
Swarm, en español enjambre, se trata de una herramienta que nos ayuda a gestionar y orquestar contenedores en un clúster. Gracias a que en Docker también podemos trabajar con este concepto, podremos asegurarnos de que nuestras aplicaciones soportan la demanda, además de ser tolerantes a fallos, teniendo más de una copia del mismo contenedor en más de una máquina o nodo.
Dentro de este clúster, existirán dos roles: manager y worker. El primero de ellos es el que es capaz de mandar órdenes al resto, para administrar el clúster. Los workers simplemente hospedan los contendores.
Como es posible que los nodos sean físicos o virtuales, lo primero que vamos a preparar son máquinas con estos roles de una forma muy sencilla con docker-machine.
Máquinas en swarm mode con docker-machine
Para poder disponer de un conjunto de máquinas de manera súper rápida podemos hacer uso de docker-machine. Lo que hace, básicamente, es crear y gestionar máquinas virtuales que, dependiendo del sistema operativo que estés utilizando, pueden ser sobre VirtualBox o Hyper-V, si estás en Windows 10. Además, como en los volúmenes, aquí también existe el concepto de drivers, por lo que también es posible crear estas máquinas en un entorno remoto. En este ejemplo usaré VirtualBox para que sea independiente del sistema operativo. Los comandos a lanzar serán los siguiente:
Cuando termine la creación de cada una de las máquinas es posible ver un listado de todas ellas a través del siguiente comando:
Como te puedes imaginar, vm-manager será a la que le otorgarás el rol de manager. Para hacerlo puedes lanzar el siguiente comando, que a través de docker-machine ssh ejecuta docker swarm init en dicha máquina, que lo que hace es inicializar un nuevo clúster.
Además, te devolverá el comando que necesitas para que otras máquinas se unan al mismo.
Cópialo y, de la misma manera que ejecutaste el comando en vm-manager, ejecuta este otro en vm-worker1 y vm-worker 2 para que se unan.
Una vez que lo hayas hecho con las dos máquinas, desde vm-manager puedes listar todos los nodos disponibles:
El resultado debería de ser: un nodo como manager y dos como workers.
Desplegar una aplicación en el clúster
Para finalizar, vamos a retomar nuestra aplicación multi-contenedor que utilicé en el artículo de aplicaciones multi-contenedor con docker-compose” y la vamos a desplegar en nuestro nuevo clúster.
Al igual que cuando trabajábamos con docker compose, aquí también es necesario un archivo docker-compose.yml donde se define la configuración de nuestra aplicación, pero con algunas propiedades más:
- replicas: se utiliza para decir cuántos contenedores quieres de una misma imagen.
- networks: se utiliza para definir y para establecer en qué red estarán mis contenedores. Esta propiedad es muy importante ya que sin ella los distintos tipos de contenedores no se podrían ver entre sí internamente.
Obviamente hay muchas otras opciones que podemos configurar pero, en este caso, estas son las mínimas que necesitarás para que todo funcione correctamente.
Antes de poder ejecutar esta configuración, debemos hacer dos cosas:
Las imagenes de backend y frontend deben de estar alojadas en un registro, para que los nodos de mi clúster puedan acceder a ellas (sino tendrías que ir nodo por nodo construyendo la imagen a partir del código ¿te imaginas?). Hace unos días te enseñe cómo hacerlo para Docker Hub y Azure Container Registry. Para este ejemplo utilizaré Docker Hub, renombrado mis imágenes locales de la siguiente forma:
Para subirlas al registro solo debes hacer push de cada una de ellas.
Como es lógico, el archivo docker-compose.yml lo has creado en tu máquina local, pero realmente necesitas lanzarlo desde vm-manager, que es quien puede mandar órdenes a los nodos que tiene tu clúster. Existe una forma muy cómoda para mapear el terminal de vm-manger con el terminal de nuestro equipo local:
Al lanzar este comando se generan unas variables de entorno que nos permiten hacer esta conexión. Ahora ejecuta el siguiente para terminar con la configuración.
Sin ningún tipo de aviso, ahora ya puedes lanzar comandos en el terminal como si estuvieras dentro de vm-manager, pero además puedes utilizar todo de lo que dispones en tu máquina local, como el archivo docker-compose.yml. Para materializar todo lo descrito en él debes aprender otro comando más, docker stack, que funciona de la siguiente manera:
Al cabo de unos segundos todos los contenedores con todas sus replicas serán repartidos entre todos los nodos de tu clúster. Para ver el estado usa este comando:
Podrás ver que tu aplicación, o stack, está desplegado correctamente (Running) y podrás acceder al frontend a través del puerto 4000 y al backend a través del puerto 8080 ¿pero de qué IP? Pues en realidad de cualquiera de las IP de cualquiera de los nodos, por ejemplo http://192.168.99.102:4000, ya que todos ellos tienen por delante lo que se conoce como el swarm load balancer, el cual conoce dónde hay réplicas del contenedor al que quieres acceder y nos hace transparente esta gestión.
Imagen de portada por kyohei ito.
¡Saludos!