sábado, 5 de enero de 2019

Usando plugins en Docker - NetApp Trident

Hoy vamos a estudiar cómo podemos extender las funcionalidades de Docker mediante el uso de plugins.

Docker y por tanto Docker Swarm, al igual que orquestadores como Kubernetes o Rancher, permite el uso de plugins o módulos adicionales que nos permitirán la integración de nuestra infraestructura de contenedores con otros servicios o añadirán funcionalidades adicionales. Estos plugins, disponibles en Docker Hub, nos permiten integrar nuestros dockerhosts con sistemas de almacenamiento, añadir funcionalidades de logging o extender las capacidades de red.

Para estudiar el funcionamiento del sistema de plugins de Docker, voy a centrarme en el plugin Trident desarrollado por NetApp, que nos permite administrar y montar volúenes alojados y servidos por sistemas NetApp en nuestros dockerhosts.

Plugin Trident de NetApp disponible en Docker Hub.
En la página del plugin en Docker Hub tenemos disponible la descripción del plugin así como las instrucciones de instalación del mismo, pero es recomendable seguir las instrucciones de configuración oficiales dadas en el siguiente enlace.

En resumen, para usar este plugin debemos realizar los siguientes pasos:
  1. Debemos crear el fichero de configuración en todos los dockerhosts que vayamos a integrar con nuestros sistemas NetApp.
  2. Crearemos una o más SVMs que proporcionarán los servicios de bloque o fichero necesarios. Es muy importante que dichas SVMs tengan asignado uno o más agregados para la creación de volúmenes.
  3. Creamos un rol y un usuario específico para el uso del plugin en cada una de las SVMs que vayan a proporcionar servicio a nuestros dockerhosts.
  4. Por último instalamos el plugin en todos nuestros dockerhosts.
Empecemos por el fichero de configuración, como indica la documentación este fichero debe estar en la ruta /etc/netappdvp y es un fichero JSON cuyo nombre por defecto será config.json. Una configuración simple del fichero, para un entorno NAS, podría ser:

Fichero de configuración de Trident.
En esta configuración estoy especificando:
  • Los parámetros managementLIF y dataLIF contienen el nombre DNS o dirección IP de las LIF de gestión y datos de la SVM para esta instanacia de configuración.
  • El parámetro svm indica el nombre de la SVM que estamos usando, siendo username y password las credenciales del usuario que usaremos para interactuar con dicha SVM.
  • La sección default establece una serie de valores por defecto para la creación de nuestros volúmenes desde los dockerhosts. En este ejemplo establecemos la política de snapshots así como la política de exportación de volúmenes, el tamaño de los volúmenes creados, el tipo de seguridad y la reserva de espacio para snapshots.
En caso de cambiar la configuración de Trident, será necesario reiniciar el plugin con los comandos docker plugin disable y docker plugin enable.
 
Creamos una SVM con el mismo nombre que el que indicamos en el fichero de configuración, así como el rol con los permisos adecuados que luego asignaremos al usuario que tabién vamos a crear. Los permisos necesarios para el rol son los siguientes:

Creación del rol necesario para el plugin.
Creamos el usuario y le asignamos el rol que acabamos de crear, es importante que establezcamos como tipo de aplicación a usar por el usuario ontapi:

Creación del usuario y asignación del rol.
Ahora ya podemos instalar el plugin en todos nuestros dockerhosts, siendo la salida de la instalación como la siguiente:

Instalación del plugin Trident en los dockerhosts.
El plugin ya instalado y disponible.
Una vez instalado el plugin, al estar habilitado, el demonio docker se encargará de arrancarlo cada vez que iniciemos el sistema. Podemos comprobarlo viendo los procesos de cada uno de nuestros dockerhosts:
Procesos del plugin Trident.
En caso de ser necesario, podemos parar el plugin usando el comando docker plugin del siguiente modo:

Parando el plugin Trident en un dockerhost.

Como ya he comentado la SVM debe tener agregados asignados a ella para permitir la creación de volúmenes desde el plugin. En caso de no ser así recibiríamos un error como el siguiente:

