Creación de un cluster con docker swarm

Docker Logo

El artículo se ha escrito utilizando docker 1.12 y 4 máquinas ubuntu 16.04.1 LTS virtualizadas con VirtualBox, de las cuales solo 1 de ellas tenia instalado docker-machine.

Este artículo es una guia rápida de creación de un cluster de nodos de docker, gestionados de forma nativa por docker swarm.

Algunos de los conceptos manejados por docker swarm son:

  • nodos. Diferentes equipos ejecutando docker
  • manager. Uno de los nodos del cluster actúan de manager y es el responsable de gestionar los nodos del cluster.
  • worker. El resto de nodos son los workers. Estos con los responsables de ejecutar las tareas que el manager le indica, creando y ejecutando los contenedores. El manager también puede actuar como worker.

Cuando desplegamos una aplicación en un cluster de docker swarm, creamos una definición de un servicio. Esta definición del servicio la enviamos al manager. El manager divide el servicio en tareas o tasks y las envia a los workers, que son los que finalmente ejecutan las tareas. Estas tareas o tasks se traducen en la creación de los contenedores que son los que finalmente ejecutan nuestra aplicación.

Creación del cluster swarm y del manager

Nos conectamos a uno de los nodos para seleccionarle como el manager.

$ eval $(docker-machine env node-2)

$ docker-machine ls
NAME     ACTIVE   DRIVER    STATE     URL                         SWARM   DOCKER    ERRORS
node-1   -        generic   Running   tcp://192.168.56.104:2376           v1.12.1
node-2   *        generic   Running   tcp://192.168.56.102:2376           v1.12.0
node-3   -        generic   Running   tcp://192.168.56.103:2376           v1.12.0

$ docker swarm init --advertise-addr $(docker-machine ip node-2)
Swarm initialized: current node (4hrikn3j4fls4xrdz8dzc2g9r) is now a manager.

To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-31svc7oooa11nisnue3p2lysil3tczafncdkjk6voyht3zoh2a-36ng05zu8nw82d1npvxflbzpc \
192.168.56.102:2377

To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-31svc7oooa11nisnue3p2lysil3tczafncdkjk6voyht3zoh2a-7diqubxwe8ghhtqe2g3rgqhz1 \
192.168.56.102:2377

Creacion de los workers

Nos conectamos al resto de nodos para que se unan al swarm o cluster recién creado y les decimos que actúen como workers.

$ eval $(docker-machine env node-3)
$ docker-machine ls
NAME     ACTIVE   DRIVER    STATE     URL                         SWARM   DOCKER    ERRORS
node-2   -        generic   Running   tcp://192.168.56.102:2376           v1.12.0
node-3   *        generic   Running   tcp://192.168.56.103:2376           v1.12.0

$ docker swarm join \
--token SWMTKN-1-31svc7oooa11nisnue3p2lysil3tczafncdkjk6voyht3zoh2a-36ng05zu8nw82d1npvxflbzpc \
192.168.56.102:2377
This node joined a swarm as a worker.

Repetimos el mismo paso para el node-1.

Comprobar el estado del cluster

Nos conectamos al manager para comprobar el estado del cluster.

$ eval $(docker-machine env node-2)
$ docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
4hrikn3j4fls4xrdz8dzc2g9r *  node-2    Ready   Active        Leader
6p5kd0u96vcs5m70kmc3c78s2    node-3    Ready   Active
8aircf03acpeu1ym8oq9bb7j2    node-1    Ready   Active

Volver a ver los tokens para gestionar los manager y los workers

Desde el nodo manager ejecutamos los comandos siguientes.

$ docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-31svc7oooa11nisnue3p2lysil3tczafncdkjk6voyht3zoh2a-7diqubxwe8ghhtqe2g3rgqhz1 \
192.168.56.102:2377
$ docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-31svc7oooa11nisnue3p2lysil3tczafncdkjk6voyht3zoh2a-36ng05zu8nw82d1npvxflbzpc \
192.168.56.102:2377

Crear una red de tipo overlay

Para la comunicación entre contenedores desplegados en diferentes nodos debemos crear una red de tipo overlay.

$ docker network create --driver overlay mydemo-network
0wmy8heuieggqzsi8y5fg1vz2

Creación del primer servicio y comprobación del servicio

La imagen francois/apache-hostname está basada en un servidor apache que devuelve el id del contendor donde se ejecuta.

El servicio crea 3 contenedores en el cluster, cada uno de ellos desplegado en el puerto 80, pero accesible desde fuera en el puerto 8080.

Esto significa que cualquier petición que realicemos a cualquiera de los nodos del cluster al puerto 8080, docker swarm se va a encargar de enviar la petición balanceando la carga a 1 de los nodos del cluster al puerto 80, y será el contenedor ejecutandose en ese nodo el que responda a la petición.

Docker swarm realiza el balanceo a nivel interno creando una IP virtual por cada servicio. El balanceo se produce utilizando IPVS, el cual se encuentra implementado en el Kernel de linux, con lo que conseguimos un balanceo de carga con un rendimiento mayor del que conseguiríamos utilizando Nginx, HAProxy o similares.

IPVS (IP Virtual Server)

implements transport-layer load balancing inside the Linux kernel, so called Layer-4 switching. IPVS running on a host acts as a load balancer at the front of a cluster of real servers, it can direct requests for TCP/UDP based services to the real servers, and makes services of the real servers to appear as a virtual service on a single IP address

Creación del servicio

La definición del servicio se la mandamos al manager. Entre los parámetros posibles se encuentra el número de replicas del servicio, lo que se traduce en tareas que son enviadas a los workers, y que se convierten en la creación de 1 contenedor por replica.

Si una de las replicas (contenedor) cae, el servicio sigue siendo atendido por el resto de replicas (contenedores) mientras docker swarm levanta una nueva replica para mantener el estado inicial de la definición del servicio.

$ docker service create --name echo-container-id --replicas 3 --network mydemo-network -p 8080:80 francois/apache-hostname
8ccdsdi7av1hcpggb5y2xluwr
$ docker service ls
ID            NAME               REPLICAS  IMAGE                     COMMAND
8ccdsdi7av1h  echo-container-id  0/3       francois/apache-hostname

Recién creado el servicio no existe ninguna replica ejecutando el servicio. Por eso vemos 0/3 en el número de replicas. Si esperamos unos segundos y volvemos a ejecutar el mismo comando, veremos como el número de replicas disponibles se convierte en 3.

$ docker service ls
ID            NAME               REPLICAS  IMAGE                     COMMAND
8ccdsdi7av1h  echo-container-id  3/3       francois/apache-hostname

Comprobación del servicio

Vemos como cada petición es resulta por diferentes contenedores, que se encuentran ejecutándose en nodos diferentes del cluster.

$ curl http://node-1:8080
<html><body>This page is displayed on the container: <b>21e83efd0c75</b></body></html>

$ curl http://node-1:8080
<html><body>This page is displayed on the container: <b>317d9e7a04bc</b></body></html>

$ curl http://node-1:8080
<html><body>This page is displayed on the container: <b>e75e3d5ddc73</b></body></html>

$ curl http://node-2:8080
<html><body>This page is displayed on the container: <b>21e83efd0c75</b></body></html>

$ curl http://node-3:8080
<html><body>This page is displayed on the container: <b>317d9e7a04bc</b></body></html>

Conclusión

Como vemos la creación de un cluster con docker swarm 1.12 es realmente sencilla. Cualquier aplicación que necesitemos crear la traduciremos en una definición del servicio, que como hemos visto se la enviaremos al manager, y el se encargará del resto por nosotros.

Documentación de referencia

Deja un comentario