Tutorial de Pacemaker – Configurar un Cluster en Linux Centos

Pacemaker es un software opensource, con soporte de RedHat, para la configuración de servicios en cluster o con alta disponibilidad.

A continuación, puedes ver cómo configurar Pacemaker con DRBD, un software de réplica de datos de filesystems en modo activo-pasivo. Más adelante tienes acceso a la documentación.

Instalación del software necesario

Lo primero de todo es instalar el software necesario en todos los nodos donde vayamos a compartir el mismo disco. Todo el procedimiento lo voy a realizar en Linux CentOS 7.

yum -y install pcs fence-agents-all lvm2-cluster

Si lo instalas en RedHat 7 en vez de en CentOS 7, necesitarás la suscripción de los paquetes de Hight Availability o, bien, descargarte la ISO de RedHat e instalarlos manualmente. Sin embarglo, para tener soporte oficial de RedHat y poder abrir casos en caso de incidencia, se necesita comprar la suscripción.

[root@pcmkrrh1 HighAvailability]# pwd
/RHEL76/mnt/addons/HighAvailability
[root@pcmkrrh1 HighAvailability]# ll |grep pcs
-r--r--r-- 1 root root    12084 Jun 26  2018 clufter-lib-pcs-0.77.1-1.el7.noarch.rpm
-r--r--r-- 1 root root  5290156 Aug 31  2018 pcs-0.9.165-6.el7.x86_64.rpm
-r--r--r-- 1 root root    79808 Aug 31  2018 pcs-snmp-0.9.165-6.el7.x86_64.rpm
[root@pcmkrrh1 HighAvailability]#

Bloqueo de LVM para que sea gestionado por el cluster

Habilitamos el bloqueo por cluster en todos los nodos:

lvmconf --enable-cluster
reboot


Este comando, configura la directiva locking_type en el fichero /etc/lvm/lvm.conf:

[root@pacemaker1 ~]# grep locking_type /etc/lvm/lvm.conf |grep -v "#"
    locking_type = 3
[root@pacemaker1 ~]#

Configuración del cluster con Pacemaker

Arrancamos los servicios en ambos nodos:

[root@pacemaker1 ~]# systemctl start pcsd
[root@pacemaker1 ~]# systemctl enable pcsd
Created symlink from /etc/systemd/system/multi-user.target.wants/pcsd.service to /usr/lib/systemd/system/pcsd.service.
[root@pacemaker1 ~]#

Repetimos los mismos comandos en el resto de nodos del cluster

Asignamos una contraseña al usuario de administración de Pacemaker):

[root@pacemaker1 ~]# passwd hacluster
Changing password for user hacluster.
New password: 
BAD PASSWORD: The password fails the dictionary check - it is based on a dictionary word
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@pacemaker1 ~]#

Autorizamos el acceso de los nodos que forman parte del cluster:

[root@pacemaker1 ~]# pcs cluster auth pacemakercl1 pacemakercl2
Username: hacluster
Password:
pacemakercl2: Authorized
pacemakercl1: Authorized
[root@pacemaker1 ~]#

Creamos la configuración básica del cluster, lo arrancamos y comprobamos su estado:

[root@pacemaker1 ~]# pcs cluster setup --name ha_cluster pacemakercl1 pacemakercl2
Destroying cluster on nodes: pacemakercl1, pacemakercl2...
pacemakercl1: Stopping Cluster (pacemaker)...
pacemakercl2: Stopping Cluster (pacemaker)...
pacemakercl1: Successfully destroyed cluster
pacemakercl2: Successfully destroyed cluster

Sending 'pacemaker_remote authkey' to 'pacemakercl1', 'pacemakercl2'
pacemakercl1: successful distribution of the file 'pacemaker_remote authkey'
pacemakercl2: successful distribution of the file 'pacemaker_remote authkey'
Sending cluster config files to the nodes...
pacemakercl1: Succeeded
pacemakercl2: Succeeded

Synchronizing pcsd certificates on nodes pacemakercl1, pacemakercl2...
pacemakercl2: Success
pacemakercl1: Success
Restarting pcsd on the nodes in order to reload the certificates...
pacemakercl2: Success
pacemakercl1: Success
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs cluster start --all
pacemakercl1: Starting Cluster (corosync)...
pacemakercl2: Starting Cluster (corosync)...
pacemakercl1: Starting Cluster (pacemaker)...
pacemakercl2: Starting Cluster (pacemaker)...
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs status cluster
Cluster Status:
 Stack: unknown
 Current DC: NONE
 Last updated: Sat Jun 15 10:16:51 2019
 Last change: Sat Jun 15 10:16:33 2019 by hacluster via crmd on pacemakercl2
 2 nodes configured
 0 resources configured

PCSD Status:
  pacemakercl1: Online
  pacemakercl2: Online
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs status corosync

Membership information
----------------------
    Nodeid      Votes Name
         1          1 pacemakercl1 (local)
         2          1 pacemakercl2
[root@pacemaker1 ~]#

Creamos un grupo de recursos o servicios

Para este ejemplo, voy a crear un grupo de recursos llamado MySQLGroup que montará un filesystem y dará de alta una IP. Lo haremos de la siguiente manera:

  • Añadimos el filesystem
[root@pacemaker1 ~]# pcs resource create MySQL_fs Filesystem device="/dev/vgmysql/lvmysql" directory="/MySQL" fstype="xfs" --group MySQLGroup
Assumed agent name 'ocf:heartbeat:Filesystem' (deduced from 'Filesystem')
[root@pacemaker1 ~]#
  • Añadimos la IP de servicio
