Ingeniería

Una nueva era para la coordinación de clusters en Elasticsearch

Una de las razones por las que Elasticsearch se ha vuelto tan popular es por lo bien que escala desde un pequeño cluster con tan solo algunos nodos hasta un cluster grande con cientos de nodos. El subsistema de coordinación de clusters está en su centro. La versión 7 de Elasticsearch contiene un nuevo subsistema de coordinación de clusters que ofrece muchos beneficios en comparación con versiones anteriores. Este artículo cubre las mejoras a este subsistema en la versión 7. Describe cómo usar este nuevo subsistema, cómo los cambios afectan las actualizaciones desde la versión 6 y cómo estas mejoras previenen que inadvertidamente pongas en riesgo tus datos. Concluye con una parte de la teoría que describe cómo funciona el subsistema.

¿Qué es la coordinación de cluster?

Un cluster de Elasticsearch puede desempeñar muchas tareas que requieran que una cantidad de nodos trabajen juntos. Por ejemplo, cada búsqueda debe enrutarse a los shards correctos para garantizar que los resultados sean precisos. Cada réplica debe actualizarse cuando indexas o eliminas algún documento. Cada solicitud de cliente debe reenviarse desde el nodo que la recibe hacia los nodos que pueden gestionarla. Cada nodo tiene su propia visión general del cluster para poder realizar búsquedas, indexar y realizar otras actividades coordinadas. Esta visión general se conoce como el [estado de cluster] (https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-state.html). El estado de cluster determina cuestiones como los mapping y las configuraciones para indexación, los shards que se asignan a cada nodo y las copias de los shards que están en sincronización. Es muy importante que esta información sea consistente en todo el cluster. Muchas características recientes, incluidas la replicación basada en número de secuencia y la replicación entre clusters funcionan correctamente solo porque pueden confiar en la consistencia del estado del cluster.

El subsistema de coordinación funciona al elegir un nodo particular para que sea el maestro del cluster. Este nodo maestro seleccionado garantiza que todos los nodos en su cluster reciban actualizaciones del estado del cluster. Esto es más difícil de lo que parece a primera vista porque los sistemas distribuidos como Elasticsearch deben estar preparados para ocuparse de muchas situaciones extrañas. En ocasiones, los nodos se ejecutan lentamente, pausan para recolectar basura o pierden poder repentinamente. Las redes sufren particiones, pérdida de paquete, períodos de latencia alta o pueden entregar mensajes en un orden diferente del orden en que se enviaron. Pueden ocurrir más de uno de estos problemas a la vez y pueden ocurrir de manera intermitente. A pesar de todo esto, el sistema de coordinación de cluster debe poder garantizar que cada nodo tenga una visión consistente del estado del cluster.

Lo que es importante, Elasticsearch debe ser resistente a las fallas de nodos individuales. Logra su resistencia al considerar que las actualizaciones de estado de cluster fueron exitosas después de que un quorum de nodos las haya aceptado. Un quorum es un subconjunto de los nodos aptos como maestro en un cluster. La ventaja de requerir solo un subconjunto de los nodos para responder es que algunos de los nodos pueden fallar sin afectar la disponibilidad del cluster. Los quorums deben seleccionarse cuidadosamente para que los clusters no puedan seleccionar dos maestros independientes que tomen decisiones inconsistentes que lleven a la pérdida de datos en última instancia.

Generalmente, recomendamos que los clusters tengan tres nodos aptos para maestro para que, si uno de los nodos falla, los otros dos puedan formar un quorum de forma segura y progresar. Si un cluster tiene menos de tres nodos aptos para maestro, no puede tolerar la pérdida de ninguno de forma segura. A la inversa, si un cluster tiene muchos más de tres nodos aptos para maestro, entonces las selecciones y las actualizaciones del estado de cluster pueden llevar más tiempo.

¿Evolución o revolución?