Error cuando la SVM no tiene agregados asignados.
Desde OnCommand System Manager podemos asignar de forma muy rápida y simple los agregados a la SVM con solo editarla desde el apartado SVMs:

Asignamos un agregado a nuestra SVM para el usuao de Trident.
Lo primero que podemos hacer es crear los volúmenes que vayamos a necesitar usando el comando docker volume. Como es lógico esto solo lo haremos desde uno de nuestros dockerhosts, así que como ejemplo creamos varios volúmenes desde diferentes dockerhosts:

Creamos varios volúmenes usando el plugin Trident.
Comprobamos que los nuevos volúmenes existen en el agregado.
Es muy importante que nos demos cuenta que al delegar un agregado a la SVM como hemos hecho, el usuario que utilicemos tiene control total sobre los volúmenes que existan en dicho agregado. Por tanto, si el agregado está compartido con más clientes, es posible borrar el resto de volúmenes con los comandos de gestión de volúmenes de Docker a través de Trident, siempre y cuando todos los volúmenes de dicho agregado contengan el mismo prefijo que hemos establecido en la configuación del plugin. Por ejemplo, si listamos los volúmenes disponibles vemos que aparece uno que no hemos creado con Trident:

Listado de volúmenes disponibles.
Para evitar problemas, si es necesario que diferentes cliente compartan el mismo agregado, lo mejor es que los volúmenes controlados por Trident utilicen un prefijo distinto al del resto de volúmenes del agregado.
 
Una vez creados los volúmenes, podemos pasar a usarlos montándolos cuando despleguemos un contenedor o un servicio en nuestro swarm:

Creación de un servicio replicado con un volumen.
El comando anterior utiliza la sintaxis mount para el montaje de volúmenes, esta sintaxis está disponible desde la versión 17.06 de Docker para contenedores standalone y no solo para swarm. En próximas entradas explicaré más detalladamente como utilizarla y sus diversas opciones, por ahora quedémonos en que vamos a montar un volumen controlado por el plugin Trident.
 
Al ejecutar el comando anterior, swarm orquesta el montaje del volúmen especificado en los hosts en los que se despliegue un contenedor que lo necesite, con lo que, de forma automática montará por NFS el volumen swarm_HTML que hemos creado anteriormente y que está sirviendo nuestra SVM. Esto lo podemos comprobar del siguiente modo:

Escalamos el servicio a 3 réplicas.
Ahora el contenedor solo está corriendo en tres de los dockerhosts que forman el swarm, con lo que el volumen necesario solo está montado en dichos hosts como podemos ver:

Docker Swarm ha montado el volumen en los hoosts necesarios.
Si ahora escalamos de nuevo el servicio, comprobaremos que se montará el volumen en el nodo swarm-nodo2 para poder levantar correctamente el contenedor con el volumen requerido:

Docker Swarm monta el volumen en el nodo restante.
Como es lógico, al borrar el servicio, el volumen se desmontará de todos los nodos si ningún otro servicio lo está utilizando.

Por tanto, y en resumen, hemos visto como Docker Swarm es capaz de orquestar perfectamente el montaje de volúmenes externos, en este caso controlados por el plugin Trident de NetApp y como este plugin nos permite integrar nuestra infraestructura de contenedores basada en Docker con los sistemas de almacenamiento NetApp. Además hemos podido comprobar como expandir las funcionalidades de Docker mediante el uso de plugins.

Como es lógico este plugin también está disponible para Kubernetes, el cual espero poder estudiar dentro de un tiempo y repasar su funcionamiento.

En próximas entradas, repasaré las opciones disponibles para la gestión y uso de volúmenes en servicios implementados en Docker Swarm con la opción mount.

martes, 25 de diciembre de 2018

Como añadir discos en ONTAP simulator

Si como yo estás preparándote la certificación de cluster ONTAP, estarás más que acostumbrado a usar el simulador de NetApp para poder realizar pruebas. En ese caso puede suceder que necesites añadir más discos para realizar pruebas con diferentes funcionalidades, para lo cual hoy vamos a ver como podemos añadir discos de forma sencilla a cada controladora.

