Llevando a Docker más allá con Docker Swarm
En este artículo, te voy a mostrar cómo crear un cluster de Docker Swarm. Fácil, rápido y efectivo.
Docker Swarm es un orquestador para Docker, tan pero tan underrated como lo es la banda de música Matchbox Twenty:
A ver, no voy a discutir, minimizar o cuestionar la superioridad y popularidad de Kubernetes. Quedó como el estándar defacto y punto. Pero hay otras opciones y Docker Swarm es mi preferida, le tengo cariño ya que fue una tecnología que use durante casi 4 años para orquestar cuatro hosts de Docker con cerca de 400 contenedores y nunca, pero nunca tuve un problema.
La otra cosa que escribo un artículo sobre Swarm a la altura del partido, es que curiosamente nunca lo hice en el blog, así que me parece buena oportunidad.
¿Arrancamos?
Como comenté más arriba, Docker Swarm es un orquestador que nos va a permitir trabajar con múltiples Docker Hosts. Sobre sus características principales, pueden leer en el siguiente enlace:
Swarm viene incluido en Docker Engine, con lo cual no hay que instalar nada adicional y si bien hay diferencias en cómo lo manejamos, la curva de aprendizaje es más plana que otras soluciones parecidas.
En este tutorial, vamos a trabajar con tres nodos de Docker Swarm. Uno de ellos será el Manager y usaremos dos Workers Pueden leer más sobre estos conceptos en el siguiente enlace:
Ahora, bien, el sistema operativo en donde correremos para este artículo es Ubuntu, pero, mi preferencia para sistemas productivos es usar un sistema operativo liviano pensado para contenedores, mi preferido en RancherOS (Puff, acabo de darme cuenta que este blog tiene un solo artículo sobre RancherOS), pero existe Fedora CoreOS, Flatcar, entre otros.
Vamos a actualizar los repos para descargar Docker en Ubuntu Server en cada uno de los nodos.
$ sudo apt update & sudo apt dist-upgrade
Una vez que termino de actualizar los repositorios y el sistema operativo, vamos a instalar Docker.
$ sudo apt install docker
Vamos a agregar nuestro usuario al grupo de Docker para no tener que correr con sudo, cada comando.
Atención con esto, porque si bien nos da "facilidad" para correr los comandos de Docker, puede generar un problema de seguridad más adelante.
$ sudo usermod -aG docker $tuusuario
Para que tome estos cambios, nos deslogueamos y volvemos a loguearnos para continuar:
$ logout
Armemos el enjambre
Una vez que esta Docker instalado en todos los nodos, vamos a crear el Swarm y lo vamos a hacer ejecutando lo siguiente:
$ docker swarm init --advertise-addr 192.168.1.70
La terminal nos debería devolver algo como esto:
Swarm initialized: current node (mmqz7hzqhdqeanz4rwnvvo0y2) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0rje48awy16jwc56s6h8tatb1rm07sf8h58dhefpuj7s9mebqw-5gw3oiytbv0dvaqn1v0z40ddi 192.168.1.80:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Ahora bien, hagamos una pequeña comprobación para ver como esta nuestro enjambre, veamos los nodos que tenemos:
$ docker node ls
La devolución sería algo como esto:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
mmqz7hzqhdqeanz4rwnvvo0y2 * manager Ready Active Leader 19.03.8
Ahora bien, tenemos dos hosts más para agregar, así que vamos a "joinear" esos dos hosts a este enjambre.
Para eso vamos a ejecutar el comando "docker swarm join", tal como nos respondió la terminal cuando iniciamos el manager en el primer host más arriba. Esto lo vamos a hacer en cada servidor que vamos a usar como Worker.
docker swarm join --token SWMTKN-1-0rje48awy16jwc56s6h8tatb1rm07sf8h58dhefpuj7s9mebqw-5gw3oiytbv0dvaqn1v0z40ddi 192.168.1.80:2377
Tengan en cuenta que ese token, no deberían compartirlo ni dejarlo público, acá solo se muestra como demostración.
Si todo sale bien, luego, desde el manager, podremos ejecutar...
docker node ls
Y nos debería devolver los tres nodos listos para trabajar:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
mmqz7hzqhdqeanz4rwnvvo0y2 * manager Ready Active Leader 19.03.8
s7sr549u92x0x1w58s149c3ep worker01 Ready Active 19.03.8
9gthsz2t5wb3drrlxbkql6pcq worker02 Ready Active 19.03.8
Hagamos una pruebita
Ya tenemos nuestro enjambre listo, ahora vamos a probar si podemos replicar un contenedor para que corra en un mismo hosts.
Si te preguntas, por qué haríamos eso, porque es un excelente caso, donde podemos hacer que nuestras aplicaciones escalen no solo en el mismo hosts, sino a través de todo el Swarm.
Hagamos una prueba tonta, corriendo creando un servicio con NGINX. Para eso y para que el mismo quede replicado en todos los nodos, podemos correrlo así desde el manager:
docker service create --mode global --publish mode=host,target=80,published=8080 --name=nginx nginx:latest
Enseguida se pondrá a descargar nginx y lo desplegará en cada uno de los nodos, lo que hará también es exponer el puerto 8080 para poder consumir lo que nos ofrece ese Webserver.
Cuando le damos enter al comando anterior, la terminal nos devolverá algo como esto:
qup79nnlckxhob1658dd2ig3
overall progress: 0 out of 3 tasks
mmqz7hzqhdqe: preparing [=================================> ]
9gthsz2t5wb3: preparing [=================================> ]
s7sr549u92x0: preparing [=================================> ]
Al finalizar, veremos algo como esto:
qqup79nnlckxhob1658dd2ig3
overall progress: 3 out of 3 tasks
mmqz7hzqhdqe: running [==================================================>]
9gthsz2t5wb3: running [==================================================>]
s7sr549u92x0: running [==================================================>]
verify: Service converged
Vamos a comprobar si efectivamente nuestros NGINX están corriendo:
$ docker service ls
Y si, efectivamente están corriendo:
ID NAME MODE REPLICAS IMAGE PORTS
qqup79nnlckx nginx global 3/3 nginx:latest
Para comprobar de que respondan, podemos hacer un curl al puerto 80 de uno de los nodos, sea cual sea, en mi caso puede ser al manager (192.168.1.80) a los workers (192.168.1.81 y 82) y me responderá la pagina de bienvenida de NGINX.
$ curl -v 192.168.1.80:8080
Otra prueba que podemos hacer es romper uno de los NGINX en uno de los Workers, para que el manager, lo ponga a correr sin intervención nuestra.
Para romperlo, voy a conectarme al worker02 y voy a ejecutar un "docker rm <id-contenedor> --force":
$ docker rm 60409a1e3981 --force
Enseguida, vamos al manager y si hacemos un "docker service ls" veremos que hay corriendo 2 de 3 replicas.
ID NAME MODE REPLICAS IMAGE PORTS
qqup79nnlckx nginx global 2/3 nginx:latest
Pero al cabo de unos segundos, si volvemos a correr el mismo comando, veremos como Swarm se encargo de generar de nuevo el contenedor en el nodo que estaba faltando:
ID NAME MODE REPLICAS IMAGE PORTS
qqup79nnlckx nginx global 3/3 nginx:latest
Para ir cerrando
Cómo ves, no es muy complicado empezar a usar Docker Swarm y estoy seguro que traerá muchos beneficios a tu infraestructura.
En otros artículos veremos cómo montar un storage compartido para que el setup que armamos con NGINX tenga más sentido y realmente sea algo escalable con data verdadera.
Espero que te haya gustado, si tienes dudas o consultas, no dudes en dejarla en los comentarios.