[root@pacemaker1 ~]# pcs resource create VirtualIP IPaddr2 ip=10.0.1.50 cidr_netmask=24 --group MySQLGroup
Assumed agent name 'ocf:heartbeat:IPaddr2' (deduced from 'IPaddr2')
[root@pacemaker1 ~]#
  • Comprobamos el estado de los recursos que acabamos de crear
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Stopped
     VirtualIP  (ocf::heartbeat:IPaddr2):       Stopped
[root@pacemaker1 ~]#

Desde el otro nodo también se puede comprobar:

[root@pacemaker2 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Stopped
     VirtualIP  (ocf::heartbeat:IPaddr2):       Stopped
[root@pacemaker2 ~]#

Arrancamos los recursos del cluster

[root@pacemaker1 ~]# pcs property set stonith-enabled=false
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Started pacemakercl1
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemakercl1
[root@pacemaker1 ~]#
  • Comprobamos que tanto el filesystem como la IP de servicio están disponibles:
[root@pacemaker1 ~]# df -hP /MySQL/
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/vgmysql-lvmysql 1017M   33M  985M   4% /MySQL
[root@pacemaker1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:7d:c0:f8:2d:60 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.16/24 brd 10.0.1.255 scope global dynamic eth0
       valid_lft 3375sec preferred_lft 3375sec
    inet 10.0.1.50/24 brd 10.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::47d:c0ff:fef8:2d60/64 scope link
       valid_lft forever preferred_lft forever
[root@pacemaker1 ~]#

Mover recursos del cluster

Ahora movemos el grupo de recursos al grupo secundario:

[root@pacemaker1 ~]# pcs resource move MySQLGroup pacemakercl2
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Started pacemakercl2
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemakercl2
[root@pacemaker1 ~]#

Comprobamos que en el nodo primario ya no está ni montado el filesystem ni dada de alta la IP de servicio:

[root@pacemaker1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:7d:c0:f8:2d:60 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.16/24 brd 10.0.1.255 scope global dynamic eth0
       valid_lft 3126sec preferred_lft 3126sec
    inet6 fe80::47d:c0ff:fef8:2d60/64 scope link
       valid_lft forever preferred_lft forever
[root@pacemaker1 ~]#

En cambio sí están habilitados ambos servicios en el nodo secundario, tal y como esperábamos:

[root@pacemaker2 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:f6:c7:1a:06:40 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.237/24 brd 10.0.1.255 scope global dynamic eth0
       valid_lft 2964sec preferred_lft 2964sec
    inet 10.0.1.50/24 brd 10.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::4f6:c7ff:fe1a:640/64 scope link
       valid_lft forever preferred_lft forever
[root@pacemaker2 ~]#

Parar y volver a arrancar los recursos del cluster

Parada:

[root@pacemaker1 ~]# pcs resource disable MySQLGroup
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Stopped (disabled)
     VirtualIP  (ocf::heartbeat:IPaddr2):       Stopped (disabled)
[root@pacemaker1 ~]#

Arranque:

[root@pacemaker1 ~]# pcs resource enable MySQLGroup
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     MySQL_fs   (ocf::heartbeat:Filesystem):    Started pacemakercl1
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemakercl1
[root@pacemaker1 ~]#

Eliminar un recurso del cluster

Si queremos eliminar alguno de los recursos del cluster de Pacemaker que hemos creado anteriormente, utilizaremos el siguiente comando:

[root@pacemaker1 ~]# pcs resource delete MySQL_fs
Deleting Resource - MySQL_fs
[root@pacemaker1 ~]# pcs resource show
 Resource Group: MySQLGroup
     VirtualIP  (ocf::heartbeat:IPaddr2):       Stopped (disabled)
[root@pacemaker1 ~]#

Modificar recursos del cluster

[root@pacemaker1 ~]# pcs resource update drbdmysqlFS op start interval=10 timeout=60
[root@pacemaker1 ~]# pcs resource update drbdmysqlFS op notify interval=10 timeout=60
[root@pacemaker1 ~]# pcs resource update drbdmysqlFS op stop interval=10 timeout=60
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs config show drbdmysqlFS
Cluster Name: ha_cluster
Corosync Nodes:
 pacemakercl1 pacemakercl2
Pacemaker Nodes:
 pacemakercl1 pacemakercl2

Resources:
 Group: MySQLGroup
  Resource: VirtualIP (class=ocf provider=heartbeat type=IPaddr2)
   Attributes: cidr_netmask=24 ip=10.0.1.50
   Operations: monitor interval=10s timeout=20s (VirtualIP-monitor-interval-10s)
               start interval=0s timeout=20s (VirtualIP-start-interval-0s)
               stop interval=0s timeout=20s (VirtualIP-stop-interval-0s)
  Resource: drbdmysqlFS (class=ocf provider=heartbeat type=Filesystem)
   Attributes: device=/dev/drbd0 directory=/MySQL fstype=xfs
   Operations: monitor interval=20s timeout=40s (drbdmysqlFS-monitor-interval-20s)
               notify interval=10 timeout=60 (drbdmysqlFS-notify-interval-10)
               start interval=10 timeout=60 (drbdmysqlFS-start-interval-10)
               stop interval=10 timeout=60 (drbdmysqlFS-stop-interval-10)
 Master: DrbdDataClone
  Meta Attrs: master-node-max=1 clone-max=2 notify=true master-max=1 clone-node-max=1
  Resource: DrbdMySQLData (class=ocf provider=linbit type=drbd)
   Attributes: drbd_resource=drbmysql
   Operations: demote interval=0s timeout=90 (DrbdMySQLData-demote-interval-0s)
               monitor interval=20 role=Slave timeout=20 (DrbdMySQLData-monitor-interval-20)
               monitor interval=10 role=Master timeout=20 (DrbdMySQLData-monitor-interval-10)
               notify interval=0s timeout=90 (DrbdMySQLData-notify-interval-0s)
               promote interval=0s timeout=90 (DrbdMySQLData-promote-interval-0s)
               reload interval=0s timeout=30 (DrbdMySQLData-reload-interval-0s)
               start interval=0s timeout=240 (DrbdMySQLData-start-interval-0s)
               stop interval=0s timeout=100 (DrbdMySQLData-stop-interval-0s)

Stonith Devices:
Fencing Levels:

Location Constraints:
  Resource: MySQLGroup
    Enabled on: pacemakercl1 (score:INFINITY) (role: Started) (id:cli-prefer-MySQLGroup)
Ordering Constraints:
Colocation Constraints:
Ticket Constraints:

Alerts:
 No alerts defined

Resources Defaults:
 No defaults set
Operations Defaults:
 timeout: 240s

Cluster Properties:
 cluster-infrastructure: corosync
 cluster-name: ha_cluster
 dc-version: 1.1.19-8.el7_6.4-c3c624ea3d
 have-watchdog: false
 stonith-enabled: false

Quorum:
  Options:
[root@pacemaker1 ~]#

Utilizar DRDB con Pacemaker

En el artículo Réplica activa-pasiva de filesystems con DRBD en Linux CentOS expliqué cómo crear una réplica activa-pasiva de filesystems, ideal para utilizarla en clusters activos-pasivos como los que creamos con Pacemaker y en entornos de bajo coste en lo que no está implementada la réplica por cabina.

Para incorporar DRDB a un cluster de Pacemaker, por ejemplo, para replicar una base de datos SQL entre los diferentes nodos del cluster, seguiremos los siguientes pasos (me salto la parte de configuración de DRDB porque ya la expliqué en el post indicado anteriormente).

  • Integramos el servicio de DRDB en el cluster:
[root@pacemaker1 ~]# pcs cluster cib drbd_cfg
[root@pacemaker1 ~]#
  • Creamos el recurso de DRDB, que llamaremos «DrbdMySQLData»:
[root@pacemaker1 ~]# pcs -f drbd_cfg resource create DrbdMySQLData ocf:linbit:drbd drbd_resource=drbmysql --group MySQLGroup
[root@pacemaker1 ~]#
  • Añadimos el servicio de réplica de datos dr DRDB:
[root@pacemaker1 ~]# pcs -f drbd_cfg resource master DrbdDataClone DrbdMySQLData master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true --group MySQLGroup
[root@pacemaker1 ~]#
  • Actualizamos la configuración del cluster:
[root@pacemaker1 ~]# pcs cluster cib-push drbd_cfg
CIB updated
[root@pacemaker1 ~]#
  • Creamos el recurso del filesystem DRDB, el orden en que se tiene que arrancar cada recurso y volvemos a actualizar el cluster de Pacemaker:
[root@pacemaker1 ~]# pcs cluster cib fs_cfg
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs -f fs_cfg resource create drbdmysqlFS Filesystem device="/dev/drbd0" directory="/MySQL" fstype="xfs" --group MySQLGroup
Assumed agent name 'ocf:heartbeat:Filesystem' (deduced from 'Filesystem')
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs -f fs_cfg constraint colocation add drbdmysqlFS with DrbdDataClone INFINITY with-rsc-role=Master --group MySQLGroup
[root@pacemaker1 ~]# pcs  -f fs_cfg constraint order promote DrbdDataClone then start drbdmysqlFS --group MySQLGroup
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs cluster cib-push fs_cfg
CIB updated
[root@pacemaker1 ~]#

Adjunto también la configuración del FS DRDB para que podamos entender mejor cómo lo hemos añadido al cluster de Pacemaker:

[root@pacemaker1 ~]# cat /etc/drbd.d/drbmysql.res
resource drbmysql {
        on pacemaker1 {
                device /dev/drbd0;
                disk /dev/vgmysql/lvmysql;
                        meta-disk internal;
                        address 10.0.1.16:7789;
        }
        on pacemaker2 {
                device /dev/drbd0;
                        disk /dev/vgmysql/lvmysql;
                        meta-disk internal;
                        address 10.0.1.237:7789;
        }
}
[root@pacemaker1 ~]#
  • Aumentamos los delays de los recursos de DRBD porque fallaban al arrancar:
pcs resource update DrbdMySQLData op start interval=10 timeout=60
pcs resource update DrbdMySQLData op notify interval=10 timeout=60
pcs resource update DrbdMySQLData op stop interval=10 timeout=60
pcs resource update DrbdMySQLData op demote interval=10 timeout=60
pcs resource update DrbdMySQLData op promote interval=10 timeout=60

pcs resource update drbdmysqlFS op start interval=10 timeout=60
pcs resource update drbdmysqlFS op notify interval=10 timeout=60
pcs resource update drbdmysqlFS op stop interval=10 timeout=60
pcs resource update drbdmysqlFS op demote interval=10 timeout=60
pcs resource update drbdmysqlFS op promote interval=10 timeout=60
  • Comprobamos el estado del cluster:
[root@pacemaker1 ~]# pcs status resources
 Resource Group: MySQLGroup
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemakercl2
     drbdmysqlFS        (ocf::heartbeat:Filesystem):    Started pacemakercl2
 Master/Slave Set: DrbdDataClone [DrbdMySQLData]
     Masters: [ pacemakercl2 ]
     Slaves: [ pacemakercl1 ]
[root@pacemaker1 ~]#
  • Verificamos que el filesystem y la IP están arrancados en el nodo indicado:
[root@pacemaker2 drbd.d]# df -hP /MySQL/
Filesystem      Size  Used Avail Use% Mounted on
/dev/drbd0     1017M   33M  985M   4% /MySQL
[root@pacemaker2 drbd.d]# 

[root@pacemaker2 drbd.d]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:f6:c7:1a:06:40 brd ff:ff:ff:ff:ff:ff
    inet 10.0.1.237/24 brd 10.0.1.255 scope global dynamic eth0
       valid_lft 2701sec preferred_lft 2701sec
    inet 10.0.1.50/24 brd 10.0.1.255 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::4f6:c7ff:fe1a:640/64 scope link
       valid_lft forever preferred_lft forever
[root@pacemaker2 drbd.d]#

Ejecutar un script personalizado como recurso de Pacemaker

Con Pacemaker podemos ejecutar, parar y monitorizar scripts personalizados si nos interesa. Para ello, tendremos que definir las funciones y metadatos dentro del script:

Acciones

  • start: Función de arranque del script
  • stop: Función de parada
  • monitor: Monitorización del estado de salud del script. Hay que devolver un Exit 0 si el script está corriendo.
  • meta-data: Provee información en formato XLM, sobre las funciones definidas dentro del script.
  • validate-all: Valida que los parámetros de ejecución del script son correctos. Exit 0 si está todo bien, 2 si no es válido, 6 si el recurso no está configurado.
  • promote: La instancia local hace de nodo primario del cluster.
  • demote: La instancia local hace de nodo secundario.
  • reload: Recarga la configuración del script sin afectación al servicio.

También es posible definir parámetros de ejecución del script. Por ejemplo, cuando hemos creado anteriormente un recurso para dar de alta una IP virtual de servicio, hemos tenido que pasar como parámetro la IP que queríamos.

Ubicación de los scripts de Pacemaker

Por defecto, Pacemaker trae consigo una serie de scripts predefinidos para arrancar procesos o aplicaciones populares, como podría ser dar de alta una IP o arrancar un servidor WEB Apache, por ejemplo.

Todos esos script se encuentran en el directorio /usr/lib/ocf/resource.d/heartbeat y nos pueden ser muy útiles para tomarlos como ejemplo para crear nuestro propio script personalizado.

Creación de un script personalizado

En la ruta indicada anteriormente de ambos nodos del cluster, he creado un script muy sencillo que, lo único que hace es escribir un fichero en /tmp para saber que el script se ha ejecutado. Ni siquiera he programado la monitorización del mismo, pues con este ejemplo y con todos los scripts predefinidos ya nos podemos hacer una idea de cómo añadir un script personalizado dentro de nuestro cluster de Pacemaker.

Veamos el código fuente del script de test:

[root@pacemaker1 ~]# cat /usr/lib/ocf/resource.d/heartbeat/ScriptDavidTest
#!/bin/sh
#
# Resource script for MailTo
#
# Author: David Martinez
#
# Description: Testeando script personalizado con Pacemaker
#

: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs


meta_data() {
        cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="ScriptDavidTest">
<version>1.0</version>

<longdesc lang="en">
Este es un script de pruebas.
</longdesc>
<shortdesc lang="en">Script de pruebas</shortdesc>

<actions>
<action name="start" timeout="10s" />
<action name="stop" timeout="10s" />
<action name="meta-data" timeout="5s" />
</actions>
</resource-agent>
END
}

EchoToStart() {

   echo $(date +%Y%m%d_%H%M) - Script start $(hostname) >> /tmp/pacemakertest.log

}

EchoToStop () {

   echo $(date +%Y%m%d_%H%M) - Script stop $(hostname) >> /tmp/pacemakertest.log

}

usage () {

   echo "Instrucciones para el modo de uso del script"

}

case $1 in
  start)                EchoToStart
                        ;;
  stop)                 EchoToStop
                        ;;
  meta-data)            meta_data;;
  *)                    usage
                        exit $OCF_ERR_UNIMPLEMENTED
                        ;;