Es importante, antes de continuar, tener en cuenta ciertos puntos sobre el simulador de ONTAP:
  • Al tratarse de máquinas virtuales, no hay una conexión física entre las controladoras ni entre las controladoras y los discos de su partner, con lo que no se pueden realizar pruebas de storage failover.
  • No podemos comprobar el estado de conexión de las bandejas mi configurar ACP.
  • Cada nodo puede tener un máximo de 4 bandejas simuladas, con 14 discos por bandeja para un total de 56 discos por nodo virtual.
Para poder incrementar el número de discos en un nodo virtual, solo tenemos que seguir estos pasos:
  1. Es necesario desbloquear la cuenta de usuario diag. Este usuario es necesario para poder acceder a la systemshell. La systemshell es la shell del nodo, ya sea físico o virtual, en la cual estamos accediendo al FreeBSD sobre el que corre ONTAP y, por tanto, al sistema operativo que corre en nuestras controladoras.
  2. Pasamos al usuario diag y nos conectamos a la systemshell de cada nodo.
  3. Hay un script en cada nodo llamado vsim_makedisks que nos permitirá añadir los discos que necesitemos, de ciertos tipos ya predefinidos, a dicho nodo. Si lo ejecutamos con la opción -h nos mostrará una lista de los tipos de discos disponibles.
  4. Cambiamos al directorio /sim/dev y lanzamos el script usando sudo indicando el número de discos (-n), el tipo de los mismos (-t) y el puerto o controladora virutal donde vamos a "conectar" estos nuevos discos.
  5. Por último es necesario rebotar el nodo para que los nuevos discos aparazcan como unassigned y podamos asignarlos al nodo.
El proceso descrito en los pasos anteriores, podemos verlo en las siguientes imágenes:

Desbloqueamos el usuario diag.
Entramos en la systemshell de cada nodo.
Salida de ayuda del script vsim_makedisks.
Ficheros para cada disco en /sim/dev/,disks en cada nodo.
Añadimos 14 discos del tipo 31 al adapatador 0.
Asignamos los nuevos discos al nodo.
El proceso anterior podemos hacer en ambos nodos o solamente en uno y, una vez terminado ya tendremos nuestros nuevos discos listos para realizar todas las pruebas que necesitemos.

viernes, 7 de diciembre de 2018

Administración de Docker swarm con Rancher

Hoy continuamos explorando Docker swarm pero, para variar un poco, vamos a instalar Rancher para crear y administrar un swarm de dockerhosts así como para explorar las funcionalidades que puede aportar a nuestros despliegues de Docker swarm.

¿Que es Rancher? es una plataforma de gestión de contenedores que nos permite su despliegue y control en cualquier entorno, desde nuestros propios servidores, ya sean físicos o virtuales o en entornos cloud. Además proporciona una gran cantidad de funcionalidades adicionales que pueden ser desplegadas desde diferentes catálogos, lo que permite añadir nuevas herramientas a nuestros despliegues de forma rápida y sencilla.

De forma muy resumida, la unidad de trabajo básica de Rancher es el entorno, cada uno de los cuales puede utilizar un tipo de orquestación y que contendrá los hosts asociados a dicho entorno. Como siempre, para una información más detallada y mucho mejor que esta, os recomiendo visitar la página oficial de Rancher.

Después de un poco de rollo teórico vamos a instalar Rancher, para lo cual he seguido las instrucciones de instalación dadas en esta página para un entorno multinodo, en el cual he desplegado cuatro máquinas virtuales, siendo una de ellas el servidor de base de datos y las otras tres los nodos donde he instalado Docker.

Para comenzar la instalación, solo necesitamos lanzar el siguiente comando en al menos uno de los hosts:
Instalación del nodo servidor de Rancher.
Como es lógico este comando descargará la imagen de correspondiente de Docker Hub y creará un contenedor para nuestro servidor Rancher, el cual conectará con el servidor de base de datos indicado en los parámetros del comando docker run. Tras ejecutar el comando anterior podemos comprobar que hay un contenedor en nuestro host que se corresponde con el servidor Rancher:

Host con el contenedor del servidor Rancher.






