Esta pagina se ve mejor con JavaScript habilitado

RAID1 remoto mediante HAST

 ·  🎃 kr0m

Mediante HAST (Highly Available Storage) seremos capaces de montar un sistema de almacenamiento transparente entre dos equipos remotos conectados mediante una red TCP/IP, se podría decir que HAST es un RAID1 (mirror) por red.

El artículo se compone de varias secciones:


Introducción:

Para mostar el funcionamiento de HAST dispondremos de dos servidores FreeBSD13.1 cada uno con su ip independiente y una VIP-CARP :

VIP: 192.168.69.40
PeanutBrain01: 192.168.69.41
PeanutBrain02: 192.168.69.42

Cuando trabajemos con HAST debemos tener en cuenta varios aspectos, HAST proporciona replicación síncrona a nivel de bloque, haciendo que sea transparente para los sistemas de ficheros y las aplicaciones. No existe diferencia entre utilizar dispositivos HAST o discos en crudo, particiones, etc, todos ellos no son mas que proveedores regulares GEOM . HAST trabaja en modo primary-secondary, solo unos de los nodos puede estar activo en un momento dado. El nodo primary atenderá las peticiones I/O, el nodo secundary es automáticamente sincronizado desde el primary. Las operaciones de escritura/borrado/flusheo son enviadas al primary y luego replicadas al secondary. Las operaciones de lectura son servidas desde el primary a no ser que exista algún error de I/O, en tal caso la lectura se envía al secondary.

HAST implementa varios modos de sincronización:

  • memsync: Este modo reporta una operación de escritura como completada cuando el primary ha escrito los datos en disco y el secondary envía el ACK para confirmar el inicio de recepción de los datos, solo el inicio de recepción, los datos no han sido escritos en el secondary. Este modo reduce la latencia incluso proveyendo una fiabilidad razonable, es el modo por defecto.
  • fullsync: Este modo reporta una operación de escritura como completada cuando ambos nodos han escrito los datos en disco, es el modo mas seguro pero también el mas lento.
  • async: Este modo reporta una operación de escritura como completada cuando el primary ha escrito los datos en disco, es el modo mas rápido pero también el mas peligroso, solo debe ser utilizado cuando la latencia hasta el secondary es demasiado alta para utilizar alguno de los otros dos modos.

Si estamos utilizando un custom kernel tendremos que habilitar la siguiente opción en la compilación del mismo:

options	GEOM_GATE

Configuración HAST:

En ambos servidores tenemos dos discos además del que utiliza el sistema de este modo podremos probar el funcionamiento con UFS/ZFS.

  • UFS: /dev/ada1
  • ZFS: /dev/ada2
root@PeanutBrain01:~ # camcontrol devlist
<VBOX HARDDISK 1.0>                at scbus0 target 0 lun 0 (pass0,ada0)
<VBOX HARDDISK 1.0>                at scbus0 target 1 lun 0 (pass1,ada1)
<VBOX HARDDISK 1.0>                at scbus1 target 0 lun 0 (pass2,ada2)
root@PeanutBrain02:~ # camcontrol devlist
<VBOX HARDDISK 1.0>                at scbus0 target 0 lun 0 (pass0,ada0)
<VBOX HARDDISK 1.0>                at scbus0 target 1 lun 0 (pass1,ada1)
<VBOX HARDDISK 1.0>                at scbus1 target 0 lun 0 (pass2,ada2)

Los discos deben estar impolutos:

It is not possible to use GEOM providers with an existing file system or to convert an existing storage to a HAST-managed pool

La configuración HAST sería la siguiente en ambos nodos:

vi /etc/hast.conf

resource MySQLData {
	on PeanutBrain01 {
		local /dev/ada1
		remote 192.168.69.42
	}
	on PeanutBrain02 {
		local /dev/ada1
		remote 192.168.69.41
	}
}

resource FilesData {
	on PeanutBrain01 {
		local /dev/ada2
		remote 192.168.69.42
	}
	on PeanutBrain02 {
		local /dev/ada2
		remote 192.168.69.41
	}
}

Creamos los pools HAST en ambos nodos:

hastctl create MySQLData
hastctl create FilesData

Habilitamos y arrancamos el servicio:

sysrc hastd_enable=YES
service hastd start

Pasamos uno de los nodos a primary(PeanutBrain01):

hastctl role primary MySQLData
hastctl role primary FilesData

El otro nodo a secondary(PeanutBrain02):

