Elasticsearch es un motor de búsqueda y análisis distribuido: reparte cada índice en fragmentos (shards) entre varios nodos y guarda réplicas de cada uno, de modo que el clúster sigue respondiendo si un nodo cae. En este tutorial montarás un clúster de tres nodos en Ubuntu 24.04 con el paquete oficial de Elastic, usando la configuración de seguridad automática (TLS y contraseñas) y tokens de inscripción para unir los nodos. Al final crearás un índice replicado y comprobarás que el clúster tolera la caída de un nodo.

Requisitos previos

  • Tres servidores con Ubuntu 24.04 LTS, por ejemplo VPS de CubePath, con al menos 4 GB de RAM y 2 vCPU cada uno.
  • Una red privada entre ellos. En esta guía se usan estas direcciones y nombres de host:
NodoHostnameIP privada
1es-node-110.0.0.11
2es-node-210.0.0.12
3es-node-310.0.0.13
  • Un usuario no root con privilegios sudo en cada servidor.
  • UFW activo en los tres nodos.

Tres nodos es el mínimo recomendado: con tres nodos elegibles como maestro, el clúster mantiene el quórum (dos de tres) si uno falla.

Paso 1: Preparar los tres servidores

Ejecuta este paso en los tres nodos. Asigna a cada uno su hostname, porque Elasticsearch usa el nombre de host como nombre de nodo por defecto. En el nodo 1:

sudo hostnamectl set-hostname es-node-1

Repite con es-node-2 y es-node-3 en los otros servidores. A continuación, abre los puertos de Elasticsearch solo para la red privada: 9200 es la API HTTP y 9300 el transporte interno entre nodos:

sudo ufw allow from 10.0.0.0/24 to any port 9200 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 9300 proto tcp

Comprueba las reglas:

sudo ufw status
To                         Action      From
--                         ------      ----
9200/tcp                   ALLOW       10.0.0.0/24
9300/tcp                   ALLOW       10.0.0.0/24

Paso 2: Instalar Elasticsearch desde el repositorio oficial

También en los tres nodos, añade la clave GPG y el repositorio de Elastic para la rama 9.x:

sudo apt update
sudo apt install apt-transport-https ca-certificates curl gnupg
curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /etc/apt/keyrings/elasticsearch.gpg
echo "deb [signed-by=/etc/apt/keyrings/elasticsearch.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-9.x.list

Instala el paquete:

sudo apt update
sudo apt install elasticsearch

Durante la instalación se ejecuta la configuración de seguridad automática, que genera certificados TLS y una contraseña para el superusuario elastic. La salida incluye un bloque como este:

--------------------------- Security autoconfiguration information ------------------------------

Authentication and authorization are enabled.
TLS for the transport and HTTP layers is enabled and configured.

The generated password for the elastic built-in superuser is : 7Hq*...

...

Guarda la contraseña del nodo 1, que es la que usarás en el clúster. Las de los nodos 2 y 3 se descartarán al unirlos. El paquete no arranca el servicio todavía; no lo inicies en los nodos 2 y 3 hasta el paso 5.

Paso 3: Configurar y arrancar el primer nodo

En es-node-1, abre la configuración principal:

sudo nano /etc/elasticsearch/elasticsearch.yml

Define el nombre del clúster. Debe ser idéntico en los tres nodos:

cluster.name: cubepath-es

Al final del archivo está el bloque que añadió la configuración automática. Contiene cluster.initial_master_nodes: ["es-node-1"], http.host: 0.0.0.0 y una línea comentada #transport.host: 0.0.0.0. Por defecto la capa de transporte solo escucha en localhost, así que los otros nodos no podrían conectarse. Sustituye esa línea comentada por la IP privada del nodo:

transport.host: 10.0.0.11

Arranca Elasticsearch:

sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch

El primer arranque tarda un poco. Comprueba que responde usando la CA generada y la contraseña de elastic:

sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200
{
  "name" : "es-node-1",
  "cluster_name" : "cubepath-es",
  ...
  "tagline" : "You Know, for Search"
}

Si has perdido la contraseña, genera una nueva con sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic.

Paso 4: Generar un token de inscripción

Los nodos nuevos se unen al clúster con un token de inscripción que contiene la dirección del nodo existente y la huella de su CA. Genéralo en es-node-1:

sudo /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
eyJ2ZXIiOiI5LjAuMCIsImFkciI6WyIxMC4wLjAuMTE6OTIwMCJdLCJmZ3IiOiI...

El token caduca a los 30 minutos. Si se te pasa el tiempo, genera otro.

Paso 5: Unir los nodos 2 y 3

En es-node-2, antes de arrancar el servicio por primera vez, aplica el token. La herramienta sustituye los certificados autogenerados por los del clúster y configura discovery.seed_hosts:

sudo /usr/share/elasticsearch/bin/elasticsearch-reconfigure-node --enrollment-token your_enrollment_token

Responde y a la confirmación. Después edita la configuración:

sudo nano /etc/elasticsearch/elasticsearch.yml

Añade el mismo nombre de clúster y fija la dirección de transporte a la IP privada de este nodo:

cluster.name: cubepath-es
transport.host: 10.0.0.12

Si ya existe una línea transport.host en el bloque de seguridad, edítala en lugar de duplicarla. Arranca el servicio:

sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch

Repite el paso completo en es-node-3 con un token nuevo si el anterior ha caducado, usando transport.host: 10.0.0.13.

Paso 6: Verificar el clúster

Desde cualquier nodo, lista los nodos del clúster:

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/_cat/nodes?v&h=ip,name,node.role,master,heap.percent"
ip        name      node.role   master heap.percent
10.0.0.11 es-node-1 cdfhilmrstw *      21
10.0.0.12 es-node-2 cdfhilmrstw -      18
10.0.0.13 es-node-3 cdfhilmrstw -      17

El asterisco marca el maestro elegido. Consulta la salud del clúster:

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/_cluster/health?pretty"
{
  "cluster_name" : "cubepath-es",
  "status" : "green",
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  ...
}

green significa que todos los shards primarios y réplicas están asignados. yellow indica réplicas sin asignar y red, shards primarios sin asignar.

Paso 7: Dejar la configuración de descubrimiento definitiva

cluster.initial_master_nodes solo sirve para formar el clúster la primera vez y debe eliminarse una vez formado; si se queda, un nodo reiniciado con el disco vacío podría crear un clúster nuevo por su cuenta. Además, conviene que cada nodo conozca a los tres para que no dependa solo del nodo 1 al reiniciar.

En cada nodo, edita /etc/elasticsearch/elasticsearch.yml, borra o comenta la línea cluster.initial_master_nodes si existe y deja discovery.seed_hosts con los tres nodos (sustituye la línea que añadió la herramienta en los nodos 2 y 3):

discovery.seed_hosts: ["10.0.0.11:9300", "10.0.0.12:9300", "10.0.0.13:9300"]

Reinicia los nodos de uno en uno, esperando a que el estado vuelva a green antes de pasar al siguiente:

sudo systemctl restart elasticsearch

Paso 8: Crear un índice con shards y réplicas

Crea un índice de prueba con 3 shards primarios y 1 réplica de cada uno. Así cada nodo tendrá datos y cada shard existirá en dos nodos distintos:

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic -X PUT "https://localhost:9200/logs-demo?pretty" \
  -H 'Content-Type: application/json' \
  -d '{ "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }'

Indexa un documento:

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic -X POST "https://localhost:9200/logs-demo/_doc?pretty" \
  -H 'Content-Type: application/json' \
  -d '{ "message": "hola desde el clúster", "level": "info" }'

Mira cómo se han repartido los shards (p es primario y r réplica):

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/_cat/shards/logs-demo?v"
index     shard prirep state   docs store ip        node
logs-demo 0     p      STARTED    0  249b 10.0.0.12 es-node-2
logs-demo 0     r      STARTED    0  249b 10.0.0.13 es-node-3
logs-demo 1     p      STARTED    1  4.5kb 10.0.0.11 es-node-1
logs-demo 1     r      STARTED    1  4.5kb 10.0.0.12 es-node-2
logs-demo 2     r      STARTED    0  249b 10.0.0.11 es-node-1
logs-demo 2     p      STARTED    0  249b 10.0.0.13 es-node-3

Elasticsearch nunca coloca un primario y su réplica en el mismo nodo.

Paso 9: Probar la tolerancia a fallos

Detén Elasticsearch en es-node-3:

sudo systemctl stop elasticsearch

Desde es-node-1, consulta la salud del clúster:

sudo curl -s --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic "https://localhost:9200/_cluster/health?filter_path=status,number_of_nodes,unassigned_shards&pretty"
{
  "status" : "yellow",
  "number_of_nodes" : 2,
  "unassigned_shards" : 2
}

El clúster sigue aceptando lecturas y escrituras: las réplicas del nodo caído se han promovido a primarias donde hacía falta. Pasado un minuto (el retraso por defecto de index.unassigned.node_left.delayed_timeout), Elasticsearch recrea las réplicas que faltan en los nodos restantes y vuelve a green. Arranca de nuevo es-node-3 y comprueba que vuelve a unirse:

sudo systemctl start elasticsearch

Solución de problemas

  • El nodo 2 o 3 forma su propio clúster: se arrancó antes de aplicar el token. Detén el servicio, borra su directorio de datos (sudo rm -rf /var/lib/elasticsearch/*, solo en ese nodo nuevo y sin datos), vuelve a ejecutar elasticsearch-reconfigure-node y arráncalo.
  • elasticsearch-reconfigure-node no conecta con el nodo 1: comprueba que el puerto 9200 del nodo 1 es accesible desde la red privada y que el token no ha caducado.
  • Fallos de bootstrap checks al arrancar: al escuchar en una IP que no es localhost, Elasticsearch aplica comprobaciones de producción. Revisa sudo journalctl -u elasticsearch y /var/log/elasticsearch/cubepath-es.log para ver cuál falla.
  • Estado yellow permanente: el índice pide más réplicas de las que caben. Revisa el motivo con GET _cluster/allocation/explain.

Conclusión

Tienes un clúster de Elasticsearch de tres nodos en Ubuntu 24.04 con TLS en HTTP y transporte, autenticación y shards replicados que sobreviven a la caída de un nodo. Como siguientes pasos, crea usuarios con roles limitados en lugar de usar elastic desde las aplicaciones, define políticas de ciclo de vida (ILM) para rotar índices de logs, y configura snapshots periódicas a un repositorio S3 compatible.