A continuación ya podremos acceder a la consola de administración de Rancher, con lo que solo necesitamos lanzar un navegador y acceder al puerto 8080 del host donde hemos lanzado el contenedor del servidor Rancher. Al acceder por primera vez a la consola nos encontraremos con una imagen como la siguiente:

Conosla de administración de Rancher.
En este punto, lo primero es configurar el control de acceso a la consola y configurar el método de autenticación que vayamos a utilizar. En nuestro ejemplo, usaremos autenticación local por sencillez. Para configurar el control de acceso solo tenemos que acceder a la sección Access Control dentro del menú ADMIN y crear la cuenta de usuario con derechos de administración que vayamos a utilizar:

Configuración del control de acceso a la consola de Rancher.
A continuación debemos crear un nuevo entorno usando la plantilla disponible para Docker swarm. Para crearlo solo es necesario pinchar sobre el botón Add Environment desde la sección Manage Environments del menú Default, que nos indica cual es el entorno que estamos gestionando:

Ventana para la gestión de entornos en Rancher.
Creación de un entorno Docker Swarm
Tras crearlo, ahora veremos nuestros dos entornos disponibles en la ventana de gestión de entornos y que el entorno por defecto es el entorno llamado Default:

Entornos disponibles tras la creación del entorno para Swarm.
Ambos entornos se encuentran en estado Unhealthy ya que no hemos añadido hosts a ninguno de ellos. Por tanto, el siguiente paso consiste en añadir hosts a la infraestructura de nuestro nuevo entorno, para ello solo tenemos que cambiar al entorno Swarm test lab y acceder a la sección Hosts del menú INFRASTRUCTURE para añadir nuestros dockerhosts. El proceso, muy resumido, podemos verlo en las siguientes imágenes:


Definición de la infraestructura para establecer nuestro Swarm. Rancher indica que debemos añadir hosts.
Añadimos un dockerhost a la infraestructura de nuestro entorno Docker Swarm.
En la pantalla para añadir un nuevo host a la infraestructura, es recomendable incluir la dirección IP del host para asegurar que no haya problemas de comunicación, sobre todo al registrar el dockerhost que contiene el propio servidor de Rancher.

Es muy importante recordar que estamos creando un swarm con varios dockerhosts, con lo que es necesario que creemos las reglas necesarias en los firewalls de cada nodo para asegurar el correcto funcionamiento del swarm. Relacionado con esta correcta configuración del cortafuegos de los dockerhosts, un punto importante a tener en cuenta para registrar correctamente el dockerhost donde se está ejecutando el contenedor con el servidor Rancher, es que debemos añadir el interfaz docker0 a la zona trusted del firewall o bien definir las reglas correspondientes para permitir las conexiones a la dirección IP física del host teniendo en cuenta el interfaz docker0 y las conexiones salientes desde el contenedor agente.

Una vez que hayamos realizado los pasos anteriores para todos nuestros nodos virtuales, incluyendo el dockerhost en el que se encuentra el propio servidor de Rancher, la infraestructura de nuestro entorno será similar a la siguiente:

Infraestructura de nuestro entorno Docker swarm con tres dockerhosts.

Revisando la imagen anterior, ¿que es lo que ha hecho Rancher? Pues como vemos ha creado un swarm en el que todos los hosts tiene el rol de manager y ha desplegado en ellos una serie de contenedores que implementan los servicios de infraestructura necesarios. Desde el menú SWARM podremos comprobar que el estado de toda la infraestructura del entorno es correcta:

Infraestructura del entorno swarm.
Servicios de infraestructura desplegado por Rancher en el swarm.
Como veremos en entradas futuras sobre Rancher, cada uno de estos servicios de infraestructura desempeñan una función determinada para el correcto funcionamiento de nuestro entorno y Rancher los implementa mediante un contenedor dedicado en cada dockehost.

En este punto tenemos un swarm el cual está controlado por Rancher, con lo que el siguiente paso es desplegar un servicio simple. Para esto, basta con acceder a la sección Containers del menú INFRASTRUCTURE y pinchar sobre Add Container:

Apartado contenedores del entorno docker swarm.
Al crear un contenedor a partir de una imagen, nos encontramos con todas las opciones disponibles en línea de comandos cuando estamos administrando Docker. Así, para nuestro ejemplo tenemos lo siguiente:

Definición de parámetros de configuración de un contenedor.
Como vemos, en las diferentes pestañas tenemos las opciones de configuración disponibles para nuestro contenedor. Estableciendo una configuración básica para nuestro ejemplo y pinchando sobre el botón Create se seguirá el proceso de descargar la imagen de Docker Hub y crear el contenedor con la configuración que hemos especificado. Una vez creado Rancher nos mostrará las estadísticas de rendimiento del contenedor así como sus parámetros de configuración:

Estadísticas de uso de nuestro contenedor.
Este contenedor no lo hemos definido como un servicio y por tanto, solo será accesible desde el nodo en el cual se esté ejecutando. Para crear un servicio debemos crear un stack, para lo cual debemos definir un archivo docker-compose.yaml que contenga la descripción de nuestro servicio o bien, usar uno de los servicios de infraestructura que Rancher ha desplegado al crear nuestro swarm. Este servicio de infraestructura se llama Portainer y se encuentra disponible en el menú SWARM:

Acceso a Portainer desde el menú SWARM.
Pantalla de acceso al interfaz de administración Portainer.
Portainer es un interfaz gráfico que nos permite administrar entornos Docker y está incluido como uno de los servicios de infraestructura desplegados por Rancher. Una vez que accedemos al interfaz de portainer, la consola de administración es como podemos ver en la siguiente imagen:
Interfaz de administración de Portainer.
Usando Portainer, podemos desplegar un servicio de forma muy sencilla desde el apartado Services con solo especificar los parámetros de configuración necesarios para nuestro servicio:

Creación de un servicio desde Portainer.
Panel de control de los servicios desplegados.
Ahora desde el interfaz de Rancher, en la sección Containers de nuestra infraestructura vemos los contenedores que están ejecutándose:

Los contenedores de nuestro servicio vistos desde Rancher.
Por tanto, y en resumen, podemos crear y gestionar nuestros entornos Docker Swarm desde Rancher y lo más importante es que añade nuevas funcionalidades gracias a los servicios de infraestructura que despliega. 

Adicionalment nos permite tener un análisis de uso de los contenedores de nuestros servicios y controlarlos directamente, aunque desde mi punto de vista lo recomendable es que usemos Portainer directamente ya que nos da acceso a las acciones de servicio.

En las próximas entradas sobre Docker Swarm y Rancher desplegaremos servicios, describiéndolos con los ficheros compose correspondientes e investigaremos los servicios de infraestructura disponibles y como podemos utilizarlos.

NOTA IMPORTANTE: Es necesario establecer el parámetro de configuración max_allowed_packet de nuestra base de datos, si usamos MySQL o MariaDB, en al menos 32M para que Rancher pueda refrescar correctamente el catálogo de plugins y plantillas de los repositorios de Rancher. 

viernes, 9 de noviembre de 2018

Administración básica de Docker swarm - Parte I

Hoy, tras los dos entradas anteriores sobre Docker swarm, es buena idea que le demos un repaso a los comandos básicos de los que disponemos cuando estamos interactuando con un cluster de Docker swarm. Como vamos a ver, son muy similares a los que hemos estado utilizando en el caso de un dockerhost y nos permiten realizar las mismas tareas, con la única diferencia de que ahora se realizarán y afectarán a todos los hosts que forman nuestro swarm.

Lo primero a tener en cuenta es que los comandos debemos realizarlos desde un nodo manager del swarm, ya que son los nodos que coordinan las tareas de los nodos worker del cluster. De forma simple podemos consultar el rol de cada uno de los nodos del swarm con el comando docker node ls:
Nodos de un swarm y su rol.
Como vemos, la columna manager status, nos muestra que el nodo swarm-node1 es un nodo manager y por tanto desde este nodo ejecutaremos todos los comandos de administración del swarm. Como referencia, en general siempre será un nodo manager aquel en el que ejecutamos el comando docker swarm init para crear el swarm inicialmente.