hastctl role secondary MySQLData
hastctl role secondary FilesData

Comprobamos el estado en ambos:

root@PeanutBrain01:~ # hastctl status MySQLData
Name	Status	 Role		Components
MySQLData	complete primary        /dev/ada1	192.168.69.42

root@PeanutBrain01:~ # hastctl status FilesData
Name	Status	 Role		Components
FilesData	complete primary        /dev/ada2	192.168.69.42
root@PeanutBrain02:~ # hastctl status MySQLData
Name	Status	 Role		Components
MySQLData	complete secondary      /dev/ada1	192.168.69.41

root@PeanutBrain02:~ # hastctl status FilesData
Name	Status	 Role		Components
FilesData	complete secondary      /dev/ada2	192.168.69.41

Podemos ver como el dispositivo HAST solo ha sido generado en el primary:

root@PeanutBrain01:~ # ls -la /dev/hast/
total 1
dr-xr-xr-x   2 root  wheel      512 Oct 30 18:11 .
dr-xr-xr-x  10 root  wheel      512 Oct 30 18:04 ..
crw-r-----   1 root  operator  0x61 Oct 30 18:11 FilesData
crw-r-----   1 root  operator  0x5f Oct 30 18:11 MySQLData
root@PeanutBrain02:~ # ls -la /dev/hast/
ls: /dev/hast/: No such file or directory

Ahora debemos decidir que sistema de ficheros queremos utilizar en el dispositivo HAST, en mi caso voy a utilizar tanto UFS como ZFS, los siguientes comandos SOLO los ejecutamos en el primary:

newfs -U /dev/hast/MySQLData
mkdir /var/db/mysql
mount /dev/hast/MySQLData /var/db/mysql
zpool create FilesData /dev/hast/FilesData

Comprobamos que esté montado en el nodo primary:

df -Th /var/db/mysql
Filesystem           Type    Size    Used   Avail Capacity  Mounted on
/dev/hast/MySQLData  ufs      15G    8.0K     14G     0%    /var/db/mysql
zpool status FilesData
pool: FilesData
  state: ONLINE
  config:

      NAME              STATE     READ WRITE CKSUM
      FilesData         ONLINE       0     0     0
      hast/FilesData  ONLINE       0     0     0

  errors: No known data errors

df -Th /FilesData
  Filesystem  Type    Size    Used   Avail Capacity  Mounted on
  FilesData   zfs      15G     96K     15G     0%    /FilesData

La idea es montar dos servicios MySQL y NFS, ambos serán ofrecidos por el nodo primary que será un nodo u otro dependiendo de donde esté configurada la VIP-CARP en cada momento.

Instalamos el paquete mysql-server en ambos nodos:

pkg install mysql80-server

Habilitamos el servicio en ambos nodos:

sysrc mysql_enable=YES

Bindeamos el servicio a todas las ips del servidor:

vi /usr/local/etc/mysql/my.cnf

[mysqld]
bind-address                    = 0.0.0.0

Arrancamos el servicio en ambos nodos:

service mysql-server start

Ahora habilitamos NFS para el directorio /FilesData en el primary:

zfs set sharenfs="maproot=root:wheel" FilesData

Comrpobamos que esté compartido:

zfs get sharenfs FilesData

NAME       PROPERTY  VALUE               SOURCE
FilesData  sharenfs  maproot=root:wheel  local

Habilitamos los servicios NFS en ambos nodos de este modo cuando la VIP-CARP migre estará todo listo:

sysrc rpcbind_enable=YES
sysrc nfs_server_enable=YES
sysrc mountd_enable=YES

Arrancamos el servicio NFS en ambos nodos:

service nfsd start

Creamos un fichero de prueba en el nodo primary:

echo kr0m > /FilesData/AA

Desde nuestro pc nos aseguramos de que podamos acceder al contenido por NFS:

Garrus # ~> showmount -e 192.168.69.40
Exports list on 192.168.69.40:
/FilesData                         Everyone

Garrus # ~> mount 192.168.69.40:/FilesData /mnt/nfs/
Garrus # ~> df -Th /mnt/nfs/
Filesystem                Type    Size    Used   Avail Capacity  Mounted on
192.168.69.40:/FilesData  nfs      15G    100K     15G     0%    /mnt/nfs

Garrus # ~> cat /mnt/nfs/AA 
kr0m