esac
exit $?

[root@pacemaker1 ~]#

Y ahora, vamos a instalarlo como un recurso del cluster:

[root@pacemaker1 heartbeat]# pcs resource create ScriptDavidTest ocf:heartbeat:ScriptDavidTest --group GrupoRecursosTest
[root@pacemaker1 heartbeat]#

[root@pacemaker1 ~]# pcs resource show
 Resource Group: GrupoRecursosTest
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1
     ScriptDavidTest    (ocf::heartbeat:ScriptDavidTest):       Stopped
[root@pacemaker1 ~]#

Aparece como «stopped» porque no he creado la función para monitorizarlo. Pero vamos a ejecutarlo:

[root@pacemaker1 ~]# pcs resource debug-start ScriptDavidTest
Operation start for ScriptDavidTest (ocf:heartbeat:ScriptDavidTest) returned: 'ok' (0)
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# cat /tmp/pacemakertest.log
20190616_1757 - Script start pacemaker1
[root@pacemaker1 ~]#

Como vemos, se ha creado el fichero que queríamos. Podemos utilizar este procedimiento para ejecutar cualquier script que queramos como, por ejemplo, arrancar una base de datos Oracle, etc.

Añadir un nuevo nodo al cluster

Si queremos pasar de dos nodos a tres en el cluster, podemos hacerlo de una manera muy sencilla.

