La alta criticidad en los entornos empresariales provoca la necesidad de redundar los entornos para hacerlos más tolerantes a fallas, Peacemaker es una solución para Linux de alta disponibilidad que puede ayudarnos a redundar entornos y mejorar la operabilidad.

En este post voy a explicar como crear un clúster HA con Pacemaker para dar soporte a una solución de centralita de teléfonos configurada con Asterisk. La idea es aprender como funciona Pacemaker, Asterisk solo lo utilizaré como servicio de ejemplo.
Entorno
Empecemos con el entorno. Mi consejo general en entornos como este es separar las máquinas físicamente en clúster diferentes, esto es un concepto básico de la alta disponibilidad en el que no entraremos en este post, sirve de poco configurar un clúster HA si las dos máquinas virtuales cuelgan del mismo servidor físico.
El sistema que os propongo se ha pensado para correr en un clúster virtual con dos equipos físicos de virtualización separados. Esto da al sistema de redundancia y capacidad de respuesta ante problemas relacionados con hardware, software, comunicaciones, mantenimiento o fallos.

También podemos crear un clúster de servidores que estén físicamente separados, o incluso dos máquinas aisladas, la idea es que sean equipos físicamente distintos y en sitios alejados.
Software
Ambos servidores cuentas con un software idéntico, el sistema base es una distribución Debian 9.9 Stretch. No hay restricciones aquí más allá de la compatibilidad con Pacemaker y Asterisk.
El software que controla las llamadas telefónicas es un Asterisk configurado con todas las extensiones necesarias para manejar los teléfonos. Es importante que la configuración esté en ambas máquinas, esto puede solventarse de muchas maneras, en el laboratorio he optado por la más fácil, rápida y menos aconsejable, he configurado uno y lo he copiado al otro :).
En mi caso hay dos servidores que ejecutan servicios críticos por lo tanto hay que configurarlos con el software de alta disponibilidad de forma que se organicen los servicios, se monitoricen y si hay algún problema, se pueda recuperar el servicio con el menor tiempo de fallo posible.
El software encargado de dotar al sistema de redundancia como os adelantaba es Pacemaker, un programa capaz de crear un clúster de nodos para poder dar recursos compartidos.
Se van a compartir dos recursos necesarios para poder soportar la caída de un nodo con relativa rapidez:
- Servicio de direccionamiento compartido (IP Virtual)
- Script de convergencia de telefonía IP
El primero es encargado de servir una única IP virtual que el sistema asigna al Maestro del clúster, y el segundo se encarga de reconfigurar los sistemas de telefonía para reducir la convergencia de registro en el nuevo servidor (de esto me di cuenta después de montarlo 😝).

Podemos realmente organizar nuestra alta disponibilidad de dos maneras, como un clúster Activo-Activo o como Activo-Pasivo. ¿Y por qué no siempre en Activo-Activo y aprovechar mejor el rendimiento?, bueno en ocasiones esto no es posible dado que el aplicativo que queremos ejecutar es monolítico y no permite estas características.
Es el caso de Asterisk, ya que hay el estado de las conexiones que es complicado sincronizar entre dos servidores, por lo tanto hemos optado por usar la configuración Activo-Pasivo.