El cambio de role será controlado mediante eventos devd, cuando la VIP-CARP migre a un nodo este se configurará como primary, cuando se pierda la VIP-CARP se configurará como secondary.
Los parámetros necesarios para la configuración de las reglas devd son los siguientes :

System    Subsystem    Type         Description
CARP                                Events related to the carp(4) protocol.
CARP      vhid@inet                 The "subsystem" contains	the actual
                                    CARP vhid and the name of the network
                                    interface on which the event took
                                    place.
CARP      vhid@inet    MASTER       Node become the master for a virtual
                                    host.
CARP      vhid@inet    BACKUP       Node become the backup for a virtual
                                    host.

Añadimos la siguiente configuración a devd para que ejecute un script de reconfiguración de HAST cuando detecte una migración de la VIP-CARP:

vi /etc/devd/carp-hast.conf

notify 30 {
	match "system" "CARP";
	match "subsystem" "1@em0";
	match "type" "MASTER";
	action "/usr/local/sbin/carp-hast-switch primary";
};

notify 30 {
	match "system" "CARP";
	match "subsystem" "1@em0";
	match "type" "BACKUP";
	action "/usr/local/sbin/carp-hast-switch secondary";
};

Reiniciamos devd:

service devd restart

Según el cambio detectado el script de failover actuará de un modo determinado:

  • Primary: Espera a que los procesos HAST-secondary mueran, cambia el role, monta/importa el sistema de ficheros y arranca los servicios.
  • Secondary: Para los servicios, desmonta/exports el sistema de ficheros y cambia el role.

Todos los recursos HAST están vinculados a un directorio donde se montarán, el tipo de sistema de ficheros y a un servicio:

Recurso Directorio Sistema de ficheros Servicio
MySQLData /var/db/mysql UFS mysql
FilesData /FilesData ZFS nfs

El script en cuestión sería el siguiente:

vi /usr/local/sbin/carp-hast-switch

#!/bin/sh

# The names of the HAST resources, as listed in /etc/hast.conf
resources="MySQLData FilesData"
# Resource mountpoints
resource_mountpoints="/var/db/mysql /FilesData"
# Supported file system types: UFS, ZFS
resource_filesystems="UFS ZFS"
# Service types: mysql nfs
resource_services="mysql nfs"

# Delay in mounting HAST resource after becoming primary
delay=3

# logging
log="local0.debug"
name="carp-hast"

# end of user configurable stuff