Las versiones 6.x y anteriores de Elasticsearch usan un subsistema de coordinación de cluster llamado Zen Discovery. El subsistema ha evolucionado y madurado a lo largo de los años y potencia con éxito los clusters tanto grandes como pequeños. Sin embargo, estas son algunas mejoras que queríamos hacer, las cuales requirieron cambios más fundamentales en lo concerniente a la forma de trabajo.

Zen Discovery permite que el usuario elija cuántos nodos aptos para maestro forman un quorum mediante la configuración discovery.zen.minimum_master_nodes. Es de vital importancia ajustar esta configuración correctamente en cada nodo y actualizarla correctamente a medida que el nodo escala dinámicamente. Para el sistema no es posible detectar si un usuario ha ajustado mal esta configuración y, en la práctica, es muy fácil olvidar ajustarla después de agregar o eliminar nodos. Zen Discovery intenta proteger contra este tipo de error de configuración al esperar unos segundos en cada selección de maestro y, generalmente, también es bastante conservador con otros tiempos de espera. Esto significa que si el nodo maestro seleccionado falla, el cluster no está disponible por al menos unos segundos cruciales antes de elegir un reemplazo. Si el cluster no puede seleccionar un maestro en ese momento, en ocasiones puede ser muy difícil comprender por qué.

Para Elasticsearch 7.0, hemos repensado y reconstruido el subsistema de coordinación de cluster:

  • La configuración minimum_master_nodes se elimina para permitir a Elasticsearch elegir por sí mismo qué nodos pueden formar un quorum. 
  • Las selecciones de maestros típicos ahora requieren mucho menos de un minuto para completarse. 
  • Aumentar y reducir clusters se vuelve más seguro y deja mucha menos posibilidad para configurar el sistema de forma que pueda perder datos. 
  • Los nodos registran su estado con más claridad para ayudar a diagnosticar por qué no pueden unirse a un cluster o por qué no puede elegirse un maestro.

A medida que se agregan o eliminan nodos, Elasticsearch automáticamente mantiene un nivel óptimo de tolerancia a las faltas mediante la actualización de la configuración de voto del cluster. La configuración de voto es un conjunto de nodos aptos para maestro cuyos votos se cuentan al tomar una decisión. Generalmente, la configuración de voto contiene todos los nodos aptos para maestro del cluster. Los quorums son mayorías simples de la configuración de voto: todas las actualizaciones de estado de cluster requieren la aceptación de más de la mitad de los nodos en la configuración de voto. Como el sistema gestiona la configuración de voto y por lo tanto sus quorums, puede evitar cualquier posibilidad de error de configuración que podría llevar a la pérdida de datos, incluso si se agregaran o eliminaran los nodos.

Si un nodo no puede descubrir un nodo maestro ni ganar una selección por sí mismo, entonces, a partir de 7.0, Elasticsearch registrará periódicamente un mensaje de alerta que describa su situación actual con suficiente detalle para ayudar a diagnosticar muchos problemas comunes.