Para no repetirme, en el tercer nodo seguiremos todos los pasos de instalación de Pacemaker descritos anteriormente en este artículo y, por supuesto, arrancaremos todos los servicios del cluster (instalación del producto, habilitar el servicio, arrancarlo y dar de alta el usuario hacluster y la contraseña).

Así que, una vez que tenemos el tercer nodo con todos los requerimientos necesarios ya configurados, lo añadiremos al cluster.

[root@pacemaker1 ~]# pcs cluster node add pacemaker3
Disabling SBD service...
pacemaker3: sbd disabled
Sending remote node configuration files to 'pacemaker3'
pacemaker3: successful distribution of the file 'pacemaker_remote authkey'
pacemaker1: Corosync updated
pacemaker2: Corosync updated
Setting up corosync...
pacemaker3: Succeeded
Synchronizing pcsd certificates on nodes pacemaker3...
pacemaker3: Success
Restarting pcsd on the nodes in order to reload the certificates...
pacemaker3: Success
[root@pacemaker1 ~]# 

[root@pacemaker3 ~]# pcs cluster enable
[root@pacemaker3 ~]#

[root@pacemaker3 ~]# pcs cluster start --all
pacemaker1: Starting Cluster (corosync)...
pacemaker2: Starting Cluster (corosync)...
pacemaker3: Starting Cluster (corosync)...
pacemaker2: Starting Cluster (pacemaker)...
pacemaker3: Starting Cluster (pacemaker)...
pacemaker1: Starting Cluster (pacemaker)...
[root@pacemaker3 ~]#