Recursos
Tenemos dos servidores que, según el Pacemaker, reciben el nombre de nodos.
Las IP flotantes son direcciones que no están asignadas a una máquina en concreto, sino que están encadenadas al servicio y el servidor que ejecute este servicio es el que ha de tener esa dirección. Por lo tanto, reciben el nombre de «direcciones flotantes» porque pueden ir de una máquina a otra dependiendo de donde esté el servicio que ejecutan.
Las dos máquinas tienen que ser capaces de ejecutar Asterisk. De forma que las dos tienen el servicio de voz instalado.
Por lo tanto, identificamos como recursos las IP flotante más el software a ejecutar para reducir la convergencia (script).
¿Qué es STONITH?
STONITH son las Siglas de “Shoot The Other Node In The Head” (“Pégale un Tiro en la Cabeza al otro Nodo”). Es una técnica usada por Peacemaker que se asegura de que un servidor supuestamente muerto no interfiera con el funcionamiento del clúster. En caso de no implementarse bien esta técnica, podría dar lugar a que el clúster no funcione, por tanto como no tiene sentido en un clúster de dos nodos, desactivamos esta función.
Quorum
Para que un clúster funcione como se espera, los nodos deben estar de acuerdo con ciertos hechos, como qué máquinas son actualmente miembros del clúster, dónde se ejecutan los servicios y qué máquinas están utilizando qué recursos.
El método en el que esto se implementa en el complemento de alta disponibilidad de Peacemaker es mediante el uso de un esquema de votación por mayoría. Cada nodo del clúster emite un voto si se une con éxito a la comunicación de red corosync y puede comunicarse con los otros nodos que ya participan en el clúster.
Este sistema permite al clúster tomar decisión auto-administradas y bajo ciertos criterios sin que un administrador tenga que actuar. En el caso que nos ocupa, el quorum no tiene sentido, ya que el clúster está formado por dos nodos.
Instalación y configuración del Clúster
Actualizar todos los paquetes sel SO para comenzar (en los dos servidores)
root@ASTERISK1:/~# apt-get updateInstalamos los paquetes necesarios para crear el clúster (Pacemaker y cronosync):
apt-get install pacemaker corosync crmshDe aquí en adelante llamaremos ASTERISK1 al nodo maestro y ASTERISK2 al nodo standby. Creamos en Asterisk1 la clave de autenticación de corosync y la copiamos a Asterisk2:
root@ASTERISK1:/~# corosync-keygen root@ASTERISK1:/~# scp /etc/corosync/authkey 10.1.90.5:/etc/corosync/authkey
root@ASTERISK2:~# chmod 400 /etc/corosync/authkey
Esto debe darnos autorización para tratar información entre los dos equipos mediante el protocolo de comunicación corosync.
Editamos el fichero de configuración de corosync (/etc/corosync/corosync.conf) de ambos nodos añadiendo la red que se va a utilizar para controlar el latido entre los nodos (en nuestro caso va a ser la misma por la que se ofrecen los recursos, pero lo habitual sería que fuese una interfaz dedicada):
bindnetaddr: 10.1.90.0
Además para que corosync se inicie de forma automática al arrancar la máquina, marcamos a “yes” el parámetro START del fichero de configuración del demonio (/etc/default/corosync) en ambos nodos.
Este paso hay que ejecutarlo en ambas máquinas para asegurar el correcto funcionamiento del sistema.
Una vez hecho esto podemos reiniciar los servicios para comprobar si el clúster está activo correctamente.
root@ASTERISK1:/~# service paceaker restart
root@ASTERISK1:/~# service corosync restart
Utilizando el comando crm_mon podemos ver el estado del clúster y comprobar que las cosas funcionan.
root@ASTERISK1:~# crm_mon Stack: corosync Current DC: ASTERISK1 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sat Sep 7 17:23:14 2019 Last change: Sat Sep 7 14:02:01 2019 by root via crm_resource on ASTERISK1 2 nodes configured 2 resources configured Online: [ ASTERISK1 ASTERISK2 ] Active resources:
Vemos resaltado y subrayado que los nodos están en línea y comunicándose. Podemos comprobarlo también el nodo restante.
Configurando los recursos
El recurso que vamos a configurar va a ser una dirección IP 10.1.90.6, para ello en primer lugar desactivamos el mecanismo de STONITH (Shoot The Other Node In The Head), que se utiliza para parar un nodo que esté dando problemas y así evitar un comportamiento inadecuado del clúster:
root@ASTERISK1:~# crm configure property stonith-enabled=false
Recurso DIRECCIÓN IP VIRTUAL
Ahora configuramos el recurso de la IP virtual (10.1.90.6) solo es necesario configurarlo en uno de los equipos:
root@ASTERISK1:~# crm configure primitive FAILOVER-ADDR ocf:heartbeat:IPaddr2 params ip="10.1.90.6" nic="eth0:0" cidr_netmask="24" op monitor iflabel="IP_VIRTUAL” interval="10s" meta is-managed="true"
Estos son los campos que estamos configurando:
- Ip: dirección IP virtual
- Nic: nombre de la tarjeta virtual
- cidr_netmask: Máscara de subred
- iflabel: etiqueta para mostrar if ifconfig, ojo, si no se configuran, las tarjetas funciona pero no es visible
Comprobamos el recurso con crm_mon:
stack: corosync Current DC: ASTERISK2 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sat Sep 7 17:41:11 2019 Last change: Sat Sep 7 14:02:01 2019 by root via crm_resource on ASTERISK2 2 nodes configured 2 resources configured Online: [ ASTERISK1 ASTERISK2 ] Active resources: renovarSIP (ocf::heartbeat:anything): Started ASTERISK1 FAILOVER-ADDR (ocf::heartbeat:IPaddr2): Started ASTERISK1
Verificamos la IP con ifconfig en los servidores:
root@ASTERISK1:~# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.1.90.4 netmask 255.255.255.0 broadcast 10.1.90.255 inet6 fe80::8412:83ff:fea1:77b5 prefixlen 64 scopeid 0x20<link> ether 86:12:83:a1:77:b5 txqueuelen 1000 (Ethernet) RX packets 195645 bytes 16259767 (15.5 MiB) RX errors 0 dropped 80 overruns 0 frame 0 TX packets 67718 bytes 9153674 (8.7 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.1.90.6 netmask 255.255.255.0 broadcast 10.1.90.255 ether 86:12:83:a1:77:b5 txqueuelen 1000 (Ethernet)
Una vez con esto en marcha podemos comprobar el funcionamiento del clúster apagando el equipo que está dando servicio al recurso. Os recomiendo que lo probéis varias veces mientras está en testing, después es más peliagudo hacer pruebas, ya me entendéis.
Prioridad de nodos
Dado que en el sistema que estamos configurando (IPVIRTUAL + Scripts) en caso de error debe ejecutar los scripts. Tenemos que asegurarnos que los recursos se ejecutan siempre en la misma máquina a la vez (IPVIRTUAL + Scripts), ya que Peacemaker intentará balancearlos repartiéndolos en máquinas distintas.
Esto provoca que si el equipo que gestiona la IP virtual cae (y por tanto el que gestiona los scripts sigue en marcha y asume la IP) al no tener un fallo (el equipo de los scripts) estos nunca son ejecutados, y por tanto la convergencia telefónica se eleva a más de una hora.
Para crear una regla de ejecución de recursos basta con migrarlos manualmente a un nodo, Peacemaker por detrás crea las reglas necesarias para que el recurso siempre se ejecute en el nodo seleccionado. En nuestro caso, ejecutaremos siempre los recursos en ASTERISK1, por tanto:
root@ASTERISK1:~#crm resource migrate FAILOVER-ADDR ASTERISK1
Pacemaker, que depende de las capacidades de mensajería de Corosync, ahora está listo para comenzar. En ambos servidores, habilitamos Pacemaker para iniciar el arranque del sistema con este comando:
$ sudo update-rc.d pacemaker defaults 20 01
Debido a que Pacemaker necesita comenzar después de Corosync, establecemos la prioridad de inicio de Pacemaker en 20, que es más alta que la de Corosync (es 19 por defecto).
Como hemos explicado antes, no tiene sentido quorum en un clúster de dos servidores, por tanto lo deshabilitamos:
crm configure property no-quorum-policy=ignore
Scripts de convergencia
Dada la automatización del clúster, que en caso de fallo permuta la dirección virtual a un equipo activo, se produce un tiempo de convergencia por la propia arquitectura Activo/Pasivo de la configuración. Durante el tiempo en que los diferentes equipos telefónicos consiguen registrar su cuente en el servidor Asterisk, pasa un tiempo en el cual las llamadas pueden ser erráticas y causar confusión y mal servicio.
Como he comentado antes, los scripts pueden utilizarse para infinidad de cosas, básicamente el sistema ejecuta algo cuando ocurre un evento de failover. En el ejemplo que estamos montando, ejecutamos un script para forzar a los teléfonos registrados en el equipo de la falla a registrarse nuevamente, de esta manera, aunque podamos tener un corte temporal, la convergencia será más rápida.
Este es solo un ejemplo y no voy a entrar a explicar los scripts, solo os cuento como configurar los vuestros.
Para solucionar nuestro inconveniente hay que acometer 3 ramas de modificaciones para conseguir una convergencia de más o menos un minuto.
- Realizar una comunicación ICMP a los diferentes equipos implicados para reconfigurar las tablas MAC de los switches de comunicación y dirigir el tráfico a la nueva situación
- Reconfigurar los telefonospara reducir el tiempo de renovación de sesión.
- Reiniciar median SSH y de manera automática los telefonos que no permiten la modificación del tiempo de renovación, siempre que se produzca un cambio de situación
Con estas tres actuaciones funcionando de manera conjunta, se consigue realizar una migración de sistema de una manera prácticamente imperceptible para los operarios/usuarios y lo que es más importante, de manera automática.
En pacemaker, existe un recurso capaz de ejecutar cualquier tipo de script cuando se produce un fallo en el nodo que lo está sirviendo, este es el servico “anything”.
Procedemos a configurarlo:
Primero debemos generar los scripts que queremos ejecutar en caso de fallo, en nuestro caso son dos:
- renovarARP.sh : Este script realiza un ping a cada uno de los interfonos (hay agregar los interfonos a mano si se añaden nuevos), y además ejecuta en última instancia el script de Python resetear.py.
- resetear.py : básicamente reinicia equipos.
Ambos scripts se alojan en /root/ (hay que tener los ficheros iguales en las dos máquinas).
Una vez tenemos los scripts funcionales, pasamos a crear un recurso compartido con la platilla “anything”:
root@ASTERISK1:~# crm configure primitive renovarSIP ocf:heartbeat:anything params binfile="/root/renovarARP.sh"
Asignamos (como hemos explicado antes) el recurso a la máquina maestra (hay que hacerlo si o si, si no Peacemaker toma la iniciativa):
root@ASTERISK1:~#crm resource migrate renovarSIP ASTERISK1
Comprobamos:
Stack: corosync Current DC: ASTERISK2 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sat Sep 7 18:26:34 2019 Last change: Sat Sep 7 14:02:01 2019 by root via crm_resource on ASTERISK2 2 nodes configured 2 resources configured Online: [ ASTERISK1 ASTERISK2 ] Active resources: renovarSIP (ocf::heartbeat:anything): Started ASTERISK1 FAILOVER-ADDR (ocf::heartbeat:IPaddr2): Started ASTERISK1
También podemos comprobar la configuración con crm configure show
root@ASTERISK1:~# crm configure show
node 167838339: ASTERISK1
node 167838345: ASTERISK2
primitive FAILOVER-ADDR IPaddr2 \
params ip=10.1.90.6 nic="eth0:0" cidr_netmask=24 \
op monitor interval=10s iflabel=IP_VIRTUAL \
meta is-managed=true
primitive renovarSIP anything \
params binfile="/root/renovarARPAudenasa.sh"
location cli-prefer-FAILOVER-ADDR FAILOVER-ADDR role=Started inf: ASTERISK1location cli-prefer-renovarSIP renovarSIP role=Started inf: ASTERISK1property cib-bootstrap-options: \
have-watchdog=false \
dc-version=1.1.16-94ff4df \
cluster-infrastructure=corosync \
cluster-name=debian \
stonith-enabled=false \
no-quorum-policy=ignoreY listo, ya disponemos de un clúster funcional y con una convergencia ágil.
Conclusión
Pacemaker puede ser una buena solución para diferentes entornos en nuestros sistemas empresariales, no tiene coste, es eficaz, y tiene multitud de configuraciones útiles. Quizás tiene algo de complejidad para configurarlo, pero una vez conocemos su funcionamiento puede ayudarnos bastante.
Evidentemente si tenemos un entorno cloud HA, o un sistema virtual VMWARE, Citrix o similar con HA tampoco tiene sentido implantar soluciones de este tipo, pero en ciertas ocasiones el separar ciertos servicios del «Core» de los servidores puede resultar útil en momentos de crisis, Pacemaker puede hacer este trabajo.





