Docker se ha convertido en una herramienta esencial en el día a día de administradores de sistemas y desarrolladores.
Ofrece mucha versatilidad y flexibilidad a la hora de lanzar servicios y aplicaciones, componentes de terceros, etc.
Si queremos crear un cluster con contenedores de Docker utilizaremos Docker Swarm, una aplicación nativa de Docker para ello.

¿Que es Docker Swarm?

Swarm es una funcionalidad de Docker utilizada para la orquestación de clústeres de servicios, que ayuda en la distribución y administración de sistemas acoplados en infraestructuras de host múltiples.

Para usarlo, no necesita más que el motor de Docker instalado, ya que se incluye de forma nativa desde la versión 1.12.

Para hacer un ejemplo, podemos lanzar algunas maquinas virtuales con Vagrant sobre VirtualBox, y montar un Docker Swarm con 3 workers y un manager, que ejecuten un servicio de Apache, por ejemplo.

Esto no es para producción, es solo para realizar pruebas sobre unas maquinas virtuales y ver como funciona de manera básica el clúster.

¿Que necesitamos?

Es necesario que tengamos instalados los siguientes paquetes si trabajamos en cualquiero distro de GNU/Linux:

  • virtualBox
  • vagrant
  • git

Para ello, utilizaremos el VagrantFile de mi repositorio, que es un branch de atSistemas:

https://github.com/xavigm/vagrant-docker-swarm-cluster.git

Así que descargaremos el repo:

 git clone https://github.com/xavigm/vagrant-docker-swarm-cluster.git

Una vez se haya descargado, ponte en el directorio y ejecuta:

 vagrant up

Esto hará que se aprovisionen 4 maquinas en VirtualBox, inicializa el clúster, con una máquina Manager y las máquinas worker01worker02 y worker03 serán nodos Worker.

Ahora nos conectaremos por SSH al Manager (tienes que estar en el mismo directorio):

 vagrant ssh manager

Y podemos comprobar que todos los nodos están corriendo:

vagrant@manager:~ sudo docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
dflfxsrgn7wqchucnemg63pml *   manager             Ready               Active              Leader              18.09.2
5o9jr6ur3jtfst6316t1xl3r3     worker01            Ready               Active                                  18.09.2
fckpcxl3ndhcegb9ltzhwqx7s     worker02            Ready               Active                                  18.09.2
iygaxwqec41259hdypbcf1ct4     worker03            Ready               Active                                  18.09.2

Ahora, podemos desplegar un servicio básico, con 10 replicas por ejemplo, de Apache. Mapeamos el puerto 80 del clúster al del servicio httpd:

vagrant@manager:~ sudo docker service create –replicas 10 –name helloworld -p 80:80

Cuando termine, podemos comprobarlo:

vagrant@manager:~ sudo docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
wycuwjm89wgw        helloworld          replicated          10/10               httpd:latest        *:80->80/tcp

O cuantas instancias corren en cada nodo:

vagrant@manager:~ sudo docker service ps helloworld
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
rd6cpebhdmjh        helloworld.1        httpd:latest        worker03            Running             Running 3 minutes ago
fw0bh8k1zerb        helloworld.2        httpd:latest        manager             Running             Running 3 minutes ago
oqfziatt65rv        helloworld.3        httpd:latest        worker01            Running             Running 3 minutes ago
lvkfizvq1b78        helloworld.4        httpd:latest        worker02            Running             Running 3 minutes ago
t6klkwngd8zg        helloworld.5        httpd:latest        worker03            Running             Running 3 minutes ago
mdo2glwqflo2        helloworld.6        httpd:latest        manager             Running             Running 3 minutes ago
nxrufd7bdg6y        helloworld.7        httpd:latest        worker01            Running             Running 3 minutes ago
mv655d7cqfwe        helloworld.8        httpd:latest        worker02            Running             Running 3 minutes ago
tah8m0dtfw34        helloworld.9        httpd:latest        worker03            Running             Running 3 minutes ago
bdsfhw4s254l        helloworld.10       httpd:latest        worker02            Running             Running 3 minutes ago