[root@pacemaker3 ~]# pcs status
Cluster name: ClusterTest
Stack: corosync
Current DC: pacemaker2 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Sun Jun 16 18:53:00 2019
Last change: Sun Jun 16 18:52:55 2019 by hacluster via crmd on pacemaker2

3 nodes configured
2 resources configured

Online: [ pacemaker1 pacemaker2 pacemaker3 ]

Full list of resources:

 Resource Group: GrupoRecursosTest
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1
     ScriptDavidTest    (ocf::heartbeat:ScriptDavidTest):       Stopped

Failed Actions:
* ScriptDavidTest_monitor_0 on pacemaker1 'unimplemented feature' (3): call=11, status=complete, exitreason='',
    last-rc-change='Sun Jun 16 18:49:18 2019', queued=0ms, exec=12ms
* ScriptDavidTest_monitor_0 on pacemaker2 'unimplemented feature' (3): call=9, status=complete, exitreason='',
    last-rc-change='Sun Jun 16 18:49:18 2019', queued=0ms, exec=15ms


Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled
[root@pacemaker3 ~]#

Como podemos observar, el nodo pacemaker3 se ha añadido al cluster satisfactoriamente.

¿Quién hace de servidor de Quorum?

[root@pacemaker1 ~]# pcs status |grep -i quorum
Current DC: pacemaker2 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
[root@pacemaker1 ~]#

Ahora hago un shutdown del servidor pacemaker2 y comprobamos que ahora es otro servidor el que hace de Quorum:

[root@pacemaker1 ~]# pcs status |grep -i quorum
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
[root@pacemaker1 ~]#

Eliminar un nodo del cluster

Ahora vamos a eliminar del cluster el nodo que acabamos de incorporar, a modo de prueba.

[root@pacemaker1 ~]# pcs cluster node remove pacemaker3
Error: Removing the node will cause a loss of the quorum, use --force to override
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs cluster node remove pacemaker3 --force
pacemaker3: Stopping Cluster (pacemaker)...
pacemaker3: Successfully destroyed cluster
pacemaker1: Corosync updated
pacemaker2: Corosync updated
[root@pacemaker1 ~]# pcs status
Cluster name: ClusterTest
Stack: corosync
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Mon Jun 17 06:19:55 2019
Last change: Mon Jun 17 06:19:51 2019 by root via crm_node on pacemaker1

2 nodes configured
2 resources configured

Online: [ pacemaker1 ]
OFFLINE: [ pacemaker2 ]

Full list of resources:

 Resource Group: GrupoRecursosTest
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1
     ScriptDavidTest    (ocf::heartbeat:ScriptDavidTest):       Stopped

Failed Actions:
* ScriptDavidTest_monitor_0 on pacemaker1 'unimplemented feature' (3): call=11, status=complete, exitreason='',
    last-rc-change='Mon Jun 17 06:18:26 2019', queued=0ms, exec=12ms


Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs status |grep -i quorum
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
[root@pacemaker1 ~]#

Configurar un servidor de Quorum o Stonith de Pacemaker

Ahora vamos construir un cluster de dos nodos de servicio más otro nodo de servidor de Quorum con las siguientes IPs:

10.0.1.58 pacemaker1
10.0.1.138 pacemaker2
10.0.1.130 pacemaker-stonith

El servidor de Quorum o Stonith, que así se llama en Pacemaker, se encarga de revisar el estado de salud del cluster. Si uno de los nodos pierde comunicación con el resto de nodos del cluster, éste necesita saber si es un problema suyo o del resto de nodos. Es ahí donde interviene el servidor de Quorum para poner orden en el estado del cluster.

En todos los nodos del cluster instalaremos el siguiente paquete:

[root@node1:~]# yum install corosync-qdevice
[root@node2:~]# yum install corosync-qdevice

En el servidor de quorum instalaremos el paquete:

[root@pacemaker-stonith ~]# yum install pcs corosync-qnetd

Y habilitaremos el servicio:

[root@pacemaker-stonith ~]# systemctl start pcsd.service
[root@pacemaker-stonith ~]# systemctl enable pcsd.service

[root@pacemaker-stonith ~]# pcs qdevice setup model net --enable --start
Quorum device 'net' initialized
quorum device enabled
Starting quorum device...
quorum device started
[root@pacemaker-stonith ~]#

[root@pacemaker-stonith ~]# pcs qdevice start net
Starting quorum device...
quorum device started
[root@pacemaker-stonith ~]# pcs qdevice enable net
quorum device enabled
[root@pacemaker-stonith ~]#

[root@pacemaker-stonith ~]# pcs qdevice status net --full
QNetd address:                  *:5403
TLS:                            Supported (client certificate required)
Connected clients:              0
Connected clusters:             0
Maximum send/receive size:      32768/32768 bytes

[root@pacemaker-stonith ~]#

