Pacemaker es el gestor de recursos de clúster más usado en Linux: decide en qué nodo se ejecuta cada servicio y lo mueve a otro cuando algo falla. Corosync es la capa de comunicación que mantiene la lista de miembros del clúster y el quórum, y pcs es la herramienta de línea de comandos que configura ambos. En esta guía montarás un clúster de tres nodos en Ubuntu 24.04 que ofrece Nginx detrás de una IP virtual, configurarás el fencing (STONITH) y comprobarás que el servicio sobrevive a la caída de un nodo.

Cómo funciona el clúster

Antes de empezar conviene tener claros cuatro conceptos:

  • Quórum: un nodo solo puede ejecutar recursos si forma parte de una mayoría de votos. Con tres nodos, dos bastan para tener quórum, así que el clúster tolera la caída de uno. Con dos nodos no hay mayoría posible tras una partición y hace falta un caso especial (two_node), por eso se recomiendan tres.
  • Recursos: lo que gestiona Pacemaker. Aquí serán una IP virtual (agente ocf:heartbeat:IPaddr2) y el servicio de systemd de Nginx.
  • Restricciones y grupos: indican qué recursos deben ir juntos y en qué orden. Un grupo arranca sus recursos en orden y los mantiene en el mismo nodo.
  • Fencing o STONITH (Shoot The Other Node In The Head): cuando un nodo deja de responder, el clúster no puede saber si está caído o solo aislado. Antes de arrancar sus recursos en otro sitio, lo apaga de forma forzada, normalmente a través de su BMC (IPMI). Sin fencing, dos nodos podrían montar el mismo disco o anunciar la misma IP a la vez (split-brain).

Requisitos previos

Necesitas:

  • Tres servidores con Ubuntu 24.04 LTS, por ejemplo servidores dedicados o VPS de CubePath, con un usuario no root con privilegios sudo.
  • Una red privada común entre los tres. En esta guía se usan estas direcciones, sustitúyelas por las tuyas:
NodoIP privadaIP de la BMC (IPMI)
node110.0.0.1110.0.1.11
node210.0.0.1210.0.1.12
node310.0.0.1310.0.1.13
  • Una IP libre en la misma subred para la IP virtual: 10.0.0.100.
  • Para fencing en producción: acceso IPMI a la BMC de cada servidor físico, o un agente de fencing compatible con tu plataforma de virtualización.

Paso 1: Preparar los nodos

Ejecuta este paso en los tres nodos. Primero da a cada uno su nombre de host (cambia node1 en cada servidor):

sudo hostnamectl set-hostname node1

Haz que los nombres se resuelvan a las IP privadas, para que Corosync no dependa del DNS. Edita /etc/hosts:

sudo nano /etc/hosts

Añade estas líneas:

10.0.0.11 node1
10.0.0.12 node2
10.0.0.13 node3

Comprueba que el nombre propio no apunta a 127.0.1.1 (si existe una línea 127.0.1.1 node1, elimínala) y que los nodos se ven entre sí:

ping -c 2 node2

Corosync es sensible a los saltos de reloj, así que confirma que la hora está sincronizada. Ubuntu 24.04 usa systemd-timesyncd por defecto:

timedatectl status | grep synchronized
System clock synchronized: yes

Paso 2: Abrir los puertos del clúster

Si usas UFW, permite el tráfico del clúster solo desde la red privada, en los tres nodos. pcsd usa el puerto TCP 2224 y Corosync los puertos UDP 5404 y 5405:

sudo ufw allow from 10.0.0.0/24 to any port 2224 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 5404:5405 proto udp

Abre también HTTP para el servicio que publicará el clúster:

sudo ufw allow 80/tcp

Paso 3: Instalar Pacemaker, Corosync y pcs

En los tres nodos, instala los paquetes del clúster, los agentes de recursos y los agentes de fencing básicos. En Ubuntu 24.04 los agentes están divididos en paquetes -base (mantenidos en main) y -extra:

sudo apt update
sudo apt install pacemaker corosync pcs resource-agents-base fence-agents-base

