Alta disponibilidad en cluster Linux con Pacemaker
Hace bastante tiempo, hablamos de Corosync como sistema para gestión de un clúster de alta disponibilidad y os enseñé un par de entradas de como se configura en un cluster Proxmox:
Hoy vamos a hablar de Pacemaker. Pacemaker y Corosync son dos componentes clave en la construcción de clústeres de alta disponibilidad en sistemas Linux. Aunque a menudo se mencionan juntos y se utilizan conjuntamente, tienen roles y funcionalidades distintas dentro del ecosistema de alta disponibilidad. Os dejo una pequeña tabla comparativa:
Integración de Pacemaker y Corosync
En la práctica, Pacemaker y Corosync se utilizan juntos para formar una solución completa de alta disponibilidad. Aquí hay un ejemplo de cómo se complementan:
- Corosync:
- Configura y gestiona la comunicación entre los nodos del clúster.
- Detecta cuando un nodo falla y comunica este evento a Pacemaker.
- Pacemaker:
- Recibe la información de fallo de Corosync y toma decisiones sobre cómo reubicar los recursos.
- Ejecuta las acciones necesarias para recuperar los recursos en otros nodos del clúster.
En resumen, Corosync maneja la comunicación y la membresía del clúster, asegurando que todos los nodos tengan una visión coherente del estado del clúster. Pacemaker, por otro lado, se encarga de la gestión de recursos, asegurando que los servicios críticos se mantengan en funcionamiento incluso en caso de fallos de nodo.
Voy a centrarme en Pacemaker…
Pacemaker es un gestor de clúster de alta disponibilidad (HA) que se utiliza para asegurar la disponibilidad continua de servicios y aplicaciones en sistemas Linux. Su propósito principal es gestionar los recursos del clúster de manera que, en caso de fallo de uno de los nodos del clúster, los recursos sean movidos automáticamente a otro nodo para minimizar el tiempo de inactividad.
Características de Pacemaker
- Alta Disponibilidad:
- Asegura que los servicios estén siempre disponibles al moverlos automáticamente a otro nodo en caso de fallo.
- Escalabilidad:
- Puede manejar desde dos nodos hasta clústeres con decenas de nodos sin problemas de rendimiento significativos.
- Compatibilidad:
- Funciona con una variedad de sistemas operativos Linux y puede gestionar una amplia gama de servicios y recursos.
- Gestión de Recursos:
- Permite definir y gestionar recursos del clúster, como IPs virtuales, sistemas de archivos, servicios de base de datos, etc.
- Políticas de Recuperación:
- Soporta políticas de recuperación configurables para determinar cómo y cuándo los recursos deben ser recuperados.
- Integración con Corosync:
- Pacemaker se suele utilizar junto con Corosync para proporcionar la infraestructura de comunicación necesaria para la gestión del clúster.
Componentes de Pacemaker
- Cluster Information Base (CIB):
- Almacena la configuración y el estado del clúster, replicando esta información en todos los nodos para mantener la coherencia.
- Resource Agents:
- Scripts que encapsulan el conocimiento necesario para gestionar un recurso específico. Pacemaker utiliza estos agentes para iniciar, detener y monitorizar los recursos del clúster.
- Cluster Resource Manager (CRM):
- Toma decisiones sobre la gestión de recursos basadas en la información del CIB y en las políticas configuradas por el administrador del clúster.
- Fencing:
- Mecanismo utilizado para aislar un nodo defectuoso del resto del clúster para asegurar la integridad de los datos.
Instalación y Configuración Pacemaker en LXC Proxmox
Como sin ejemplos, no vamos a aprender nada, vamos a generar unos LXC Proxmox basados en Debian 12 con una página web, y haremos pruebas de caídas y validaciones. Vamos al lío…
Partimos de tener dos nodos Proxmox, vamos a crear un contenedor LXC en cada host:
Requisitos cluster Linux
- Proxmox VE: Un clúster de Proxmox VE con al menos dos nodos.
- Contenedores LXC: Dos contenedores LXC basados en Debian 12.
- Pacemaker y Corosync: Instalados en los contenedores LXC.
Generamos los contenedores LXC Debian con IPs 192.168.2.12, 192.168.2.13 y 192.168.2.14 para el Qourum / IP Virtual:
Yo he clonado uno de ellos:
Lo he generado en el otro nodo:
Y luego he cambiado la IP:
Para que corosync corra en un container LXC Proxmox, es necesario agregar unos parámetros a los containers, lo haré en su fichero .conf (/etc/pve/lxc/ID-CONTAINER.conf):
1 2 3 4 |
lxc.apparmor.profile: unconfined lxc.cap.drop: lxc.cgroup.devices.allow: a lxc.mount.auto: proc:rw sys:rw |
Si no hacéis esto, os podéis encontrar con que el servicio Corosync no arranque, por ejemplo, y os de este tipo de error al intentar ejecutar el cluster:
1 2 3 4 5 6 |
root@PACEMAKER01:~# pcs cluster start --all pacemaker02: Error connecting to pacemaker02 - (HTTP error: 400) pacemaker01: Error connecting to pacemaker01 - (HTTP error: 400) Error: unable to start all nodes pacemaker02: Error connecting to pacemaker02 - (HTTP error: 400) pacemaker01: Error connecting to pacemaker01 - (HTTP error: 400) |
Con esto tengo todo preparado para lanzar comandos:
Lo primero que validamos que hay comunicación entre los contenedores LXC. Agregar estas IPs al fichero hosts de cada nodo o vuestro DNS (yo lo hago en el role del Mikrotik) para que entiendan también los nombres de las máquinas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
root@PACEMAKER01:~# ping 192.168.2.13 PING 192.168.2.13 (192.168.2.13) 56(84) bytes of data. 64 bytes from 192.168.2.13: icmp_seq=1 ttl=64 time=0.551 ms 64 bytes from 192.168.2.13: icmp_seq=2 ttl=64 time=0.501 ms ^C --- 192.168.2.13 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1046ms rtt min/avg/max/mdev = 0.501/0.526/0.551/0.025 ms root@PACEMAKER02:~# ping 192.168.2.12 PING 192.168.2.12 (192.168.2.12) 56(84) bytes of data. 64 bytes from 192.168.2.12: icmp_seq=1 ttl=64 time=0.047 ms 64 bytes from 192.168.2.12: icmp_seq=2 ttl=64 time=0.031 ms ^C --- 192.168.2.12 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1049ms rtt min/avg/max/mdev = 0.031/0.039/0.047/0.008 ms root@PACEMAKER01:~# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters # --- BEGIN PVE --- 192.168.2.12 PACEMAKER01.negu.local PACEMAKER01 192.168.2.13 PACEMAKER02.negu.local PACEMAKER02 # --- END PVE --- |
Instalamos los paquetes necesarios en cada nodo:
1 2 |
apt update apt install -y pacemaker pcs resource-agents |
Hacemos lo mismo con pacemaker:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
root@PACEMAKER01:~# systemctl restart pacemaker.service root@PACEMAKER01:~# systemctl enable pacemaker.service Synchronizing state of pacemaker.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable pacemaker root@PACEMAKER01:~# systemctl status pacemaker.service * pacemaker.service - Pacemaker High Availability Cluster Manager Loaded: loaded (/lib/systemd/system/pacemaker.service; enabled; preset: enabled) Active: active (running) since Wed 2024-06-05 16:47:08 UTC; 13s ago Docs: man:pacemakerd https://clusterlabs.org/pacemaker/doc/ Main PID: 3815 (pacemakerd) Tasks: 7 Memory: 31.1M CPU: 120ms CGroup: /system.slice/pacemaker.service |-3815 /usr/sbin/pacemakerd |-3816 /usr/lib/pacemaker/pacemaker-based |-3817 /usr/lib/pacemaker/pacemaker-fenced |-3818 /usr/lib/pacemaker/pacemaker-execd |-3819 /usr/lib/pacemaker/pacemaker-attrd |-3820 /usr/lib/pacemaker/pacemaker-schedulerd `-3821 /usr/lib/pacemaker/pacemaker-controld |
Habilitamos en cada nodo el siguiente servicio, y fijamos la contraseña del usuario hacluster:
1 2 3 |
root@PACEMAKER01:~# systemctl enable pcsd Synchronizing state of pcsd.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable pcsd |
Agregamos un usuario de gestión para cluster, al cual le ponemos una contraseña:
1 2 3 4 |
root@PACEMAKER01:~# passwd hacluster New password: Retype new password: passwd: password updated successfully |
Inicializamos el cluster:
1 2 3 4 5 6 7 |
root@PACEMAKER01:~# pcs cluster destroy Warning: It is recommended to run 'pcs cluster stop' before destroying the cluster. WARNING: This would kill all cluster processes and then PERMANENTLY remove cluster state and configuration Type 'yes' or 'y' to proceed, anything else to cancel: y Shutting down pacemaker/corosync services... Killing any remaining services... Removing all cluster configuration files... |
Autorizamos los nodos:
1 2 3 4 5 |
root@PACEMAKER01:~# pcs host auth pacemaker01 pacemaker02 Username: hacluster Password: pacemaker01: Authorized pacemaker02: Authorized |
Configuramos el cluster:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
root@PACEMAKER01:~# pcs cluster setup hacluster pacemaker01 pacemaker02 No addresses specified for host 'pacemaker01', using 'pacemaker01' No addresses specified for host 'pacemaker02', using 'pacemaker02' Destroying cluster on hosts: 'pacemaker01', 'pacemaker02'... pacemaker02: Successfully destroyed cluster pacemaker01: Successfully destroyed cluster Requesting remove 'pcsd settings' from 'pacemaker01', 'pacemaker02' pacemaker01: successful removal of the file 'pcsd settings' pacemaker02: successful removal of the file 'pcsd settings' Sending 'corosync authkey', 'pacemaker authkey' to 'pacemaker01', 'pacemaker02' pacemaker01: successful distribution of the file 'corosync authkey' pacemaker01: successful distribution of the file 'pacemaker authkey' pacemaker02: successful distribution of the file 'corosync authkey' pacemaker02: successful distribution of the file 'pacemaker authkey' Sending 'corosync.conf' to 'pacemaker01', 'pacemaker02' pacemaker01: successful distribution of the file 'corosync.conf' pacemaker02: successful distribution of the file 'corosync.conf' Cluster has been successfully set up. |
Esto hace que el fichero /etc/corosync/corosync.conf quede configurado de la siguiente forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
oot@PACEMAKER01:~# cat /etc/corosync/corosync.conf totem { version: 2 cluster_name: hacluster transport: knet crypto_cipher: aes256 crypto_hash: sha256 cluster_uuid: 01d2e5090dd746a184adccc6c275c8da } nodelist { node { ring0_addr: pacemaker01 name: pacemaker01 nodeid: 1 } node { ring0_addr: pacemaker02 name: pacemaker02 nodeid: 2 } } quorum { provider: corosync_votequorum two_node: 1 } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes timestamp: on } |
Arrancamos servicios del cluster, lo hacemos sobre uno de los nodos:
1 2 3 |
root@PACEMAKER01:~# pcs cluster start --all pacemaker01: Starting Cluster... pacemaker02: Starting Cluster... |
Habilitamos los servicios, también lo lanzamos en uno de los nodos:
1 2 3 |
root@PACEMAKER01:~# pcs cluster enable --all pacemaker01: Cluster Enabled pacemaker02: Cluster Enabled |
Comprobamos el estado del cluster:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
root@PACEMAKER01:~# pcs cluster status Cluster Status: Status of pacemakerd: 'Pacemaker is running' (last updated 2024-06-05 20:02:39Z) Cluster Summary: * Stack: corosync * Current DC: pacemaker01 (version 2.1.5-a3f44794f94) - partition with quorum * Last updated: Wed Jun 5 20:02:40 2024 * Last change: Wed Jun 5 20:01:18 2024 by hacluster via crmd on pacemaker01 * 2 nodes configured * 0 resource instances configured Node List: * Online: [ pacemaker01 pacemaker02 ] PCSD Status: pacemaker01: Online pacemaker02: Online |
Con esto ya tenemos nuestro cluster montado…ahora vamos a agregar un servicio apache y realizar validaciones.
Instalación servidor Apache para validar Pacemaker
Instalamos en cada nodo el servidor Apache:
1 2 |
root@PACEMAKER01:~# apt update root@PACEMAKER01:~# apt install -y apache2 |
Revisamos el estado:
1 2 3 4 5 6 7 8 9 10 |
root@PACEMAKER01:~# wget http://127.0.0.1/server-status --2024-06-06 14:36:28-- http://127.0.0.1/server-status Connecting to 127.0.0.1:80... connected. HTTP request sent, awaiting response... 200 OK Length: 4286 (4.2K) [text/html] Saving to: 'server-status' server-status 100%[=======================>] 4.19K --.-KB/s in 0s 2024-06-06 14:36:28 (811 MB/s) - 'server-status' saved [4286/4286] |
En uno de los contenedores, configuramos el recurso de Apache en Pacemaker:
1 |
root@PACEMAKER01:~# pcs resource create WebServer ocf:heartbeat:apache configfile="/etc/apache2/apache2.conf" statusurl="http://127.0.0.1/server-status" op monitor interval=30s |
Revisamos su estado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
root@PACEMAKER01:~# pcs status Cluster name: hacluster WARNINGS: No stonith devices and stonith-enabled is not false Status of pacemakerd: 'Pacemaker is running' (last updated 2024-06-06 13:33:04Z) Cluster Summary: * Stack: corosync * Current DC: pacemaker01 (version 2.1.5-a3f44794f94) - partition with quorum * Last updated: Thu Jun 6 13:33:04 2024 * Last change: Thu Jun 6 13:33:00 2024 by root via cibadmin on pacemaker01 * 2 nodes configured * 1 resource instance configured Node List: * Online: [ pacemaker01 pacemaker02 ] Full List of Resources: * WebServer (ocf:heartbeat:apache): Started [ pacemaker02 pacemaker01 ] Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled |
Configuramos una IP virtual que se moverá entre los contenedores en caso de fallo:
1 2 3 4 |
root@PACEMAKER01:~# pcs resource create VirtualIP ocf:heartbeat:IPaddr2 ip=192.168.2.14 cidr_netmask=24 nic=eth0 op monitor interval=30s root@PACEMAKER01:~# pcs constraint colocation add WebServer with VirtualIP INFINITY root@PACEMAKER01:~# pcs constraint order start VirtualIP then WebServer Adding VirtualIP WebServer (kind: Mandatory) (Options: first-action=start then-action=start) |
Reiniciamos el cluster:
1 2 3 4 5 6 7 |
root@PACEMAKER01:~# pcs cluster stop --all && pcs cluster start --all pacemaker02: Stopping Cluster (pacemaker)... pacemaker01: Stopping Cluster (pacemaker)... pacemaker02: Stopping Cluster (corosync)... pacemaker01: Stopping Cluster (corosync)... pacemaker01: Starting Cluster... pacemaker02: Starting Cluster... |
Ahora validamos el estado y la asignación de la IP Virtual. Os dejo unos cuantos comandos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
root@PACEMAKER01:~# pcs resource config VirtualIP Resource: VirtualIP (class=ocf provider=heartbeat type=IPaddr2) Attributes: VirtualIP-instance_attributes cidr_netmask=24 ip=192.168.2.14 nic=eth0 Operations: monitor: VirtualIP-monitor-interval-30s interval=30s start: VirtualIP-start-interval-0s interval=0s timeout=20s stop: VirtualIP-stop-interval-0s interval=0s timeout=20s root@PACEMAKER01:~# pcs constraint Location Constraints: Resource: WebServer Enabled on: Node: pacemaker01 (score:50) Ordering Constraints: start VirtualIP then start WebServer (kind:Mandatory) Colocation Constraints: WebServer with VirtualIP (score:INFINITY) Ticket Constraints: root@PACEMAKER01:~# pcs status Cluster name: hacluster WARNINGS: No stonith devices and stonith-enabled is not false Status of pacemakerd: 'Pacemaker is running' (last updated 2024-06-06 07:39:46Z) Cluster Summary: * Stack: corosync * Current DC: pacemaker01 (version 2.1.5-a3f44794f94) - partition with quorum * Last updated: Thu Jun 6 17:39:46 2024 * Last change: Thu Jun 6 17:38:59 2024 by root via cibadmin on pacemaker01 * 2 nodes configured * 2 resource instances configured Node List: * Online: [ pacemaker01 pacemaker02 ] Full List of Resources: * WebServer (ocf:heartbeat:apache): Started [ pacemaker02 pacemaker01 ] * VirtualIP (ocf:heartbeat:IPaddr2): Started Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled |
Podéis ir haciendo pruebas parando el servicio de apache en los nodos para ver si responde la ip virtual:
Donde se guarda la información del cluster Pacemaker
En un clúster gestionado por Pacemaker en Debian 12, la configuración de los recursos, incluidas las IPs virtuales, no se guarda en un único fichero de configuración como en otros sistemas. En cambio, Pacemaker utiliza una base de datos interna llamada CIB (Cluster Information Base) para almacenar toda la configuración del clúster, incluidos los recursos y sus restricciones.
Puedes exportar la información:
1 |
pcs cluster cib > /tmp/cib.xml |
Editar el fichero cib.xml y luego restaurarlo de la siguiente forma:
1 |
pcs cluster cib-push /tmp/cib.xml |
Destruir cluster Pacemaker
Si lo que necesitáis es destruir el cluster, os dejo un par de comandos (parar y destruir):
1 2 3 4 5 6 7 8 9 10 11 12 |
root@PACEMAKER01:~# pcs cluster stop --all pacemaker01: Stopping Cluster (pacemaker)... pacemaker02: Stopping Cluster (pacemaker)... pacemaker01: Stopping Cluster (corosync)... pacemaker02: Stopping Cluster (corosync)... root@PACEMAKER01:~# pcs cluster destroy --all Warning: Unable to load CIB to get guest and remote nodes from it, those nodes will not be deconfigured. pacemaker01: Stopping Cluster (pacemaker)... pacemaker02: Stopping Cluster (pacemaker)... pacemaker01: Successfully destroyed cluster pacemaker02: Successfully destroyed cluster |
Te ha gustado la entrada SGUENOS EN TWITTER O INVITANOS A UN CAFE?