Desde cualquiera de los nodos del cluster autorizamos al servidor de Stonith:

[root@pacemaker1 ~]# pcs cluster auth pacemaker-stonith
Username: hacluster
Password:
pacemaker-stonith: Authorized
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs quorum config
Options:
[root@pacemaker1 ~]# pcs quorum status
Quorum information
------------------
Date:             Mon Jun 17 14:36:53 2019
Quorum provider:  corosync_votequorum
Nodes:            2
Node ID:          1
Ring ID:          1/68
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   2
Highest expected: 2
Total votes:      2
Quorum:           1
Flags:            2Node Quorate WaitForAll

Membership information
----------------------
    Nodeid      Votes    Qdevice Name
         1          1         NR pacemaker1 (local)
         2          1         NR pacemaker2

[root@pacemaker1 ~]#

Por último, activamos el servicio del servidor de Stonith:

[root@pacemaker1 ~]# pcs quorum device add model net host=pacemaker-stonith  algorithm=ffsplit
Setting up qdevice certificates on nodes...
pacemaker1: Succeeded
pacemaker2: Succeeded
Enabling corosync-qdevice...
pacemaker2: not enabling corosync-qdevice: corosync is not enabled
pacemaker1: corosync-qdevice enabled
Sending updated corosync.conf to nodes...
pacemaker1: Succeeded
pacemaker2: Succeeded
Corosync configuration reloaded
Starting corosync-qdevice...
pacemaker1: corosync-qdevice started
pacemaker2: corosync-qdevice started
[root@pacemaker1 ~]#


[root@pacemaker1 ~]# pcs quorum config
Options:
Device:
  votes: 1
  Model: net
    algorithm: ffsplit
    host: pacemaker-stonith
[root@pacemaker1 ~]#


[root@pacemaker1 ~]# pcs quorum status
Quorum information
------------------
Date:             Mon Jun 17 14:39:22 2019
Quorum provider:  corosync_votequorum
Nodes:            2
Node ID:          1
Ring ID:          1/68
Quorate:          Yes

Votequorum information
----------------------
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2
Flags:            Quorate WaitForAll Qdevice

Membership information
----------------------
    Nodeid      Votes    Qdevice Name
         1          1    A,V,NMW pacemaker1 (local)
         2          1    A,V,NMW pacemaker2
         0          1            Qdevice

[root@pacemaker1 ~]#


[root@pacemaker1 ~]# pcs quorum device status
Qdevice information
-------------------
Model:                  Net
Node ID:                1
Configured node list:
    0   Node ID = 1
    1   Node ID = 2
Membership node list:   1, 2

Qdevice-net information
----------------------
Cluster name:           ClusterTest
QNetd host:             pacemaker-stonith:5403
Algorithm:              Fifty-Fifty split
Tie-breaker:            Node with lowest node ID
State:                  Connected

[root@pacemaker1 ~]#

Añadir políticas o propiedades a Stonith

Si queremos que el nodo que está teniendo problemas se rebote automáticamente si no se ha recuperado tras 60 segundos, configuraremos las propiedades de Stonith de la siguiente manera:

[root@pacemaker1 ~]# pcs -f stonith_cfg property set stonith-timeout=60s
[root@pacemaker1 ~]# pcs -f stonith_cfg property set stonith-action=reboot
[root@pacemaker1 ~]# pcs -f stonith_cfg property
Cluster Properties:
 stonith-action: reboot
 stonith-enabled: true
 stonith-timeout: 60s
[root@pacemaker1 ~]#

Crear recursos del estado de salud del nodo con Stonith

Para comprobar que el nodo pacemaker1 está en un buen estado de salud, vamos a crear una política para que se autentifique por SSH hacia el nodo pacemaker2, de manera periódica, con un recurso de Stonith:

[root@pacemaker1 ~]# pcs stonith create pacemaker1-fencing fence_apc pcmk_host_list="pacemaker1" ipaddr=10.0.1.138 login=hacluster passwd=Martinez8 secure=true ssh_path="/usr/bin/ssh" ssh_options="-F /dev/null" shell_timeout=30
[root@pacemaker1 ~]#

Sin embargo, el recurso de stonith aparece como parado:

[root@pacemaker1 ~]# pcs status
Cluster name: ClusterTest
Stack: corosync
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Thu Jun 20 04:48:29 2019
Last change: Thu Jun 20 04:47:13 2019 by root via cibadmin on pacemaker1

2 nodes configured
2 resources configured

Online: [ pacemaker1 pacemaker2 ]

Full list of resources:

 Resource Group: MySQLGroup
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1
 pacemaker1-fencing     (stonith:fence_apc):    Stopped

Failed Actions:
* pacemaker1-fencing_start_0 on pacemaker2 'unknown error' (1): call=17, status=Error, exitreason='',
    last-rc-change='Thu Jun 20 04:47:13 2019', queued=0ms, exec=12268ms
* pacemaker1-fencing_start_0 on pacemaker1 'unknown error' (1): call=19, status=Error, exitreason='',
    last-rc-change='Thu Jun 20 04:47:25 2019', queued=0ms, exec=12639ms


Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled
[root@pacemaker1 ~]#

No obstante, el cluster funciona correctamente mientras no se pierda la comunicación entre los nodos ni con el servidor de Quorum al mismo tiempo.

Problemas encontrados con Stonith

El recurso que hemos creado con Stonith también lo podemos comprobar ejecutando el script en pyhon manualmente. Si lo hacemos, el resultado es el siguiente:


[root@pacemaker1 ~]# fence_apc --ip=10.0.1.138 --username=hacluster --password=Martinez8 --ssh --ssh-options="-F /dev/null" --shell-timeout=30 --plug=pacemaker21 --verbose
2019-06-20 04:52:50,303 INFO: Running command: /usr/bin/ssh  hacluster@10.0.1.138 -p 22 -o PubkeyAuthentication=no -F /dev/null
2019-06-20 04:52:50,377 DEBUG: Received: hacluster@10.0.1.138's password:
2019-06-20 04:52:50,377 DEBUG: Sent: Martinez8
2019-06-20 04:52:50,427 DEBUG: Sent:

2019-06-20 04:52:55,483 DEBUG: Timeout exceeded in read_nonblocking().
<fencing.fspawn object at 0x7f6258636b50>
version: 2.3 ($Revision: 399 $)
command: /usr/bin/ssh
args: ['/usr/bin/ssh', 'hacluster@10.0.1.138', '-p', '22', '-o', 'PubkeyAuthentication=no', '-F', '/dev/null']
searcher: searcher_re:
    0: re.compile("
>")
    1: re.compile("
apc>")
buffer (last 100 chars): Jun 20 04:52:41 2019 from pacemaker1
[hacluster@pacemaker2 ~]$
before (last 100 chars): Jun 20 04:52:41 2019 from pacemaker1
[hacluster@pacemaker2 ~]$
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 6033
child_fd: 4
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
2019-06-20 04:52:55,483 ERROR: Unable to connect/login to fencing device


[root@pacemaker1 ~]#

Aunque el script de error, el comando que ejecuta el propio script sí funciona, por lo que no entiendo el motivo del error. Fijaos en la línea que lanza:

2019-06-20 04:52:50,303 INFO: Running command: /usr/bin/ssh  hacluster@10.0.1.138 -p 22 -o PubkeyAuthentication=no -F /dev/null

Si la ejecuto manualmente funciona:

[root@pacemaker1 ~]#  /usr/bin/ssh  hacluster@10.0.1.138 -p 22 -o PubkeyAuthentication=no -F /dev/null
hacluster@10.0.1.138's password:
Last login: Thu Jun 20 04:52:50 2019 from pacemaker1
[hacluster@pacemaker2 ~]$

Me he estado volviendo loco con este error y, por lo que he leído por Internet, se trata de un bug del script fence_apc. Pareces ser que envía la contraseña demasiado rápido, es decir, antes de que la pida SSH.

Solución – Crear el recurso de Stonith con el agente de SNMP en vez de con el de SSH

Lo que he hecho ha sido instalar SNMP en el mismo servidor donde tengo instalado el servidor de Quorum aunque, lo idea, es tener otro servidor diferente. En este caso, ya nos sirve para hacer la prueba. Si nos sabes instalar SNMP, lo explico en el Crear un usuario y contraseña de SNMP.

A continuación, creo el recurso de Stonith de SNMP para que todos los nodos del cluster se validen contra este servicio:

[root@pacemaker1 ~]# pcs stonith create pcmkrrh2-snmp-fencing fence_apc_snmp ipaddr="pacemaker-stonith" pcmk_host_map="pacemaker1:1;pacemaker2:2" pcmk_host_check="static-list" pcmk_host_list="pacemaker1;pacemaker2" login="david" passwd="Martinez8" community=public
[root@pacemaker1 ~]#

[root@pacemaker1 ~]# pcs status
Cluster name: ha_cluster
Stack: corosync
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Sat Jun 22 05:53:24 2019
Last change: Sat Jun 22 05:44:34 2019 by root via cibadmin on pacemaker1

2 nodes configured
2 resources configured

Online: [ pacemaker1 pacemaker2 ]

Full list of resources:

 Resource Group: MySQLGroup
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1
 pcmkrrh2-snmp-fencing  (stonith:fence_apc_snmp):       Started pacemaker2

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
[root@pacemaker1 ~]#

La palabra Stonith significa pegarle un tiro al otro nodo. Es decir, si alguno de los nodos se queda colgado, los otros que quedan vivos lo desconectan del cluster mediante la política que hemos definido en el recurso de stonith. Por ejemplo, desconectarle del switch de la cabina de discos.

Los recursos de Stonith se definen a nivel de cluster.

¿Qué pasa si cae el servidor de Quorum?

Mientras los dos nodos de servicio del cluster tengan conectividad entre ellos, no tiene por qué pasar nada. Vamos a comprobarlo:

  • Apagamos el servidor Stonith
[root@pacemaker-stonith ~]# reboot
  • Comprobamos que los nodos ya no tienen visibilidad del Quorum
[root@pacemaker1 ~]# pcs status
Cluster name: ClusterTest
Stack: corosync
Current DC: pacemaker1 (version 1.1.19-8.el7_6.4-c3c624ea3d) - partition with quorum
Last updated: Tue Jun 18 06:56:41 2019
Last change: Mon Jun 17 20:52:20 2019 by root via cibadmin on pacemaker1

2 nodes configured
3 resources configured

Online: [ pacemaker1 pacemaker2 ]

Full list of resources:

 pacemaker1-fencing     (stonith:fence_virt):   Stopped
 pacemaker2-fencing     (stonith:fence_virt):   Stopped
 Resource Group: MySQLGroup
     VirtualIP  (ocf::heartbeat:IPaddr2):       Started pacemaker1

Failed Actions:
* pacemaker2-fencing_start_0 on pacemaker1 'unknown error' (1): call=16, status=Error, exitreason='',
    last-rc-change='Tue Jun 18 06:43:19 2019', queued=0ms, exec=1060ms
* pacemaker1-fencing_start_0 on pacemaker1 'unknown error' (1): call=14, status=Error, exitreason='',
    last-rc-change='Tue Jun 18 06:43:18 2019', queued=0ms, exec=1066ms
* pacemaker1-fencing_start_0 on pacemaker2 'unknown error' (1): call=12, status=Error, exitreason='',
    last-rc-change='Tue Jun 18 06:43:19 2019', queued=0ms, exec=1060ms
* pacemaker2-fencing_start_0 on pacemaker2 'unknown error' (1): call=10, status=Error, exitreason='',
    last-rc-change='Tue Jun 18 06:43:18 2019', queued=0ms, exec=1060ms


Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled
[root@pacemaker1 ~]#



[root@pacemaker2 ~]#  pcs quorum device status
Qdevice information
-------------------
Model:                  Net
Node ID:                2
Configured node list:
    0   Node ID = 1
    1   Node ID = 2
Membership node list:   1, 2

Qdevice-net information
----------------------
Cluster name:           ClusterTest
QNetd host:             pacemaker-stonith:5403
Algorithm:              Fifty-Fifty split
Tie-breaker:            Node with lowest node ID
State:                  Connected

[root@pacemaker2 ~]#  pcs quorum device status
Qdevice information
-------------------
Model:                  Net
Node ID:                2
Configured node list:
    0   Node ID = 1
    1   Node ID = 2
Membership node list:   1, 2

Qdevice-net information
----------------------
Cluster name:           ClusterTest
QNetd host:             pacemaker-stonith:5403
Algorithm:              Fifty-Fifty split
Tie-breaker:            Node with lowest node ID
State:                  Connect failed

[root@pacemaker2 ~]#

Como hemos podido comprobar, la IP de servicio, que es el recurso del cluster que tenemos configurado, ha seguido disponible en todo momento.

Al recuperarse el servidor de Quorum, ambos nodos han reconectado con él automáticamente.

[root@pacemaker1 ~]#  pcs quorum device status |grep State
State:                  Connected
[root@pacemaker1 ~]#

[root@pacemaker2 ~]# pcs quorum device status |grep State
State:                  Connected
[root@pacemaker2 ~]#

Acceso a la interfaz WEB de Pacemaker

Podemos configurar el cluster desde la interfaz WEB. Para ello tenemos que levantar el servicio pcs que ya habíamos instalado previamente, tal y como puedes comprobar en este post.

[root@pacemaker1 ~]# systemctl status pcsd
● pcsd.service - PCS GUI and remote configuration interface
   Loaded: loaded (/usr/lib/systemd/system/pcsd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-06-18 17:29:08 UTC; 6min ago
     Docs: man:pcsd(8)
           man:pcs(8)
 Main PID: 3453 (pcsd)
   CGroup: /system.slice/pcsd.service
           └─3453 /usr/bin/ruby /usr/lib/pcsd/pcsd

Jun 18 17:29:03 pacemaker1 systemd[1]: Starting PCS GUI and remote configuration interface...
Jun 18 17:29:08 pacemaker1 systemd[1]: Started PCS GUI and remote configuration interface.
[root@pacemaker1 ~]#

Cuando este servicio está arrancado, veremos que el proceso está escuchando por el puerto 2224:

[root@pacemaker1 ~]# netstat -anp |grep 2224 |grep LISTEN
tcp6       0      0 :::2224                 :::*                    LISTEN      3453/ruby
[root@pacemaker1 ~]# 

[root@pacemaker1 ~]# ps -ef |grep 3453
root      3453     1  0 17:29 ?        00:00:00 /usr/bin/ruby /usr/lib/pcsd/pcsd
root      5914  4174  0 17:36 pts/0    00:00:00 grep --color=auto 3453
[root@pacemaker1 ~]#

Lo que tenemos que hacer es acceder a la IP y puerto mediante https y entrar con el usuario de administración del cluster. En nuestro caso, habíamos configurado el usuario hacluster.

Administracion WEB de Pacemaker
Pacemaker WEB GUI - Administrar cluster

¿Te ha gustado? ¡Compártelo!

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on whatsapp

Tal vez también te gustaría leer...

Tutorial de Ansible

Recientemente me he estado mirando el funcionamiento de Ansible para automatizar tareas de manera masiva en servidores Linux remotos mediante esta aplicación. Hasta ahora utilizo otra pero como Ansible está cada vez más extendida y considero que vale la pena mirárselo. Más aún si RedHat está apostando por esta herramienta como estándar de automatización. Su

Leer más »

Insertar el botón «Continuar leyendo» en WordPress

Lo normal es presentar en la portada de un blog varios artículos pero no mostrar el contenido completo de cada uno de ellos porque la portada sería muy larga. Es una buena práctica insertar un botón o enlace en cada uno de los artículos de la portada que indique «Continuar leyendo» y que el usuario

Leer más »

Crear un Espinner con las Hojas de Cálculo de Google

Si no sabes lo que es un Espinner consiste en crear contenido diferente con un único texto a través de variables. Mejor lo explico con un ejemplo: Pongamos por caso que tenemos el siguiente texto con variables: Lo que hay dentro de cada llave son diferentes variables para cada palabra clave. Cuando procesemos este texto

Leer más »

Tipos de Enlaces WEB: Nofollow, Sponsored y UGC

Hasta hace muy poco, Google distinguía entre dos tipos de enlaces hacia otras URLs: Follow o, también conocidos como «DoFollow», son aquellos «puntúan» en el posicionamiento de una página WEB. NoFollow son justo lo contrario. Es decir, podemos insertar un enlace en un artículo, un foro, etc. pero no traspasaremos autoridad de nuestra página a

Leer más »

WP All Import – Importar fichero CSV y XML en WordPress

El plugin de WordPress WP All Import es muy útil para importar a WordPress una cantidad ingente de datos. El problema es que es de pago pero nos ahorrará mucho tiempo en estos casos. Imaginaos el tiempo que podéis tardar en crear 200 entradas en WordPress de forma manual. Con WP All Import, el proceso

Leer más »