Al ejecutar un comando de control de swarm en un nodo worker del mismo, recibiremos un mensaje de error como el siguiente:
Mensajes de error de nodos worker al ejecutar comandos swarm.
Con el comando docker node, podemos actuar sobre los nodos del swarm y realizar diferentes tareas sobre ellos. Por ejemplo podemos promover un nodo worker a manager usando el comando docker swarm promote, por ejemplo:

Convertimos un nodo worker en manager.
Con lo que ahora, el ejecutar de nuevo el comando docker node ls, la salida será la siguiente:

El swarm con un nodo manager adicional.
Paremos un momento para analizar la salida de este comando. Como vemos hay varias columnas con información sobre cada uno de los nodos del swarm, siendo las más importantes las columnas Status, Availability y Manager Status, siendo su significado el siguiente:
  • Columna Status, nos muestra el estado del nodo. Como es lógico esta columna nos indica si el nodo en cuestión está operativo y es alcanzable. Los estados posibles son Ready o Down.
  • Columna Availability. Esta columna nos indica si el nodo está disponible para recibir y ejecutar tareas. Un nodo que forma parte de un swarm puede estar en tres estados de disponibilidad:
    • Active, el nodo puede ejecutar tareas y recibir tareas nuevas.
    • Pause, el nodo no puede recibir tareas nuevas pero, aquellas tareas ya asignadas al mismo siguen ejecutándose.
    • Drain, el no nodo no puede recibir tareas nuevas y, aquellas tareas ya asignadas al mismo se detienen y se asignan a otro nodo.
  • Columna Manager Status. Esta columna nos muestras que nodos del swarm son nodos manager y de ellos cual es el nodo manger primario, indicado como Leader y todos los nodos manager secundarios se indican como Reachable.
Como es lógico siempre es buena idea tener más de un nodo manager en cualquier swarm ya que, de se modo, si el manager primario pasa a estar no disponible, cualquiera del resto de nodos manager secundarios, pasará a ser el nuevo manager primario que realizará las tareas de orquestación y asignación de tareas del swarm.

Del mismo modo que podemos promover un nodo worker a nodo manager con el comando docker node promote, también podemos despromocionarlo con el comando docker node demote.  

Como ya vimos en una entrada anterior, que un nodo tenga el rol manager no implica que no se ejecuten contenedores en el mismo. Si repetimos el despliegue del servicio web simple que realizamos en una entrada anterior, cambiando un poco los parámetros veremos como se distribuyen los contenedores en todos nuestrios nodos del swarm:
Creamos un servicio con 4 replicas.
Al inspeccionar donde están corriendo las réplicas de este servicio, veremos como ha desplegado el nodo manager las tareas:
Información sobre las réplicas del servicio en el swarm.
En este caso comprobamos que el nodo manager primario ha distribuido una réplica en cada uno de los nodos del swarm y por tanto, podemos acceder al servicio desde cada uno de los nodos de manera individual.

Ahora supongamos que necesitamos aumentar el número de réplicas de nuestro servicio porque, con las réplicas con las que inicialmente lo hemos desplegado, no es suficiente para el número de peticiones de nuestros clientes. Para estos casos usaremos el comando docker scale, el cual nos permite levantar réplicas adicionales de un servicio ya desplegado de una manera muy rápida y sin ningún corte en el servicio actual. Por ejemplo, pasemos nuestro servicio de 4 réplicas a 10:
Escalado del servicio a 10 réplicas.
Ahora, al comprobar el número de contenedores de este servicio usando el comando docker service ps, vemos que tenemos desplegados 10 contenedores entre todos los nodos del swarm:
Listamos las réplicas del servicio tras el escalado.
Del mismo modo, podemos escalar el servicio disminuyendo el número de réplicas del siguiente modo:
Reducción del número de réplicas de un servicio.
Por último, si queremos parar el servicio lo que tenemos que hacerlo es eliminarlo con el comando docker service rm:
Eliminación del servicio en el swarm.
En resumen hemos visto cómo administrar un swarm es muy similar a la administración de un dockerhost individual, como los comandos utilizados en swarm son muy parecidos a los utilizados con un dockerhost y sobre todo, hemos podido comprobar la potencia que nos proporciona para escalar servicios en caso de ser necesario de forma muy rápida y simple.