case "$1" in
	primary)
        logger -p $log -t $name "Switching to primary provider for - ${resources} -."
        sleep ${delay}

        # -- SERVICE MANAGEMENT --
        logger -p $log -t $name ">> Stopping services."
        resource_counter=1
        for resource in ${resources}; do
            resource_service=`echo $resource_services | cut -d\  -f$resource_counter`
            case "${resource_service}" in
            mysql)
                logger -p $log -t $name "Service MySQL detected for resource - ${resource} -."
                logger -p $log -t $name "Stoping MySQL service for resource - ${resource} -."
                service mysql-server stop
                logger -p $log -t $name "Done for resource ${resource}"
                ;;
            nfs)
                logger -p $log -t $name "Service NFS detected for resource - ${resource} -."
                logger -p $log -t $name "Disabling NFS-ZFS share for resource - ${resource} -."
                zfs set sharenfs="off" FilesData
                logger -p $log -t $name "Done for resource ${resource}"
                logger -p $log -t $name "Stopping NFS service for resource - ${resource} -."
                service nfsd stop
                logger -p $log -t $name "Done for resource ${resource}"
                ;;
            *)
                logger -p local0.error -t $name "ERROR: Unknown service: ${resource_filesystem}, exiting."
                exit 1
                ;;
            esac
            let resource_counter=$resource_counter+1
        done

        # -- HAST ROLE MANAGEMENT --
        logger -p $log -t $name ">> Managing disks."
        for resource in ${resources}; do
            # When primary HAST node is inaccesible secondary node stops hastd secondary processes automatically
            # Wait 30s for any "hastd secondary" processes to stop
            num=0
            logger -p $log -t $name "Waitting for secondary process of resource - ${resource} - to die."
            while $( pgrep -lf "hastd: ${resource} \(secondary\)" > /dev/null 2>&1 ); do
                let num=$num+1
                sleep 1
                if [ $num -gt 29 ]; then
                    logger -p $log -t $name "ERROR: Secondary process for resource - ${resource} - is still running after 30 seconds, exiting."
                    exit
                fi
            done
            logger -p $log -t $name "Secondary process for resource - ${resource} - dead successfully."

            # Switch role for resource
            logger -p $log -t $name "Switching resource - ${resource} - to primary."
            hastctl role primary ${resource}
            if [ $? -ne 0 ]; then
                logger -p $log -t $name "ERROR: Unable to change role to primary for resource - ${resource} -."
                exit 1
            fi
            logger -p $log -t $name "Role for HAST resource - ${resource} - switched to primary."
        done

        # -- WAIT FOR HAST DEVICE CREATION --
        logger -p $log -t $name ">> Waitting for hast devices."
        for resource in ${resources}; do
            num=0
            logger -p $log -t $name "Waitting for hast device of resource - ${resource} -."
            while [ ! -c "/dev/hast/${resource}" ]; do
                let num=$num+1
                sleep 1
                if [ $num -gt 29 ]; then
                    logger -p $log -t $name "ERROR: GEOM provider /dev/hast/${resource} did not appear, exiting."
                    exit
                fi
            done
            logger -p $log -t $name "Device /dev/hast/${resource} appeared for resource - ${resource} -."
        done

        # -- FILESYSTEM MANAGEMENT --
        logger -p $log -t $name ">> Managing filesystems."
        resource_counter=1
        for resource in ${resources}; do
            resource_mountpoint=`echo $resource_mountpoints | cut -d\  -f$resource_counter`
            resource_filesystem=`echo $resource_filesystems | cut -d\  -f$resource_counter`
            case "${resource_filesystem}" in
            UFS)
                logger -p $log -t $name "UFS filesystem detected in resource - ${resource} -."
                mkdir -p ${resource_mountpoint} 2>/dev/null
                logger -p $log -t $name "Checking /dev/hast/${resource} of resource - ${resource} -."
                fsck -p -y -t ufs /dev/hast/${resource}
                logger -p $log -t $name "Mounting /dev/hast/${resource} in ${resource_mountpoint}."
                out=`mount /dev/hast/${resource} ${resource_mountpoint} 2>&1`
                if [ $? -ne 0 ]; then
                    logger -p local0.error -t hast "ERROR: UFS mount - ${resource} - failed: ${out}."
                    exit 1
                fi
                logger -p local0.debug -t $name "UFS mount - ${resource} - mounted successfully."
                ;;
            ZFS)
                logger -p $log -t $name "ZFS filesystem detected in resource - ${resource} -."
                logger -p $log -t $name "Importing ZFS pool of resource - ${resource} -."
                out=`zpool import -f "${resource}" 2>&1`
                if [ $? -ne 0 ]; then
                    logger -p local0.error -t $name "ERROR: ZFS pool import for resource - ${resource} - failed: ${out}."
                    exit 1
                fi
                logger -p local0.debug -t $name "ZFS pool for resource - ${resource} - imported successfully."
                ;;
            *)
                logger -p local0.error -t $name "ERROR: Unknown filesystem: ${resource_filesystem}, exiting."
                exit 1
                ;;
            esac
            let resource_counter=$resource_counter+1
        done

        # -- SERVICE MANAGEMENT --
        logger -p $log -t $name ">> Starting services."
        resource_counter=1
        for resource in ${resources}; do
            logger -p $log -t $name "Starting service for resource - ${resource} -."
            resource_service=`echo $resource_services | cut -d\  -f$resource_counter`
            case "${resource_service}" in
            mysql)
                logger -p $log -t $name "Service MySQL detected for resource - ${resource} -."
                logger -p $log -t $name "Starting MySQL service for resource - ${resource} -."
                service mysql-server start
                logger -p $log -t $name "Done for resource . ${resource} -."
                ;;
            nfs)
                logger -p $log -t $name "Service NFS detected for resource - ${resource} -."
                logger -p $log -t $name "Starting NFS service for resource - ${resource} -."
                service nfsd start
                logger -p $log -t $name "Done for resource - ${resource} -."
                logger -p $log -t $name "Enabling NFS-ZFS share for resource - ${resource} -."
                zfs set sharenfs="maproot=root:wheel" FilesData
                logger -p $log -t $name "Done for resource - ${resource} -."
                ;;
            *)
                logger -p local0.error -t $name "ERROR: Unknown service: ${resource_filesystem}, exiting."
                exit 1
                ;;
            esac
            let resource_counter=$resource_counter+1
        done
    ;;

    secondary)
        logger -p $log -t $name "Switching to secondary provider for - ${resources} -."

        # -- SERVICE MANAGEMENT --
        logger -p $log -t $name ">> Stopping services."
        resource_counter=1
        for resource in ${resources}; do
            resource_service=`echo $resource_services | cut -d\  -f$resource_counter`
            logger -p $log -t $name "Stopping services for resource - ${resource} -."
            case "${resource_service}" in
            mysql)
                logger -p $log -t $name "Service MySQL detected for resource - ${resource} -."
                logger -p $log -t $name "Stopping MySQL service for resource - ${resource} -."
                service mysql-server stop
                logger -p $log -t $name "Done for resource - ${resource} -."
                ;;
            nfs)
                logger -p $log -t $name "Service NFS detected for resource - ${resource} -."
                logger -p $log -t $name "Disabling NFS-ZFS share for resource - ${resource} -."
                zfs set sharenfs="off" FilesData
                logger -p $log -t $name "Done for resource - ${resource} -."
                logger -p $log -t $name "Restarting NFS service for resource - ${resource} -."
                service nfsd restart
                logger -p $log -t $name "Done for resource - ${resource} -."
                ;;
            *)
                logger -p local0.error -t $name "ERROR: Unknown service: ${resource_service}, exiting."
                exit 1
                ;;
            esac
            let resource_counter=$resource_counter+1
        done

        # -- FILESYSTEM MANAGEMENT --
        logger -p $log -t $name ">> Managing filesystems."
        resource_counter=1
        for resource in ${resources}; do
            resource_mountpoint=`echo $resource_mountpoints | cut -d\  -f$resource_counter`
            resource_filesystem=`echo $resource_filesystems | cut -d\  -f$resource_counter`
            case "${resource_filesystem}" in
            UFS)
                logger -p $log -t $name "UFS filesystem detected in resource - ${resource} -."
                if ! mount | grep -q "^/dev/hast/${resource} on "
                then
                else
                    logger -p $log -t $name "Umounting - ${resource} -."
                    umount -f ${resource_mountpoint}
                    logger -p $log -t $name "Done."
                fi
                sleep $delay
                ;;
            ZFS)
                logger -p $log -t $name "ZFS filesystem detected in resources - ${resource} -."
                if ! mount | grep -q "^${resource} on ${resource_mountpoint}"
                then
                else
                    logger -p $log -t $name "Umounting - ${resource} -."
                    zfs umount ${resource}
                    logger -p $log -t $name "Done."
                    logger -p $log -t $name "Exporting ZFS pool of resources - ${resource} -."
                    out=`zpool export -f "${resource}" 2>&1`
                    if [ $? -ne 0 ]; then
                        logger -p local0.error -t $name "ERROR: ZFS pool export for resource - ${resource} - failed: ${out}."
                        exit 1
                    fi
                    logger -p local0.error -t $name "ZFS pool for resource - ${resource} - exported successfully."
                fi
                sleep $delay
                ;;
            *)
                logger -p local0.error -t $name "ERROR: Unknown filesystem: ${resource_filesystem}, exiting."
                exit 1
                ;;
            esac
            let resource_counter=$resource_counter+1
        done

        # -- HAST ROLE MANAGEMENT --
        logger -p $log -t $name ">> Managing resources."
        resource_counter=1
        for resource in ${resources}; do
            logger -p $log -t $name "Switching resource - ${resource} - to secondary."
            hastctl role secondary ${resource} 2>&1
            if [ $? -ne 0 ]; then
                logger -p $log -t $name "ERROR: Unable to switch resource - ${resource} - to secondary role."
                exit 1
            fi
            logger -p $log -t $name "Role for resource - ${resource} - switched to secondary successfully."
            let resource_counter=$resource_counter+1
        done
    ;;
