Archivo
Apache ZooKeeper
Apache ZooKeeper es un servicio de datos en estructura de árbol. El servicio es centralizado, replicado, de alta disponibilidad y escalable; y garantiza la integridad en accesos concurrentes y el orden de modificación de los datos de manera secuencial. El sistema está formado por un conjunto distribuido de instancias denominado quorum que sirven la misma información.
El servicio es centralizado porque solo una de las instancias en ejecución hace las veces de instancia maestra, es la única que puede modificar los datos y que los replica al resto de las instancias. Esto garantiza el orden de los cambios, la atomicidad transaccional y la integridad concurrente de la información. Cuando la instancia maestra cae, el algoritmo de elección de líder, decide qué instancia es la nueva instancia maestra. El acceso de lectura, sin embargo, puede hacerse a cualquiera de las instancias levantadas del sistema. Esto por un lado garantiza la disponibilidad, al poder cualquier nodo convertirse en líder, y el rendimiento y la escabilidad, al permitir poder añadir todas las instancias que queramos al quorum para repartir la carga. Este diseño lo hace más adecuado para situaciones en que la lectura de datos es mucho más habitual que la escritura (al menos 1:10 según la documentación).
El servicio es rápido porque los datos se encuentran en memoria de cada instancia y solo se replican a disco para garantizar su persistencia. También es muy sencillo, tanto en el modo en que almacena la información; como en el modo en que se accede a la misma, con un conjunto de operaciones que son muy básicas y reducidas en número.
La forma en que se estructuran, organizan y acceden los conjuntos de datos es en estructura de árbol. Muy parecido a lo que sería un sistema de ficheros clásico pero siendo todos los nodos iguales, sin que haya distinción entre directorios y ficheros: todos los nodos son accesibles, pueden contener datos y pueden tener nodos hijos. Cada nodo puede contener cualquier tipo de información ya que el acceso es binario, pero el sistema está diseñado para que sean de un tamaño moderado, unos pocos kilobytes como mucho.
Los clientes tienen configuradas una o varias de las instancias del quorum, que no tienen por qué ser todas los integrantes, y que son los que se encargan de presentar al cliente al líder en ese momento.
Los usos más habituales de este servicio es como repositorio de información de configuración y nombres, o para proveer mecanismos de sincronización (lock, mutex,…) para soluciones distribuidas.
Un ejemplo de uso que me parece muy apropiado puede ser como repositorio de configuración de un conjunto de componentes muy numeroso, por ejemplo los sistemas de red de una gran organización o los diferentes servicios de una granja de servidores. Cada nodo hoja de la estructura de árbol puede ser un sistema o servicio y la información que contiene su configuración o estado. Los nodos rama nos permiten organizar, agrupar y clasificar los sistemas o servicios de la manera más adecuada para la organización. La configuración de todos los sistemas o servicios se gestiona de manera centralizada (solo hay una configuración aún estando replicada), la solución es muy escalable y tiene alta disponibilidad (levantando más instancias podemos servir a más clientes) y es también deslocalizable (al permitir desplegar instancias en diferentes lugares buscando la idoneidad específica para cada cliente).
Es también común verla como mecanismo de sincronización o como monitor de soluciones distribuidas como en Druid, por ejemplo.
Docker
Docker es una plataforma para la virtualización de entornos a nivel de aplicación o software base en lugar de sistema operativo o máquina virtual. Docker permite definir las diferentes unidades de despliegue de la solución software, con sus componentes distribuidos y sus límites de interconexión con otras unidades, para permitir su despliegue apilado de tal manera que representen las diferentes capas de las soluciones.
La idea es que, en lugar de crear una máquina virtual completa para cada entorno con sus recursos virtuales y sistema operativo, sea el propio sistema operativo el que aísle y compartimente la ejecución de cada entorno, denominado container. El propio sistema operativo crea un entorno de ejecución aislado a nivel de sistema de ficheros, de red, de seguridad y ejecución; de tal manera que los diferentes entornos, aún ejecutando en el mismo sistema operativo, están aislados entre ellos o solo compartiendo aquellas partes que se deseen.
Docker para implementar su funcionalidad se basa en dos características del kernel de Linux, cgroups y namespaces, que permiten establecer criterios de prioridad de CPU, limitación de memoria o de operaciones de I/O o control de facturación en el primer caso; o aislar procesos, entornos de red, usuarios, sistemas de ficheros entre los diferentes entornos en el segundo.
Cada entorno en Docker en ejecución es un container, que se corresponde con el despliegue de una imagen, que contiene la definición del entorno, sus límites, puntos de interconexión con terceros y componentes software. Los containers pueden apilarse de tal manera que cada uno represente una capa de la solución final. La combinación apilada de containers se produce mediante la definición de los puntos de interconexión de los container, como pueden ser puertos de red, y la sobreposición de los sistemas de ficheros uno sobre otro, mediante UnionFS.
La posibilidad de dividir los diferentes componentes distribuidos y capas del aplicativo en diferentes containers apilables supone una gran ventaja tanto para desarrolladores como para técnicos de explotación. Por un lado las dependencias se resuelven dentro de los propios container de la solución por lo que dentro de un mismo sistema no hay incompatibilidades entre versiones y dependencias. Por otro, el proceso de despligue se modulariza y la nivelación de entornos de integración y productivos es mucho más sencilla, al basarse en el despliegue secuencial de estas unidades.
Las imágenes que se despliegan como containers pueden registrarse en directorios públicos o privados (dentro del ámbito de la organización) con Docker Hub. El servicio en la nube que registra, almacena, distribuye y da soporte social y colaborativo a la tarea de gestión de las diferentes imágenes. Este es el servicio que monetiza toda la idea. Secundo la opinión de D’Oh de que puede ser una excelente alternativa o mecanismo en el que basarse las futuras tiendas de aplicaciones o sistemas de paquetes de los sistemas operativos.
Aunque la tecnología está basada en características propias de Linux, existen versiones portadas a Windows o iOS, pero con un componente adicional de virtualización para dar soporte a estas funcionalidades de compartimentación que no existen, al menos de manera idéntica, en estos sistemas. Las plataformas de virtualización en la nube Amazon EC2 y Google Cloud también soportan de manera nativa Docker.
Ejemplo de arquitectura escalable
La gente de Octivi, a través de su arquitecto Antoni Orfin, nos hablan de cómo han conseguido servir mil millones de peticiones a la semana con una arquitectura relativamente sencilla basada en HAProxy, PHP, Redis y MySQL para un servicio de e-commerce.
El artículo está muy bien explicado, detallando la situación inicial, el por qué de cada decisión y el papel de cada componente. Muy interesante el hecho de que Redis sea quien realmente provee de datos al aplicativo, mientras MySQL es tan solo una capa de persistencia.
Configuration Management: Puppet
De entre las tareas más tediosas de la puesta en servicio se encuentran la actualización y configuración de los diferentes entornos. Estas tareas requieren la preparación de equipos con mucha experiencia y conocimiento tanto de los entornos técnicos como de lo entornos organizativos en que nos movemos. Pero una vez materializado ese conocimiento son tareas repetitivas y largas, y por lo tanto, muy propensas a error. Además de documentar y actualizar muy bien la situación de los entornos, es imprescindible automatizar estas tareas. No ya solo para evitar errores, sino también para escalar e igualar cuando el conjunto de entornos sea muy numeroso.
Para esta finalidad existen muchas soluciones. De las más conocidas en el mundo Open Source:
Todas son soluciones y basadas en código abierto (licencias Apache y GPL según cada caso), pero con una versión o servicio más completo de pago (modelo Freemium). Las más extendidas son las dos primeras, en especial Puppet que es la que tiene una comunidad más extensa, y por lo tanto una cobertura con módulos de sistemas y entornos mayor.
Puppet tiene un lenguaje de configuración propio basado en Ruby (aunque también permite el uso de Ruby directamente). La primera particularidad es que Puppet recibe una configuración de entorno final o definitiva y se encarga de decidir qué pasos tomar para llegar a ella; nosotros no definimos los pasos, sino el objetivo. Esto nos permite aplicar la misma configuración a entornos con configuraciones distintas, Puppet se encargará de igualar los diferentes entornos. Estas configuraciones son lo que Puppet llama Manifiest y se materializan en ficheros .pp.
Los ficheros .pp contienen descripciones de recursos. Cada recurso es una estructura con tipo, título y atributos que describe el estado final de un cierto elemento de configuración del entorno donde se aplica el manifiesto. Los recursos tienen una tipología propia y una estructura en clases para abarcar el conjunto de elementos o aspectos configurables en un entorno (servicios, ficheros, parametrizaciones del sistema…). Estas tipologías pueden extenderse con módulos específicos para cada elemento de software configurable (la lista se encuentra aquí). Los atributos son los valores que describen la configuración de dicho recurso. El título es el atributo que identifica al recurso de entre los de su clase (en el ejemplo: el path del fichero o el nombre del servicio). El siguientes es un ejemplo de manifiesto para la configuración de un Apache:
class apache { package { apache: ensure => installed } file { "httpd.conf": mode => 644, owner => root, group => root, path => "/etc/apache2/httpd.conf", source => "puppet://modules/files/httpd.conf", } service { apache2: ensure => true, enable => true, subscribe => [File["httpd.conf"], Package[apache]], } }
En el manifiesto anterior el estado final de configuración es aquél en el que se ha instalado el paquete de Apache, se ha copiado el fichero de configuración del repositorio de Puppet (se puede utilizar cualquier otra localización) y se ha habilitado el servicio. Nótese que el atributo, en este caso metaatributo, subscribe
indica que el recurso servicio va a ser informado de los cambios que se produzcan en los otros dos recursos; de esta manera se puede establecer orden o dependencia entre ellos. Los manifiestos pueden gestionar variables, variables de entorno, así como hacer uso de estructuras de control o de dependencia u orden.
Puppet puede instalarse con una estructura de agente y maestro, donde el maestro o maestros gestionan la configuración de los agentes, que están en los entornos configurables y que toman (pull) los cambios de los maestros. O bien, como un maestro independiente, que gestiona de manera autónoma el entorno en que se encuentra. Las consultas y aplicaciones de configuraciones se hacen mediante el comando puppet
del símbolo del sistema, aunque la versión Enterprise tiene una UI que facilita estas operaciones.
En las referencias incluyo el enlace a la documentación de Puppet (bastante completa en mi opinión), por si quieres conocer más acerca de él.
Referencias
Comparativa en Wikipedia
Review en InfoWorld
Introducción a Puppet en Puppet Labs
La foto ha sido tomada de aquí, bajo licencia CC
Esta entrada de Juan Francisco Adame Lorite está publicada bajo una licencia Creative Commons Atribución-CompartirIgual 3.0 Unported.