En las próximas entradas revisaremos los tipos de despliegue de servicios y veremos como montar volúmenes para conseguir persistencia en nuestros servicios. 

sábado, 27 de octubre de 2018

Docker swarm - Enrutamiento de servicios

Hola de nuevo, en el post anterior construimos un pequeño swarm de 4 nodos y desplegamos un servicio web muy simple. En dicho ejemplo veíamos como el manager creaba copias idénticas de nuestro servicio y las repartía entre los nodos que forman el swarm. Comprobamos que el puerto de nuestro servicio se publicaba en cada uno de los nodos y que, independientemente del nodo al que accediésemos, podíamos conectarnos con nuestro servicio.

En este post vamos a explicar, de manera muy resumida, como funciona la routing mesh en la que participan todos los nodos de un swarm y que nos permite acceder a un servicio independientemente del nodo en el que se encuentre corriendo. Para una explicación mucho mejor os recomiendo, como siempre, consultar la documentación de Docker y en concreto, el siguiente enlace.

Para comenzar vamos a desplegar de nuevo el servicio web simple que usamos especificando que queremos que el número de réplicas sea 1, con lo que el nodo manager desplegará el servicio en uno de los cuatro nodos del swarm:

Desplegamos el servicio web en el swarm.
Comprobamos en que nodo está corriendo el servicio.
Como vemos el contenedor está corriendo en el nodo 3 del swarm y si comprobamos los puertos en los que están escuchando los 4 nodos veremos que, en todos ellos, el puerto 443 está disponible en la red de servicio. Por tanto, si nos conectamos a cualquier nodo del swarm salvo el 3, comprobamos que efectivamente, nuestro servicio web está disponible:

Acceso al servicio web desde un nodo sin réplica.
En definitiva la pregunta que nos hacemos es, ¿como puedo acceder al servicio desde cualquier nodo del swarm si este solo está corriendo en uno de los nodos? La respuesta a esta pregunta es el sistema de enrutamiento del swarm.

Cuando creamos un swarm, todos los nodos del mismo participan en lo que Docker denomina una malla de enrutamieno de entrada (ingress routing mesh) mediante la cual, todos los miembros del swarm son capaces de enrutar las peticiones de conexión entrantes a los nodos donde realmente se encuentran los contenedores.

Esto quiere decir que, cuando desplegamos un servicio y publicamos un puerto, este puerto pasa a estar enlazado en los interfaces que hayamos definido como interfaces de datos en todos los hosts del swarm. El motor de Docker crea la malla de enrutamiento, que escucha en los puertos publicados en todos los hosts, y enruta cualquier petición entrante al swarm a dicho puerto hacia un contenedor activo, aunque este se encuentre en un host diferente.

De forma muy simplificada, podemos verlo del siguiente modo:

Malla de enrutamiento de entrada en un Docker swarm.
Por tanto, cada vez que llegue una petición a un host de nuestro swarm en un puerto publicado para un servicio, el nodo que reciba dicha petición lo enrutará a un contenedor activo aunque este se encuentre en otro host.

Como es lógico, necesitaremos balanceadores de carga para tener un único punto de acceso a nuestro swarm, lo cual veremos más adelante.

domingo, 21 de octubre de 2018

Como crear un cluster de Docker.

Hasta ahora, en todas las pruebas realizadas, hemos usado un solo dockerhost con el que hemos podido explorar algunas de las características que nos proprociona Docker.

Como sabemos, en un entorno productivo real, necesitaremos un cluster que nos asegure la alta disponibilidad de nuestros servicios. Por tanto hoy vamos a crear nuestro primer cluster de nodos dockerhost, con el cual podremos realizar pruebas más parecidas a un entorno real.

En un entorno Docker un grupo de dockerhosts trabajando conjuntamente, se denomina swarm. Algunas de sus características, de forma muy resumida, son:
  • En un swarm tenemos dos tipos de nodos, los nodos manager y los nodos worker. Los nodos manager se encargan del reparto de tareas entre todos los nodos worker, así como del control del estado del swarm, lo cual no quiere decir que en los nodos manager no corra ningún contenedor.
  • Veremos que podemos desplegar servicios o stacks de servicios, los cuales podremos definir mediante ficheros YAML.
  • Cada nodo enrutará el tráfico entre ellos para todas aquellas conexiones de entrada que se correspondan con servicios ejecutándose en otros nodos.