esac

Asignamos los permisos necesarios:

chmod 700 /usr/local/sbin/carp-hast-switch


Pruebas:

MySQL:
Para generar tráfico MySQL vamos a utilizar sysbench para ello creamos en el primary la base de datos sobre la que realizar el test:

mysql

root@localhost [(none)]> create database kr0m;
Query OK, 1 row affected (0.00 sec)

root@localhost [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kr0m               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

Creamos el usuario de acceso con los grants para la base de datos:

root@localhost [(none)]> create user sbtest_user identified by 'password';
Query OK, 0 rows affected (0.01 sec)

root@localhost [(none)]> grant all on kr0m.* to `sbtest_user`@`%`;
Query OK, 0 rows affected (0.01 sec)

root@localhost [(none)]> show grants for sbtest_user;
+-------------------------------------------------------+
| Grants for sbtest_user@%                              |
+-------------------------------------------------------+
| GRANT USAGE ON *.* TO `sbtest_user`@`%`               |
| GRANT ALL PRIVILEGES ON `kr0m`.* TO `sbtest_user`@`%` |
+-------------------------------------------------------+
2 rows in set (0.01 sec)

En nuestro pc instalamos sysbench:

pkg install sysbench

Creamos algunas tablas e insertamos datos en estas:

sysbench –db-driver=mysql –mysql-user=sbtest_user –mysql_password=password –mysql-db=kr0m –mysql-host=192.168.69.40 –mysql-port=3306 –tables=16 –table-size=10000 /usr/local/share/sysbench/oltp_read_write.lua prepare

Ahora que ya tenemos datos en la base de datos, dejmos sysbench realizando un test de lectura_escritura:

sysbench –db-driver=mysql –mysql-user=sbtest_user –mysql_password=password –mysql-db=kr0m –mysql-host=192.168.69.40 –mysql-port=3306 –tables=16 –threads=4 –time=0 –events=0 –report-interval=1 /usr/local/share/sysbench/oltp_read_write.lua run

NFS:
Para probar el acceso NFS utilizaremos bonnie++ , lo instalamos en nuestro pc donde tenemos el NFS montado:

pkg install bonnie++

Dejamos bonnie trabajando mientras realizamos las pruebas de failover.

bonnie++ -d /mnt/nfs/ -s 64G -n 0 -m HAST_NFS -f -b -u root

Failover:
Para migrar el servicio entre nodos disponemos de tres posibilidades:

  • Migrar la VIP, ejecutando en el nodo primary:

    ifconfig em0 vhid 1 state backup

  • Apagar ordenadamente el nodo primary:

    service mysql-server stop
    umount -f /var/db/mysql

    service nfsd stop
    zpool export -f FilesData

    service hastd stop

    shutdown -p now

  • Apagar abruptamente el nodo primary:

    Tirar del cable de alimentación eléctrica.

En caso de migrar la VIP el nodo que ha perdido la ip flotante se reconfigurará automáticamente como secondary en los otros dos casos cuando el nodo vuelva a la vida los recursos HAST estarán en estado init:

hastctl status MySQLData

Name	Status	 Role		Components
MySQLData	-        init           /dev/ada1	192.168.69.42
hastctl status FilesData
Name	Status	 Role		Components
FilesData	-        init           /dev/ada2	192.168.69.42

Debemos pasarlo a secondary:

hastctl role secondary MySQLData
hastctl role secondary FilesData
service mysql-server stop
service nfsd stop

Quedando del siguiente modo:

hastctl status MySQLData

Name	Status	 Role		Components
MySQLData	complete secondary      /dev/ada1	192.168.69.42
hastctl status FilesData
Name	Status	 Role		Components
FilesData	complete secondary      /dev/ada2	192.168.69.42

Troubleshooting:

Un punto muy importante es que los nodos tengan la misma hora, utilizar NTP es una buena idea.
En caso de Split-brain si se han escrito datos en los dos nodos el administrador debe decidir que datos son mas importantes y configurar el otro nodo como secondary descartando los datos:

hastctl role init test
hastctl create test
hastctl role secondary test

Hay ocasiones en las que el script de migración falla, siempre podemos ejecutarlo a mano para comprobar que el script no tenga ningún problema:

/usr/local/sbin/carp-hast-switch primary

Podemos ver los pasos realizados por el script de failover en los logs:

tail -f /var/log/debug.log

También podemos comprobar el estado de HAST:

hastctl status MySQLData
hastctl status FilesData

Comprobar si el pool ZFS está importado:

zpool list
zfs get sharenfs FilesData

Comprobar que la base de datos de prueba exista:

mysql -sre “show databases”

Comprobar que se tenga acceso NFS desde el cliente:

showmount -e 192.168.69.40

Debemos tener muy claro que HAST no es un backup, si se borran datos, se replica por red en el secondary perdiéndolos.
Además en ciertos escenarios como en su uso como backend para bases de datos puede ocasionar problemas, un apagado incorrecto de MySQL podría dejar los datos corrompidos, se replicarían a nivel de bloque en el secondary dejándonos con una base de datos corrupta en tal caso solo podemos restarurar un backup en el primary actual.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí