Guía de despliegue y conceptos de clúster Zookeeper

Fundamentos de Zookeeper

Definición

Zookeeper es un proyecto de código abierto desarrollaod bajo la fundación Apache, diseñado para ofrecer servicios de coordinación en entornos distribuidos. Su función principal es actuar como un servicio centralizado que permite gestionar la configuración, sincronización y nomenclatura entre múltiples nodos distribuidos.

Arquitectura interna

Desde una perspectiva de patrones de diseño, Zookeeper implementa el patrón observador. El sistema mantiene un repositorio de datos que interesa a múltiples clientes distribuidos. Los clientes pueden registrarse como observadores y, cuando el estado de los datos cambia, Zookeeper se encarga de notificar a todos los suscriptores para que reaccionen en consecuencia. Esta arquitectura se resume en dos componentes esenciales: un sistema de almacenamiento jerárquico y un mecanismo de notificaciones automáticas.

Características principales

  • Topología maestro-esclavo: Un nodo actúa como líder (Leader) y los demás como seguidores (Follower).
  • Tolerancia a fallos: El clúster sigue operativo mientras más de la mitad de los nodos estén disponibles. Por ello se recomienda usar un número impar de servidores.
  • Consistencia global: Cada servidor mantiene una réplica idéntica de los datos, garantizando que cualquier cliente obtenga la misma información sin importar a qué nodo se conecte.
  • Orden de actualizaciones: Las peticiones de un mismo cliente se procesan secuencialmente según su orden de envío (FIFO).
  • Atomicidad: Cada operación de modificación se completa en su totalidad o falla completamente, sin estados intermedios.
  • Actualización en tiempo real: Los clientes pueden acceder a los datos más recientes dentro de un margen temporal reducido.

Modelo de datos

La estructura de almacenamiento de Zookeeper se asemeja a un sistema de archivos jerárquico tipo árbol, similar al de Linux. Cada nodo del árbol se denomina ZNode, con capacidad de almacenar hasta 1MB de información por defecto. Cada ZNode posee una ruta única que lo identifica dentro del árbol.

Proceso de elección del líder

Elección inicial

Cuando el clúster arranca por primera vez, los nodos inician un proceso de votación para seleccionar un líder:

  1. El primer nodo (nodo 1) arranca y se vota a sí mismo. Al no alcanzar la mayoría necesaria (más del 50%), permanece en estado LOOKING.
  2. El segundo nodo (nodo 2) se inicia. Ambos intercambian información de votación. El nodo 1 detecta que el identificador (myid) del nodo 2 es superior, por lo que transfiere su voto al nodo 2. Sin embargo, con solo 2 votos no se alcanza la mayoría, manteniéndose ambos en LOOKING.
  3. El tercer nodo (nodo 3) entra en funcionamiento. Los nodos 1 y 2 cambian sus votos hacia el nodo 3, quien acumula 3 votos, superando el umbral de mayoría. El nodo 3 se convierte en LEADING, mientras que los nodos 1 y 2 pasan a FOLLOWING.
  4. El cuarto nodo arranca y encuentra que los nodos existentes ya no están en estado LOOKING, por lo que acepta al líder actual y se une como FOLLOWING.
  5. El quinto nodo procede de igual manera, integrándose como seguidor.

Elección tras una falla

La elección de un nuevo líder también se activa cuando un nodo pierde comunicación con el líder actual o cuando se reinicia. Existen dos escenarios posibles:

  • El clúster ya tiene líder: El nodo que intenta elegir simplemente recibe la información del líder vigente, se connecta a él y sincroniza su estado.
  • No existe líder: Se inicia un proceso de votación basado en tres criterios jerárquicos:

Reglas de prioridad en la votación:

  1. Mayor Epoch (número de período del líder) gana.
  2. Si los Epoch son iguales, mayor ZXID (identificador de transacción) gana.
  3. Si Epoch y ZXID coinciden, mayor SID (identificador de servidor) gana.

Conceptos clave en la votación:

  • SID (Server ID): Identificador único de cada servidor en el clúster, equivalente al valor de myid.
  • ZXID (ZooKeeper Transaction ID): Identificador que marca cada cambio de estado del servidor. Puede variar entre nodos dependiendo de la velocidad de procesamiento de peticiones.
  • Epoch: Código que representa el período de mandato de cada líder. Se incrementa con cada nueva ronda de votación.

Despliegue del clúster Zookeeper

Para este despliegue se utilizarán tres servidores con la siguiente configuración:

Dirección IP Software
192.168.9.210 Zokoeeper
192.168.9.120 Zookeeper
192.168.9.140 Zookeeper

Preparación del entorno

Ejecutar en todos los servidores:

# Deshabilitar firewall y SELinux
systemctl disable --now firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# Instalar Java JDK
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
java -version

Instalación del paquete Zookeeper

En el servidor 192.168.9.210:

cd /opt
tar -zxf apache-zookeeper-3.6.4-bin.tar.gz
mv apache-zookeeper-3.6.4-bin /usr/local/zookeeper

Configuración del servicio

En el servidor 192.168.9.210, copiar y editar el archivo de configuración:

cd /usr/local/zookeeper/conf
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg

Contenido del archivo zoo.cfg:

# Intervalo de latido en milisegundos
tickTime=2000

# Tiempo máximo de conexión inicial (tickTime * 10 = 20s)
initLimit=10

# Tiempo límite de sincronización entre Leader y Follower (tickTime * 5 = 10s)
syncLimit=5

# Directorio de almacenamiento de datos
dataDir=/usr/local/zookeeper/data

# Directorio de logs
dataLogDir=/usr/local/zookeeper/logs

# Puerto de conexión para clientes
clientPort=2181

# Definición de nodos del clúster (formato: server.ID=host:puerto_sync:puerto_eleccion)
server.1=192.168.9.210:3188:3288
server.2=192.168.9.120:3188:3288
server.3=192.168.9.140:3188:3288

El formato de cada línea server se compone de:

  • ID numérico: Identificador del servidor, debe coincidir con el contenido del archivo myid.
  • host: Dirección IP o hostname del servidor.
  • puerto_sync: Puerto usado por los Followers para intercambiar datos con el Leader.
  • puerto_eleccion: Puerto empleado durante el proceso de elección de un nuevo Leader.

Crear directorios y asignar el identificador del nodo:

cd /usr/local/zookeeper
mkdir -p data logs
echo 1 > data/myid

Replicación a los demás servidores

Transferir el directorio completo a los otros dos servidores:

scp -r /usr/local/zookeeper root@192.168.9.120:/usr/local/
scp -r /usr/local/zookeeper root@192.168.9.140:/usr/local/

En el servidor 192.168.9.120, actualizar el myid:

echo 2 > /usr/local/zookeeper/data/myid

En el servidor 192.168.9.140, actualizar el myid:

echo 3 > /usr/local/zookeeper/data/myid

Puesta en marcha del clúster

Iniciar el servicio en los tres servidores:

cd /usr/local/zookeeper/bin
./zkServer.sh start

# Verificar que el puerto 2181 esté activo
ss -tlnp | grep 2181

Consultar el rol de cada nodo dentro del clúster:

./zkServer.sh status

El orden de arranque determina qué nodo asume el rol de Leader y cuáles quedan como Followers, dependiendo del mecanismo de elección descrito anteriormente.

Etiquetas: Zookeeper Distributed Systems clúster Apache java

Publicado el 7-7 19:09