Hasta aquí la aburrida teoría la cual, como siempre, recomiendo ampliar visitando la documentación oficial de Docker y que intentaré ampliar en las próximas entradas.

Para construir un swarm básico necesitamos varios nodos con docker instalado, crear el swarm en uno de los nodos, lo que lo convertirá en un nodo manager y añadir el resto de nodos al swarm, que se añadirán como nodos worker.

En mi caso he utilizado cuatro máquinas virtuales CentOS 7 con dos tarjetas de red, una para formar la red de cluster entre los dockerhost y una red de servicio, para el acceso a los servicios proporcionados por los contenedores.

Para la configuración de los nodos, instalación de Docker y creación del swarm, he desarrollado un par de playbooks de Ansible, los cuales están disponibles en github para su consulta, modificación, uso y disfrute.

Así que tras instalar los nodos y ejecutar los playbooks correspondientes, tendremos un swarm de cuatro nodos. Como hemos dicho, hay un nodo manager en el swarm, que es desde el cual debemos lanzar todos nuestros comandos. Así, para comprobar el estado de nuestro swarm ejecutaremos el siguiente comando desde nuestro nodo manager:

Información sobre los nodos del swarm.
El comando docker node ls nos muestra el estado de todos los nodos que forman nuestro swarm y además, nos indica cuales son nodos manager, la versión del motor de docker de cada uno y su disponibilidad.

Como primera prueba sencilla, además de la cración del swarm, hoy vamos a desplegar un servicio simple web basado en una imagen con un servidor HTTP, para esto solo tenemos que lanzar el comando siguiente:
Creación de un servicio web simple.
De forma muy resumida, con el comando anterior hemos desplegado un servicio http basado en Apache que tiene tres réplicas distribuidas entre todos los nodos de nuestro swarm, usando como imagen la imagen disponible en el repositorio correspondiente de Docker Hub y publicando el puerto 443 de cada contenedor en cada uno de los hosts. Para comprobarlo solo tenemos que listar los servicios de nuestro swarm con el siguiente comando:

Lista de los servicios ejecutándose en el swarm.
Si inspeccionamos los contenedores que se están ejecutando en cada uno de los nodos del swarm, ejecutando el comando docker ps -a en cada uno de ellos, veremos lo siguiente:

Contenedores ejecutándose en los nodos del swarm.
Como vemos en la salida anterior, cada dos de los nodos worker del swarm está ejecutando un contenedor correspondiente a nuestro servicio, estando el tercero alojado en el nodo manager. Si ahora accedemos al servicio en nuestros nodos, podremos ver que la web se muestra correctamente y en cada caso muestra lo siguiente:
Web mostrada accediendo al nodo swarm-node1.
Web mostrada accediendo al nodo swarm-node2.
Para terminar, si quieremos eliminar el servicio, solo tendremos que ejecutar el siguiente comando en el manager de nuestro swarm:
Eliminando el servicio webserver del swarm.
Por tanto, como podemos ver, una vez que hemos creado un swarm tenemos que tener en cuenta los siguientes puntos:
  • Debemos interactuar con uno de los nodos manager del swarm para poder desplegar y controlar nuestros servicios.
  • Los contenedores se ejecutarán en cualquier nodo que forme parte del swarm, salvo que establezcamos algún tipo de limitación por nodo.
  • Al publicar un puerto de un servicio, dicho puerto estará disponible en la IP correspondiente del nodo físico que hayamos especificado como data-path en el momento de la creación del swarm.
  • Al crear un servicio simple, como el de este ejemplo, podremos especificar el número de réplicas que formarán dicho servicio y estas se distribuirán por todos los nodos que formen el swarm.
Con este ejemplo básico hemos visto como podemos comenzar a trabajar con swarms de Docker y, en las proximas entradas, exploraremos más detenidamente los tipos de despliegues y sus características, la comunicación entre los nodos que forman el swarm y como acceder a volúmenes para conseguir la persistencia de nuestros datos.