El paquete pcs crea el usuario hacluster, que pcs usa para autenticarse entre nodos. Asígnale una contraseña, la misma en los tres nodos:

sudo passwd hacluster

Arranca el demonio pcsd y habilítalo en el arranque:

sudo systemctl enable --now pcsd

Al instalarse, Ubuntu arranca Corosync con una configuración por defecto de un solo nodo. Elimínala en los tres nodos para que pcs pueda crear la del clúster real:

sudo pcs cluster destroy
Shutting down pacemaker/corosync services...
Killing any remaining services...
Removing all cluster configuration files...

Paso 4: Crear el clúster

Los comandos de este paso se ejecutan solo en node1. Primero autentica los tres nodos con el usuario hacluster:

sudo pcs host auth node1 node2 node3 -u hacluster
Password:
node1: Authorized
node2: Authorized
node3: Authorized

Crea el clúster, indicando explícitamente la IP privada de cada nodo para Corosync:

sudo pcs cluster setup cubecluster \
    node1 addr=10.0.0.11 \
    node2 addr=10.0.0.12 \
    node3 addr=10.0.0.13

Este comando genera /etc/corosync/corosync.conf con el transporte knet y lo distribuye a los tres nodos. Arranca el clúster en todos ellos y habilítalo para que arranque con el sistema:

sudo pcs cluster start --all
sudo pcs cluster enable --all

Comprueba el estado de Corosync y el quórum:

sudo corosync-quorumtool -s
Quorum information
------------------
Nodes:            3
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2

Quorate: Yes confirma que el clúster tiene mayoría. Mira el estado general con:

sudo pcs status

Los tres nodos deben aparecer en Online. De momento verás un aviso de que no hay dispositivos STONITH configurados; lo resolverás en el siguiente paso.

Paso 5: Configurar el fencing (STONITH)

Pacemaker no arranca recursos mientras STONITH esté habilitado y no haya ningún dispositivo de fencing. En servidores físicos con BMC, el agente habitual es fence_ipmilan. Antes de configurarlo, comprueba desde node1 que llegas a la BMC de cada nodo (instala ipmitool si no lo tienes):

sudo apt install ipmitool
ipmitool -I lanplus -H 10.0.1.12 -U your_ipmi_user -P 'your_ipmi_password' chassis power status
Chassis Power is on

Crea un dispositivo de fencing por nodo. pcmk_host_list indica qué nodo apaga cada dispositivo. Sustituye el usuario y la contraseña de IPMI:

sudo pcs stonith create fence-node1 fence_ipmilan \
    ip=10.0.1.11 username=your_ipmi_user password='your_ipmi_password' \
    lanplus=1 pcmk_host_list=node1
sudo pcs stonith create fence-node2 fence_ipmilan \
    ip=10.0.1.12 username=your_ipmi_user password='your_ipmi_password' \
    lanplus=1 pcmk_host_list=node2
sudo pcs stonith create fence-node3 fence_ipmilan \
    ip=10.0.1.13 username=your_ipmi_user password='your_ipmi_password' \
    lanplus=1 pcmk_host_list=node3

Evita que un nodo ejecute el dispositivo que sirve para apagarse a sí mismo:

sudo pcs constraint location fence-node1 avoids node1
sudo pcs constraint location fence-node2 avoids node2
sudo pcs constraint location fence-node3 avoids node3

Comprueba que los tres dispositivos están en Started:

sudo pcs stonith status

Prueba el fencing de verdad con un nodo, preferiblemente fuera de horario. El nodo se reiniciará de forma forzada:

sudo pcs stonith fence node3
Node: node3 fenced

Cuando node3 arranque de nuevo, volverá a unirse al clúster automáticamente porque lo habilitaste en el paso 4.

Paso 6: Crear la IP virtual y el servicio Nginx

Instala Nginx en los tres nodos y desactiva su arranque automático, porque a partir de ahora será Pacemaker quien decida dónde se ejecuta:

sudo apt install nginx
sudo systemctl disable --now nginx

Para distinguir qué nodo responde durante las pruebas, escribe el nombre del host en la página de inicio de cada nodo:

hostname | sudo tee /var/www/html/index.html

De vuelta en node1, crea la IP virtual dentro de un grupo llamado web, con una comprobación cada 10 segundos:

sudo pcs resource create vip ocf:heartbeat:IPaddr2 \
    ip=10.0.0.100 cidr_netmask=24 \
    op monitor interval=10s --group web

Añade Nginx al mismo grupo. Al ir después de la IP en el grupo, siempre arrancará en el mismo nodo que ella y una vez que la IP esté activa:

sudo pcs resource create nginx systemd:nginx \
    op monitor interval=20s --group web

Configura una adherencia (stickiness) por defecto para que los recursos no vuelvan automáticamente a su nodo original cuando este se recupere, lo que evitaría un segundo corte innecesario:

sudo pcs resource defaults update resource-stickiness=100

Comprueba dónde se está ejecutando el grupo:

sudo pcs status resources
  * Resource Group: web:
    * vip	(ocf:heartbeat:IPaddr2):	 Started node1
    * nginx	(systemd:nginx):	 Started node1

Desde otro equipo de la red privada, pide la página a la IP virtual:

curl http://10.0.0.100
node1

Paso 7: Probar el failover

Primero haz una prueba controlada poniendo node1 en espera (standby). Pacemaker moverá sus recursos a otro nodo:

sudo pcs node standby node1
sudo pcs status resources
  * Resource Group: web:
    * vip	(ocf:heartbeat:IPaddr2):	 Started node2
    * nginx	(systemd:nginx):	 Started node2

curl http://10.0.0.100 devolverá ahora node2. Devuelve node1 al servicio; gracias a la adherencia, los recursos se quedarán en node2:

sudo pcs node unstandby node1

A continuación simula un fallo del servicio. En el nodo que ejecuta el grupo, detén Nginx por fuera de Pacemaker:

sudo systemctl stop nginx

En menos de 20 segundos la operación de monitorización detectará el fallo y Pacemaker reiniciará Nginx en el mismo nodo. Lo verás en el historial de fallos:

sudo pcs resource failcount show nginx

Por último, prueba un fallo de nodo completo apagando el servidor que ejecuta el grupo (o desconectando su red privada). Los otros dos nodos mantienen el quórum, harán fencing del nodo perdido y arrancarán el grupo web en uno de ellos.

Si quieres mover el grupo a un nodo concreto a mano, por ejemplo antes de un mantenimiento, usa move y después clear para eliminar la restricción temporal que crea:

sudo pcs resource move web node3
sudo pcs resource clear web

Solución de problemas

Los recursos aparecen como Stopped y pcs status avisa de STONITH. No hay dispositivos de fencing o todos han fallado. Revisa sudo pcs stonith status y prueba el acceso IPMI con ipmitool desde otro nodo.

Un recurso queda en estado fallido y no vuelve a arrancar. Tras varios fallos, Pacemaker deja de intentarlo en ese nodo. Corrige la causa (mira journalctl -u nginx o sudo journalctl -u pacemaker) y limpia el contador:

sudo pcs resource cleanup nginx

El clúster pierde el quórum. Con corosync-quorumtool -s verás Quorate: No. Comprueba la conectividad entre nodos en los puertos UDP 5404-5405 y el estado de los enlaces de Corosync:

sudo corosync-cfgtool -s

Cada enlace debe aparecer como connected hacia los demás nodos.

La IP virtual está activa pero los clientes no llegan. La red filtra la IP virtual o los clientes tienen en caché la MAC antigua. Comprueba en el nodo activo que la IP está asignada con ip -brief addr y revisa si tu red permite IP no asignadas a la interfaz.

Conclusión

Tienes un clúster de tres nodos con Pacemaker y Corosync que mantiene quórum ante la caída de un nodo, aísla los nodos problemáticos con fencing y mueve una IP virtual y Nginx de forma automática. Como siguientes pasos puedes sustituir Nginx por HAProxy para balancear tráfico hacia tus servidores de aplicación, añadir almacenamiento compartido con los agentes LVM-activate y Filesystem, o exportar métricas del clúster a tu sistema de monitorización.