Además, Zen Discovery contaba con un modo de falla muy raro, registrado en la [página de estado de resistencia de Elasticsearch] (https://www.elastic.co/guide/en/elasticsearch/resiliency/current/index.html) como "Repeated network partitions can cause cluster state updates to be lost" ("Las reparticiones de red repetidas pueden causar que las actualizaciones se estado de cluster se pierdan"), lo que ya no puede suceder. Este artículo ahora está marcado como resuelto.

¿Cómo uso esto?

Si inicias unos nodos de Elasticsearch recién instalados con configuraciones completamente predeterminadas, automáticamente buscarán otros nodos que se estén ejecutando en el mismo host y formarán un cluster después de algunos segundos. Si inicias más nodos en el mismo host, de manera predeterminada también descubrirán este cluster y se unirán. Esto hace que sea igual de fácil iniciar un cluster de desarrollo multinodo con la versión 7.0 de Elasticsearch que con versiones anteriores.

Este mecanismo de formación de clusters totalmente automático funciona bien con un host único, pero no es lo suficientemente robusto para usarlo en producción u otros entornos distribuidos. Existe un riesgo de que los nodos no puedan descubrirse entre ellos con el tiempo y que, en cambio, formen dos o más clusters independientes. A partir de la versión 7.0, si quieres comenzar un nuevo cluster que tenga nodos en más de un host, debes especificar el conjunto inicial de nodos aptos para maestro que el cluster debería usar como configuración de voto en su primera selección. Esto se conoce como inicio de cluster y se requiere solo la primera vez que se forma el cluster. Los nodos que ya se han unido a un cluster almacenan la configuración de voto en sus carpetas de datos y reusan esa información después de un reinicio. Los nodos que recién se inician y que se están uniendo a un cluster existente pueden recibir información del maestro elegido del cluster.

Inicias un cluster ajustando la configuración cluster.initial_master_nodes con los nombres o direcciones de IP del conjunto inicial de nodos aptos para maestro. Puedes proporcionar esta configuración en la línea de comando o en el archivo elasticsearch.yml de uno o más de los nodos aptos para maestro. También necesitarás configurar el subsistema discovery para que los nodos sepan cómo encontrarse entre sí.

Si no se configura initial_master_nodes, los nodos nuevos se iniciarán esperando poder descubrir un cluster existente. Si un nodo no puede encontrar un cluster para unirse, periódicamente registrará un mensaje de advertencia que indique

no se ha descubierto el maestro todavía; este nodo no se ha unido previamente a un cluster iniciado (v7+),
y [cluster.initial_master_nodes] está vacío en este nodo

Ya no hay ninguna ceremonia especial requerida para agregar nuevos nodos aptos para maestro a un cluster. Simplemente, configura los nodos para descubrir el cluster existente, inícialos, y el cluster adaptará de manera segura y automática su configuración de voto cuando se unan nodos nuevos. También es seguro eliminar nodos simplemente deteniéndolos siempre que no detenga la mitad o más de la mitad de los nodos aptos para maestro al mismo tiempo. Si necesitas detener la mitad o más de la mitad de los nodos aptos para maestro, o si tienes necesidades de escalado y orquestación más complejas, existe un procedimiento de escalado más dirigido que usa una API para ajustar directamente la configuración de voto.

¿Cómo actualizo?

Puedes actualizar un cluster de Elasticsearch de la versión 6 a la versión 7 mediante una actualización continua o un reinicio de cluster completo. Recomendamos una actualización continua, dado que esto te permite realizar la actualización nodo por nodo mientras el cluster permanece disponible durante todo el proceso. Debes actualizar tu cluster de versión 6 a versión 6.7 antes de realizar una actualización continua a la versión 7. Un reinicio de cluster completo permite actualizar a la versión 7 a partir de cualquier versión 6.x, pero implica cerrar todo el cluster e iniciarlo nuevamente después. En cualquiera de los casos, se han realizado más cambios a Elasticsearch entre las versiones 6 y 7 que las mejoras en la coordinación de clusters que describimos aquí. Para garantizar una actualización sin problemas, siempre debes seguir cuidadosamente las instrucciones de actualización detalladas.

Si realizas una actualización continua, el arranque del cluster sucede automáticamente, con base en la cantidad de nodos en el cluster y la configuración minimum_master_nodes existente. Esto significa que es importante garantizar que esta configuración esté ajustada correctamente antes de comenzar la actualización. No hay necesidad de configurar initial_master_nodes aquí porque el inicio del cluster sucede automáticamente cuando se ejecuta una actualización continua. Los nodos aptos para maestro en la versión 7 preferirán votar por nodos de versión 6.7 en las elecciones de maestro, por lo que generalmente puedes esperar que se seleccione un nodo de versión 6.7 como maestro durante la actualización hasta que hayas actualizado todos los nodos aptos para maestro.

Si realizas una actualización de reinicio de cluster completo, debes iniciar el cluster actualizado como se describió anteriormente: antes de iniciar el cluster recientemente actualizado, primero debes configurar initial_master_nodes con los nombres o direcciones de IP de los nodos aptos para maestro.

En la versión 6 y anteriores, hay algunas otras configuraciones que permiten determinar el comportamiento de Zen Discovery en el espacio de nombre discovery.zen.*. Algunas de estas configuraciones ya no tienen efecto y se han eliminado. Otras se han renombrado. Si se ha renombrado una configuración, su nombre anterior ya no se usa en la versión 7, y deberás ajustar tu configuración para usar los nombres nuevos:

| Nombre viejo | Nombre nuevo | | --- | --- | | discovery.zen.ping.unicast.hosts | discovery.seed_hosts | | discovery.zen.hosts_provider | discovery.seed_providers | | discovery.zen.no_master_block | cluster.no_master_block |

El nuevo subsistema de coordinación de clusters tiene un nuevo mecanismo de detección de fallas. Esto significa que las configuraciones de detección de fallas de Zen Discovery en el espacio de nombre discovery.zen.fd.* ya no tienen efecto. La mayoría de los usuarios deberían usar la configuración predeterminada de detección de fallas en la versión 7 y posteriores, pero si necesitas hacer cambios, puedes hacerlo con la configuración cluster.fault_detection.*.

Primero la seguridad

En ocasiones, las versiones de Elasticsearch anteriores a 7.0 permitían que inadvertidamente realizaras una secuencia de pasos que, de manera insegura, ponían la consistencia del cluster en riesgo. En contraste, las versiones 7.0 y posteriores te pondrán totalmente al tanto de que podrías estar realizando una acción poco segura y requerirán confirmación de que realmente quieres continuar.

Por ejemplo, un cluster en Elasticsearch 7.0 no se recuperará automáticamente si más de la mitad de los nodos aptos para maestro se pierden. Es común contar con tres nodos aptos para maestro en un cluster, lo que permite a Elasticsearch tolerar la pérdida de uno de ellos sin tiempo de inactividad. Si se pierden permanentemente dos de ellos, el nodo restante no podrá progresar más de manera segura.

Las versiones de Elasticsearch anteriores a 7.0 permitían tranquilamente que un cluster se recuperara de esta situación. Los usuarios podían volver a ubicar su cluster en línea al iniciar nodos nuevos, vacíos y aptos para maestro para reemplazar cualquier cantidad de nodos perdidos. No es seguro realizar una recuperación automática de la pérdida permanente de la mitad o más de la mitad de nodos aptos para maestro porque ninguno de los nodos restantes tiene la seguridad de contar con una copia del último estado de cluster. Esto puede llevar a la pérdida de datos. Por ejemplo, puede haberse eliminado una copia del shard del conjunto en sincronización. Si ninguno de los nodos restantes lo sabe, entonces esa copia caducada del shard puede asignarse como primaria. La parte más peligrosa de esto era que los usuarios no estaban al tanto de que esta secuencia de acciones había puesto en peligro su cluster. Podían pasar semanas o meses antes de que un usuario notara alguna inconsistencia.

En Elasticsearch 7.0 y las versiones posteriores, se restringe mucho más este tipo de actividades inseguras. Los clusters preferirán mantenerse no disponibles en lugar de asumir este tipo de riesgo. En la excepcional situación de que no haya backup, todavía es posible ejecutar este tipo de operación insegura si fuera totalmente necesario. Solo requiere algunos pasos adicionales para confirmar que estés al tanto de los riesgos y para evitar la posibilidad de llevar a cabo una operación insegura por accidente.

Si has perdido más de la mitad de los nodos aptos para maestro, lo primero que debes intentar es volver a tener en línea los nodos aptos para maestro perdidos. Si los directorios de datos de los nodos siguen intactos, lo mejor que puedes hacer es iniciar nodos nuevos usando estos directorios de datos. Si esto es posible, entonces el cluster se formará de forma segura nuevamente usando el estado de cluster más actualizado.

Lo próximo que debes intentar es restaurar el cluster a partir de una snapshot reciente. Esto lleva al cluster a un buen estado conocido, pero pierde cualquier dato escrito desde que tomaste la snapshot. Puedes volver a indexar cualquier dato faltante porque conoces cuál es el período de tiempo perdido. Las snapshots son incrementales, por lo que puedes tomarlas con bastante frecuencia. No es inusual tomar una snapshot cada 30 minutos para limitar la cantidad de datos perdidos en tal recuperación.

Si ninguna de estas acciones de recuperación es posible, el último recurso es la herramienta de recuperación no segura elasticsearch-node. Esta es una herramienta de línea de comandos que puede ejecutar un administrador del sistema para realizar acciones no seguras, como seleccionar un maestro caducado de una minoría. Al mostrar explícitamente los pasos que pueden romper la consistencia, Elasticsearch 7.0 elimina el riesgo de causar involuntariamente la pérdida de datos a través de una serie de operaciones inseguras.

¿Cómo funciona?

Si estás familiarizado con la teoría de sistemas distribuidos, es posible que reconozcas la coordinación de clusters como un ejemplo de problema que se puede resolver usando consenso distribuido.  El consenso distribuido no se entendía muy ampliamente cuando comenzó el desarrollo de Elasticsearch, pero la tecnología ha avanzado de manera significativa en los últimos años.

Zen Discovery adoptó muchas ideas de los algoritmos de consenso distribuido, pero lo hizo de manera orgánica en lugar de seguir estrictamente el modelo que prescribe la teoría. También tiene tiempos de espera muy conservadores, que en ocasiones ralentizan la recuperación después de una falla. La introducción de un nuevo subsistema de coordinación de clusters en 7.0 nos dio la oportunidad de seguir el modelo teórico de manera más cercana.

La coordinación distribuida se conoce como un problema difícil de resolver correctamente. Dependemos en gran medida de métodos formales para validar nuestros diseños por adelantado, con herramientas automatizadas y brindando fuertes garantías en términos de corrección y seguridad. Puedes encontrar las especificaciones formales del nuevo algoritmo de coordinación de clusters de Elasticsearch en nuestro repositorio público de modelos formales de Elasticsearch. El módulo de seguridad central del algoritmo es simple y conciso, y existe una correspondencia individual directa entre el modelo formal y el código de producción en el repositorio de Elasticsearch.

Si estás familiarizado con el tipo de algoritmos de consenso distribuido que incluye Paxos, Raft, Zab y Viewstamped Replication (VR), el módulo de seguridad central te parecerá conocido. Modela un único registro reescribible y usa una noción de término maestro que es paralela a los votos de Paxos, los términos de Raft y las vistas de VR. El módulo de seguridad central y su modelo formal también cubren el inicio del cluster, la persistencia entre los reinicios del nodo y la reconfiguración dinámica. Todas estas características son importantes para garantizar que el sistema se comporte correctamente en todas las circunstancias.

En torno a este core teóricamente robusto, construimos una capa de liveness (https://en.wikipedia.org/wiki/Liveness) para garantizar que, sin importar qué fallas sucedan en el cluster, una vez que la red se reestablezca y haya nodos suficientes en línea, se seleccionará un maestro y se podrán publicar las actualizaciones de estado de los clusters. La capa de vida usa una cantidad de técnicas de última tecnología para evitar muchos problemas comunes. El programador de selección es adaptable y altera su comportamiento de acuerdo con las condiciones de la red para evitar un exceso de selecciones cuestionadas. Una ronda previa al voto estilo Raft suprime las elecciones que no se pueden ganar antes de que comiencen, con lo cual se evita la interrupción de nodos inapropiados. La detección de retrasos evita que los nodos interrumpan el cluster si se encuentran muy alejados del maestro. La detección de fallas bidireccional activa garantiza que los nodos en el cluster siempre puedan comunicarse mutuamente. La mayoría de las actualizaciones de estado de cluster se publican eficientemente como diffs pequeños, que evita la necesidad de copiar todo el estado del cluster de nodo a nodo. Los líderes que se cancelan con gracia abdicarán expresamente en beneficio de un sucesor de su elección, lo que reduce el tiempo de inactividad durante una conmutación deliberada al evitar la necesidad de una elección completa. Desarrollamos una infraestructura de prueba para simular eficientemente los efectos de las interrupciones patológicas que podrían durar segundos, minutos u horas, lo que nos permite verificar que el cluster siempre se recupere rápidamente una vez que se resuelve la interrupción.

¿Por qué no Raft?

Una pregunta que nos hacen seguido es por qué simplemente no “enchufamos” un algoritmo de consenso distribuido estándar como Raft. Hay unos cuantos algoritmos bien conocidos, y cada uno ofrece diferentes pros y contras. Los evaluamos cuidadosamente y nos inspiramos con toda la documentación que pudimos encontrar. Una de las pruebas de concepto tempranas usaba un protocolo mucho más cercano a Raft. Con esta experiencia, aprendimos que los cambios requeridos para integrarlo completamente con Elasticsearch eran bastante significativos. Muchos de los algoritmos estándar también requieren algunas decisiones de diseño que serían poco óptimas para Elasticsearch. Por ejemplo:

  • Con frecuencia, se estructuran en torno a un log de operaciones, mientras que el cluster de Elasticsearch se basa más naturalmente de manera directa en el estado del cluster en sí mismo. Esto habilita la optimización vital como batching (la combinación de operaciones relacionadas en una transmisión única) de manera más simple que si estuviera basada en operaciones.
  • Generalmente, tienen una capacidad relativamente restringida para aumentar o reducir clusters, lo que requiere una secuencia de pasos para lograr muchas tareas de mantenimiento, mientras que la coordinación de clusters de Elasticsearch puede realizar con seguridad reconfiguraciones aleatorias en un único paso. Esto simplifica el sistema alrededor al evitar estados intermedios problemáticos.
  • Generalmente se enfocan fuertemente en la seguridad, dejan abiertos los detalles de cómo garantizan la vida, y no describen la forma en que el cluster debería reaccionar si encuentra que un nodo no es saludable. Los controles de estado de Elasticsearch son complejos, luego de haber sido usados y refinados en el campo por muchos años, y era importante para nosotros preservar su comportamiento existente. De hecho, requirió mucho menos esfuerzo implementar las propiedades de seguridad del sistema que garantizar su vida. La mayor parte del esfuerzo de implementación se enfocó en las propiedades de vida del sistema.
  • Uno de los objetivos del proyecto era brindar soporte a una actualización continua sin tiempo de inactividad de un cluster 6.7 que ejecute Zen Discovery a un cluster de versión 7 que se ejecutara con el nuevo subsistema de coordinación. No parecía factible adaptar ninguno de los algoritmos estándar a uno que permitiera este tipo de actualizaciones continuas.

La implementación completa de fuerza industrial de un algoritmo de consenso distribuido requiere un esfuerzo significativo para desarrollarla y debe exceder lo que describe la documentación académica. Es inevitable que las personalizaciones se requieran en la práctica, pero los protocolos de coordinación son complejos, y cualquier personalización conlleva el riesgo de introducir errores. En última instancia, tenía más sentido, desde la perspectiva de ingeniería, tratar estas personalizaciones como si se desarrollara un protocolo nuevo.

Resumen

Elasticsearch 7.0 se envía con un nuevo subsistema de coordinación de clusters que es más rápido, más seguro y más simple de usar. Soporta actualizaciones continuas sin tiempo de inactividad desde 6.7, y proporciona la base para la replicación resistente de datos. Para probar el nuevo subsistema de coordinación de clusters, descarga la última versión 7.0 beta, consulta la documentación, pruébala y envíanos tus comentarios.