Y podemos abrir en un navegador para comprobar que Apache esta funcionando:

 

Ahora vamos a probar algo más.
Destruimos el servicio actual:

sudo docker service destroy helloworld

Ahora, crearemos un fichero DockerFile para definir los servicios que vamos a lanzar.
En este caso, vamos a realizar una prueba lanzando un servicio MySQL, y otro con un WordPress.
Dentro del manager, crea un fichero con el contenido siguiente:

version: ‘3.1’

networks:
wp_my-net:

services:

mysql:
image: mysql
command: –default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wp

wordpress:
image: wordpress:latest
ports:
– 80:80
environment:
WORDPRESS_DB_HOST: mysql:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: wp
WORDPRESS_TABLE_PREFIX: wp_
deploy:
mode: replicated
replicas: 4
labels: [APP=WORDPRESS]

Como veis, hemos definido la contraseña de root para el servidor de MySQL, y hemos indicado la variable en el de WordPress con el host, el usuario y la misma contraseña.

Una vez guardado, por ejemplo, con el nombre de wp.yml, lo ejecutaremos así:

vagrant@manager:~ sudo docker stack deploy –compose-file=wp.yml wp

Veremos que nos indica que se han creado los servicios:

Creating service wp_wordpress
Creating service wp_mysql

Y también la red, que la podemos inspeccionar, para comprobar su scope, que en este caso es swarm, para que los servicios se comuniquen entre ellos.

vagrant@manager:~ sudo docker network inspect wp_default
«Name»: «wp_default»,
«Id»: «rl2c3v04tr5m8u9a6sp2a49nh»,
«Created»: «2019-02-13T15:52:28.706311191Z»,
«Scope»: «swarm»,
«Driver»: «overlay»,
«EnableIPv6»: false,
«IPAM»: {
«Driver»: «default»,
«Options»: null,
«Config»: [
{
«Subnet»: «10.0.0.0/24»,
«Gateway»: «10.0.0.1»

Solo mostramos una porción de la información, ya que se describen también los servicios que la utilizan, etc.

Ahora podemos comprobar como solo falta completar la instalación de WordPress, que utilizará el servicio de MySQL como base de datos.
Podemos abrir un navegador con la IP de nuestro equipo. Como en el DockerFile hemos puesto puerto 80:80, no hace falta indicarle otro. Si ya tienes un servicio arrancado en ese puerto, deberás indicar otro, por ejemplo 8080:80.

Ahora, podemos indicar al swarm cuantas replicas queremos que tenga nuestro servicio de WordPress. Esto en cambio, en el servicio de MySQL no podemos hacerlo directamente, ya que habría que configurar la replicación de las bases de datos. No es demasiado complejo, pero no es lo que queria comentar en este post. Si quieres poder hacerlo, visita este link -> http://ayoubensalem.me/tutorials/2018-04-03/Mysql-replication-in-Swarm-Mode/

Para subir las replicas de WordPress a 10, lo haremos así:

docker service scale wp_wordpress=10

Y veremos que al momento empezarán a levantarse las replicas.

Pues esto es todo lo que quería mostraros en este articulo, como montar un Docker Swarm rápidamente para realizar pruebas y testeos, y por ejemplo, saber que rendimiento puede llegar a darnos la aplicación o servicio que queremos desplegar.

Espero que os haya sido útil, ¡hasta pronto!

 

 

Fuentes y links:

https://enmilocalfunciona.io/cluster-de-docker-con-swarm-mode/
https://github.com/atSistemas/vagrant-docker-swarm-cluster
https://writing.pupius.co.uk/apache-and-php-on-docker-44faef716150
https://blog.10pines.com/2017/12/11/docker-swarm-first-steps/
http://ayoubensalem.me/tutorials/2018-04-03/Mysql-replication-in-Swarm-Mode/