Configurar un clúster de SQL Server en Linux con grupos de disponibilidad Always On y Pacemaker

En este tutorial se describe cómo implementar un sistema de base de datos de Microsoft SQL Server en Linux mediante un grupo de disponibilidad Always On (AOAG) y Pacemaker como solución de alta disponibilidad (HA) y recuperación tras fallos (DR). En este documento, un desastre es un evento en el que falla una base de datos principal o deja de estar disponible.

Una base de datos principal puede fallar si la región en la que se encuentra falla o deja de ser accesible. Aunque una región esté disponible y funcione con normalidad, una base de datos principal puede fallar debido a un error del sistema. En estos casos, la recuperación ante desastres es el proceso de poner una base de datos secundaria a disposición de los clientes para que puedan seguir procesando datos.

Este tutorial está dirigido a arquitectos, administradores e ingenieros de bases de datos.

Preparar el proyecto y la red

Para preparar tu proyecto Google Cloud y tu VPC para desplegar grupos de disponibilidad Always On de SQL Server, haz lo siguiente:

  1. En la Google Cloud consola, abre Cloud Shell haciendo clic en el botón Activar Cloud Shell Activa Cloud Shell..

    Ir a la Google Cloud consola

  2. Configura tu ID de proyecto predeterminado:

    gcloud config set project PROJECT_ID
    

    Sustituye PROJECT_ID por el ID de tu Google Cloud proyecto.

  3. Define tu región predeterminada:

    gcloud config set compute/region REGION
    

    Sustituye REGION por el ID de la región en la que quieras hacer el despliegue.

  4. Define tu zona predeterminada:

    gcloud config set compute/zone ZONE
    

    Sustituye ZONE por el ID de la zona en la que quieras implementar el servicio. Debe ser una zona válida de la región especificada en el paso anterior.

Crear VMs Linux

Para conseguir la alta disponibilidad y el quórum del clúster de SQL Server, implementa tres máquinas virtuales Linux para alojar el clúster de SQL Server.

  1. Inicializa las siguientes variables:

    PD_SIZE=30
    MACHINE_TYPE=n2-standard-8
    
  2. Crea las máquinas virtuales de Linux:

    gcloud compute instances create node-1 \
    --project=PROJECT_ID \
    --zone REGION-a \
    --machine-type $MACHINE_TYPE \
    --subnet SUBNET_NAME \
    --create-disk=auto-delete=yes,boot=yes,device-name=node-1,image=projects/ubuntu-os-cloud/global/images/ubuntu-2004-focal-v20240426,mode=rw,size=$PD_SIZE,type=projects/PROJECT_ID/zones/REGION-a/diskTypes/pd-balanced \
    --scopes=https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/trace.append,https://www.googleapis.com/auth/devstorage.read_write
    
    gcloud compute instances create node-2 \
    --project=PROJECT_ID \
    --zone REGION-b \
    --machine-type $MACHINE_TYPE \
    --subnet SUBNET_NAME \
    --create-disk=auto-delete=yes,boot=yes,device-name=node-2,image=projects/ubuntu-os-cloud/global/images/ubuntu-2004-focal-v20240426,mode=rw,size=$PD_SIZE,type=projects/PROJECT_ID/zones/REGION-b/diskTypes/pd-balanced \
    --scopes=https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/trace.append,https://www.googleapis.com/auth/devstorage.read_write
    
    gcloud compute instances create node-3 \
    --project=PROJECT_ID \
    --zone REGION-c \
    --machine-type $MACHINE_TYPE \
    --subnet SUBNET_NAME \
    --create-disk=auto-delete=yes,boot=yes,device-name=node-3,image=projects/ubuntu-os-cloud/global/images/ubuntu-2004-focal-v20240426,mode=rw,size=$PD_SIZE,type=projects/PROJECT_ID/zones/REGION-c/diskTypes/pd-balanced \
    --scopes=https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/trace.append,https://www.googleapis.com/auth/devstorage.read_write
    

    Sustituye SUBNET_NAME por el nombre de tu subred de VPC.

  3. Actualiza el archivo hosts en node-1, node-2 y node-3:

    1. Conéctate a cada una de tus VMs mediante SSH. Consulta la documentación sobre cómo conectarse a máquinas virtuales Linux para obtener más información.
    2. Abre el archivo hosts para editarlo.

      sudo vi /etc/hosts
      
    3. Busca la dirección IP interna de cada máquina virtual Linux y añade las entradas de host a la parte inferior del archivo.

      Ir a Compute Engine

      NODE1_INTERNAL_IP node-1
      NODE2_INTERNAL_IP node-2
      NODE3_INTERNAL_IP node-3
      

      Sustituye NODE1_INTERNAL_IP, NODE2_INTERNAL_IP y NODE3_INTERNAL_IP por la dirección IP interna de cada VM Linux.

  4. Comprueba la comunicación entre tus máquinas virtuales. Todas las VMs que participen en el grupo de disponibilidad Always On deben poder comunicarse con otras VMs:

    1. Vuelve a cada máquina virtual Linux, ejecuta los comandos de cada máquina virtual y comprueba que todas las máquinas virtuales puedan comunicarse entre sí.

      ping -c 4 node-1
      ping -c 4 node-2
      ping -c 4 node-3
      

Instalar y configurar SQL Server

Descarga, instala y configura el motor de SQL Server en las tres máquinas virtuales Linux que participarán en el grupo de disponibilidad Always On.

  1. Conéctate por SSH a node-1, node-2 y node-3, y sigue estos pasos:

    1. Importa las claves del repositorio público.

      wget -qO- https://packages.microsoft.com/keys/microsoft.asc \
      | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
      
    2. Registra el repositorio de Ubuntu de SQL Server.

      sudo add-apt-repository \
      "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/mssql-server-2019.list)"
      
    3. Actualiza los archivos de índice de paquetes e instala SQL Server.

      sudo apt-get update
      sudo apt-get install -y mssql-server
      
      
  2. Configura SQL Server:

    1. Ejecuta la herramienta mssql-conf.

      sudo /opt/mssql/bin/mssql-conf setup
      
    2. Elige la edición Developer de SQL Server y acepta el contrato de licencia.

      La edición para desarrolladores incluye todas las funciones de la edición Enterprise, pero solo se puede usar en entornos que no sean de producción. Consulta más información sobre las ediciones de SQL Server y las licencias de Microsoft.

    3. Especifica una contraseña para la cuenta de SA.

    4. Comprueba que el servicio mssql-server se esté ejecutando.

      systemctl status mssql-server --no-pager
      
  3. Si tienes un cortafuegos habilitado en tus VMs, ábrelo para SQL Server:

    1. Comprueba si Uncomplicated Firewall está instalado y habilitado ejecutando el siguiente comando.

      sudo ufw status
      
    2. Si el estado es activo, ejecuta los siguientes comandos para abrir los puertos.

      sudo ufw allow 1433
      sudo ufw allow 5022
      sudo ufw reload
      

Conectarse a SQL Server

En este punto, SQL Server está instalado. Para conectarte a ella, crea un equipo Windows en la misma VPC, instala SQL Server Management Studio (SSMS) para conectarte a la instancia de SQL Server que acabas de crear en tus máquinas virtuales:

  1. Crea una VM de Windows:

    1. Vuelve a Cloud Shell y ejecuta el siguiente comando.

      gcloud compute instances create node4 \
      --project=PROJECT_ID \
      --zone ZONE \
      --subnet SUBNET_NAME \
      --machine-type=n2-standard-4 \
      --create-disk=auto-delete=yes,boot=yes,device-name=node4,image=projects/windows-cloud/global/images/windows-server-2022-dc-v20240415,mode=rw,size=50,type=projects/p3rf-sqlserver/zones/ZONE/diskTypes/pd-balanced
      
  2. Conéctate a la VM de Windows en node-4 mediante Escritorio Remoto:

  3. Actualiza el archivo hosts en node-4:

    1. Abre el Bloc de notas en modo administrador.
    2. Haz clic en Archivo > Abrir y abre el archivo hosts.

      c:\Windows\System32\drivers\etc\hosts
      
    3. Añade las entradas de host a la parte inferior del archivo.

      NODE1_INTERNAL_IP node-1
      NODE2_INTERNAL_IP node-2
      NODE3_INTERNAL_IP node-3
      

      Sustituye NODE1_INTERNAL_IP, NODE2_INTERNAL_IP y NODE3_INTERNAL_IP por la dirección IP interna correspondiente de cada VM.

    4. Guarda los cambios y sal.

  4. Verifica la conectividad a las VMs de Linux:

    1. Conéctate a la VM de Windows en node-4.
    2. Haz clic en el botón Inicio y escribe powershell en la barra de búsqueda.
    3. Haz clic para abrir la aplicación Windows PowerShell ISE.
    4. Prueba la conectividad ejecutando los siguientes comandos.

      ping node-1
      ping node-2
      ping node-3
      
  5. Instala Microsoft SQL Server Management Studio (SSMS) siguiendo estos pasos:

    1. Conéctate a la VM de Windows en node-4 mediante Escritorio remoto.

    2. En tu sesión de RDP, minimiza todas las ventanas e inicia la aplicación Windows PowerShell ISE.

    3. En el símbolo del sistema de PowerShell, descarga y ejecuta el instalador de SSMS.

      Start-BitsTransfer `
      -Source "https://aka.ms/ssmsfullsetup" `
      -Destination "$env:Temp\ssms-setup.exe"
      & $env:Temp\ssms-setup.exe
      
    4. En el instalador de SSMS, haz clic en Instalar.

    5. Acepta la petición para permitir que se hagan cambios.

    6. Cuando se haya completado la instalación, haz clic en Reiniciar para reiniciar el equipo remoto. De esta forma, se cierra la sesión de RDP.

  6. Conéctate a la instancia de SQL Server en el nodo 1:

    1. Vuelve a la node-4 mediante RDP.

    2. Abre SSMS y conéctate a node-1 con los siguientes parámetros.

      Server name: node-1
      Authentication: SQL Server Authentication
      Login: sa
      

      Para obtener más información, consulta cómo conectarse a una instancia de SQL Server mediante la documentación de SQL Server Management Studio.

    3. Introduce la contraseña de la cuenta SA creada durante la instalación.

    4. Selecciona Confiar en el certificado del servidor.

    5. Haz clic en Conectar.

Habilitar el grupo de disponibilidad Always On

En Linux, primero debes crear un grupo de disponibilidad para poder añadirlo como recurso que gestionará Pacemaker:

  1. Habilita la función de grupo de disponibilidad Always On en cada instancia de SQL Server que participe en el grupo de disponibilidad. Ejecuta los siguientes comandos en node-1, node-2 y node-3:

    sudo /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1
    sudo systemctl restart mssql-server
    
  2. Conéctate a la instancia que es el host principal del grupo de disponibilidad mediante SSMS:

    1. Abre una nueva ventana de consulta.

    2. Ejecuta el siguiente fragmento de código para crear una clave de cifrado, un certificado y una clave privada.

      USE MASTER;
      
      CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'ENCRYPTION_KEY_PASSWORD';
      CREATE CERTIFICATE my_ag_certificate WITH SUBJECT = 'my_ag_cert';
      BACKUP CERTIFICATE my_ag_certificate
      TO FILE = '/var/opt/mssql/data/my_ag_certificate.cer'
      WITH PRIVATE KEY (
          FILE = '/var/opt/mssql/data/my_ag_certificate.pvk',
          ENCRYPTION BY PASSWORD = 'PRIVATE_KEY_PASSWORD'
      );
      

      Sustituye ENCRYPTION_KEY_PASSWORD y PRIVATE_KEY_PASSWORD por las contraseñas de la clave de cifrado y la clave privada.

Transfiere los archivos de certificado y de clave

Los archivos de certificado y de clave creados en los pasos anteriores deben moverse a los nodos secundarios de SQL Server. Hay varios métodos para mover los archivos de certificado y clave a los nodos secundarios de node-2 y node-3.

Para ver otras opciones de transferencia, consulta Transferir archivos a máquinas virtuales Linux.

Transfiere los archivos de certificado y clave mediante Cloud Storage

Crea un Cloud Storage para transferir archivos de los nodos del clúster principal a los del secundario.

  1. Crea un segmento de Cloud Storage:

    1. Vuelve a Cloud Shell y ejecuta el siguiente comando:

      gcloud storage buckets create gs://BUCKET_NAME \
      --project=PROJECT_ID \
      --location=REGION \
      --public-access-prevention
      

      Sustituye BUCKET_NAME por el nombre del bucket que quieras crear. Sustituye PROJECT_ID por el ID de tu Google Cloud proyecto y REGION por el ID de la región en la que quieras desplegar el bucket.

    Para obtener más información, consulta Crear segmentos.

  2. Vuelve a SSH en node-1, node-2 y node-3 para inicializar la CLI de Google Cloud:

    1. Ejecuta el siguiente comando para inicializar la CLI de Google Cloud.

      gcloud init
      
    2. Elige option [1] para usar la cuenta de servicio preinstalada.

    3. Escribe el nombre del proyecto.

    4. Introduce n en la pregunta para configurar la región y la zona predeterminadas.

  3. Vuelve a node-1 para copiar los archivos en Cloud Storage:

    1. Sube los dos archivos que acabas de crear a Cloud Storage con los siguientes comandos.

      sudo gcloud storage cp /var/opt/mssql/data/my_ag_certificate.cer gs://BUCKET_NAME/
      sudo gcloud storage cp /var/opt/mssql/data/my_ag_certificate.pvk gs://BUCKET_NAME/
      

      Sustituye BUCKET_NAME por el nombre del bucket creado.

  4. Vuelve a node-2 y node-3 para copiar los archivos de Cloud Storage:

    1. Descarga los dos archivos de Cloud Storage en node-2.

      sudo gcloud storage cp gs://BUCKET_NAME/my_ag_certificate.cer /var/opt/mssql/data/
      sudo gcloud storage cp gs://BUCKET_NAME/my_ag_certificate.pvk /var/opt/mssql/data/
      

      Sustituye BUCKET_NAME por el nombre del bucket creado.

    2. Cambia la propiedad de los archivos de node-2 y node-3 ejecutando el comando en un shell raíz.

      chown mssql:mssql /var/opt/mssql/data/my_ag_certificate.*
      chmod 660 /var/opt/mssql/data/my_ag_certificate.*
      
      

Configurar un endpoint de creación de reflejo de la base de datos

En esta sección, crearás el endpoint de la base de datos con una clave de cifrado y un certificado compartidos por cada nodo del clúster de SQL Server para asegurar la replicación de datos.

  1. Vuelve a la máquina virtual de Windows en node-4 para crear los endpoints de creación de reflejo de la base de datos:

    1. Conéctate a las bases de datos de SQL Server en node-1, node-2 y node-3 mediante SSMS. Sigue los pasos que se indican en Conectarse a SQL Server usando node-1, node-2 y node-3 como nombre de servidor y las contraseñas que hayas definido para la cuenta SA.

    2. Crea el certificado en las VMs secundarias node-2 y node-3 a partir de los archivos copiados. Usa las contraseñas que proporcionaste al crear el certificado y la clave en el nodo principal.

      USE MASTER;
      
      CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'ENCRYPTION_KEY_PASSWORD';
      CREATE CERTIFICATE my_ag_certificate
      FROM FILE = '/var/opt/mssql/data/my_ag_certificate.cer'
      WITH PRIVATE KEY (
          FILE = '/var/opt/mssql/data/my_ag_certificate.pvk',
          DECRYPTION BY PASSWORD = 'PRIVATE_KEY_PASSWORD'
      );
      

      Sustituye ENCRYPTION_KEY_PASSWORD y PRIVATE_KEY_PASSWORD por las contraseñas de la clave de cifrado y la clave privada.

    3. Vuelve a SSMS para crear endpoints de creación de reflejo de la base de datos ejecutando el comando T-SQL para node-1, node-2 y node-3.

      CREATE ENDPOINT [my_ag_endpoint]
          AS TCP (LISTENER_PORT = 5022)
          FOR DATABASE_MIRRORING (
              ROLE = ALL,
              AUTHENTICATION = CERTIFICATE my_ag_certificate,
              ENCRYPTION = REQUIRED ALGORITHM AES
          );
      
      ALTER ENDPOINT [my_ag_endpoint] STATE = STARTED;
      

Crear y configurar el grupo de disponibilidad Always On

A continuación, crea el grupo de disponibilidad Always On de SQL Server con SQL Server Management Studio y usa los endpoints creados anteriormente para la replicación.

  1. Vuelve a la VM de Windows y abre SSMS:

    1. Conéctate al motor de base de datos de SQL Server en node-1 y abre una nueva ventana de consulta.
  2. Crea una base de datos y haz una copia de seguridad de la base de datos para preparar la replicación:

    USE MASTER;
    
    CREATE DATABASE [bookshelf];
    ALTER DATABASE [bookshelf] SET RECOVERY FULL;
    BACKUP DATABASE [bookshelf]
    TO DISK = N'/var/opt/mssql/data/bookshelf.bak';
    
  3. Crea el grupo de disponibilidad Always On:

    1. Ejecuta el siguiente comando de T-SQL en SSMS en node-1, node-2 y node-3. De esta forma, los endpoints estarán habilitados y SQL Server en cada nodo estará listo para la replicación de datos.

      IF (SELECT state FROM sys.endpoints WHERE name = N'my_ag_endpoint') <> 0
      BEGIN
          ALTER ENDPOINT [my_ag_endpoint] STATE = STARTED
      END
      GO
      
      IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='AlwaysOn_health')
      BEGIN
          ALTER EVENT SESSION [AlwaysOn_health] ON SERVER WITH (STARTUP_STATE=ON);
      END
      IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name='AlwaysOn_health')
      BEGIN
          ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START;
      END
      GO
      
    2. Ejecuta el siguiente comando de T-SQL en node-1 para crear el grupo de disponibilidad Always On.

      USE [master]
      GO
      
      CREATE AVAILABILITY GROUP [aoag1]
      WITH (
          AUTOMATED_BACKUP_PREFERENCE = SECONDARY,
          DB_FAILOVER = OFF,
          DTC_SUPPORT = NONE,
          CLUSTER_TYPE = EXTERNAL,
          REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT = 0
      )
      FOR DATABASE [bookshelf]
      REPLICA ON N'node-1' WITH (
          ENDPOINT_URL = N'TCP://node-1:5022', FAILOVER_MODE = EXTERNAL, AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SEEDING_MODE = AUTOMATIC, SECONDARY_ROLE(ALLOW_CONNECTIONS = NO)),
          N'node-2' WITH (ENDPOINT_URL = N'TCP://node-2:5022', FAILOVER_MODE = EXTERNAL, AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SEEDING_MODE = AUTOMATIC, SECONDARY_ROLE(ALLOW_CONNECTIONS = NO)),
          N'node-3' WITH (ENDPOINT_URL = N'TCP://node-3:5022', FAILOVER_MODE = EXTERNAL, AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SEEDING_MODE = AUTOMATIC, SECONDARY_ROLE(ALLOW_CONNECTIONS = NO)
      );
      GO
      
    3. Ejecuta el siguiente comando T-SQL en node-2 y node-3 para cada instancia de SQL Server que quieras unir al nuevo grupo de disponibilidad.

      ALTER AVAILABILITY GROUP [aoag1] JOIN WITH (CLUSTER_TYPE = EXTERNAL);
      GO
      
      ALTER AVAILABILITY GROUP [aoag1] GRANT CREATE ANY DATABASE;
      GO
      

    Has creado una base de datos llamada bookshelf y la has añadido a un grupo de disponibilidad llamado aoag1 en la instancia de SQL Server que se ejecuta en node-1. Node-2 y node-3 se han añadido al grupo de disponibilidad y los datos de la base de datos bookshelf se replicarán de forma síncrona en las instancias de SQL Server de los tres nodos.

Instalar y configurar Pacemaker

Pacemaker es un software de gestión de recursos de alta disponibilidad de código abierto que se usa con el motor de clústeres Corosync. En esta sección, instalará y configurará Pacemaker en cada una de sus máquinas virtuales.

Crear un inicio de sesión de SQL Server para el gestor de clústeres de Pacemaker

En esta sección, crearás una cuenta de SQL Server para que Pacemaker la use para iniciar sesión en cada instancia de SQL Server y gestionar el grupo de disponibilidad.

  1. Ejecuta el siguiente comando de T-SQL en node-1, node-2 y node-3:

    USE [master];
    
    CREATE LOGIN [pacemaker] with PASSWORD= N'PACEMAKER_LOGIN_PASSWORD';
    GO
    

    Sustituye PACEMAKER_LOGIN_PASSWORD por una contraseña para la cuenta del marcapasos.

  2. Ejecuta el comando T-SQL para conceder los permisos de inicio de sesión de Pacemaker al grupo de disponibilidad:

    GRANT ALTER, CONTROL, VIEW DEFINITION ON AVAILABILITY GROUP::[aoag1] TO [pacemaker];
    GRANT VIEW SERVER STATE TO [pacemaker];
    GO
    
  3. Vuelve a SSH en node-1, node-2 y node-3 para ejecutar los comandos que guardan el nombre de usuario y la contraseña de Pacemaker en la carpeta de secretos de SQL Server:

    echo 'pacemaker' >> ~/pacemaker-passwd
    echo 'PACEMAKER_LOGIN_PASSWORD' >> ~/pacemaker-passwd
    sudo mv ~/pacemaker-passwd /var/opt/mssql/secrets/passwd
    sudo chown root:root /var/opt/mssql/secrets/passwd
    sudo chmod 400 /var/opt/mssql/secrets/passwd
    

    Sustituye PACEMAKER_LOGIN_PASSWORD por la contraseña de la cuenta del marcapasos.

Instalar Pacemaker

A continuación, instala Pacemaker y configura una cuenta de inicio de sesión en todas las máquinas virtuales Linux para gestionar los recursos.

  1. Abre los puertos del cortafuegos para Pacemaker:

    1. Comprueba si Uncomplicated Firewall está instalado y habilitado ejecutando el siguiente comando en node-1, node-2 y node-3.

      sudo ufw status
      
    2. Si ufw está habilitado, abre los puertos del cortafuegos en node-1, node-2 y node-3.

      sudo ufw allow 2224/tcp
      sudo ufw allow 3121/tcp
      sudo ufw allow 5405/udp
      sudo ufw allow 21064/tcp
      sudo ufw allow 1433/tcp
      sudo ufw allow 5022/tcp
      sudo ufw reload
      
  2. Instala Pacemaker en node-1, node-2 y node-3:

    sudo apt-get install -y pacemaker pacemaker-cli-utils crmsh resource-agents  fence-agents corosync python3-azure pcs
    
  3. Define una nueva contraseña para el usuario hacluster en node-1, node-2 y node-3:

    sudo passwd hacluster
    

Configurar Corosync

Ahora configurarás Corosync para gestionar la pertenencia al clúster y la mensajería en todo el clúster.

  1. Crea una clave de autenticación para Corosync en node-1:

    sudo corosync-keygen
    
  2. Modifica el archivo de configuración de Corosync:

    1. Vuelve a node-1 y modifica el archivo corosync.conf.

      sudo vi /etc/corosync/corosync.conf
      
    2. Actualiza las secciones resaltadas. Después de editarlo, el archivo debería tener un aspecto similar al del siguiente ejemplo.

      # Please read the corosync.conf.5 manual page
      totem {
          version: 2
      
          # Corosync itself works without a cluster name, but DLM needs one.
          # The cluster name is also written into the VG metadata of newly
          # created shared LVM volume groups, if lvmlockd uses DLM locking.
          cluster_name: my_agcluster
      
          # crypto_cipher and crypto_hash: Used for mutual node authentication.
          # If you choose to enable this, then do remember to create a shared
          # secret with "corosync-keygen".
          # enabling crypto_cipher, requires also enabling of crypto_hash.
          # crypto works only with knet transport
          transport: udpu
          crypto_cipher: none
          crypto_hash: none
      }
      
      logging {
          # Log the source file and line where messages are being
          # generated. When in doubt, leave off. Potentially useful for
          # debugging.
          fileline: off
          # Log to standard error. When in doubt, set to yes. Useful when
          # running in the foreground (when invoking "corosync -f")
          to_stderr: yes
          # Log to a log file. When set to "no", the "logfile" option
          # must not be set.
          to_logfile: yes
          logfile: /var/log/corosync/corosync.log
          # Log to the system log daemon. When in doubt, set to yes.
          to_syslog: yes
          # Log debug messages (very verbose). When in doubt, leave off.
          debug: off
          # Log messages with time stamps. When in doubt, set to hires (or on)
          #timestamp: hires
          logger_subsys {
              subsys: QUORUM
              debug: off
          }
      }
      quorum {
          # Enable and configure quorum subsystem (default: off)
          # see also corosync.conf.5 and votequorum.5
          provider: corosync_votequorum
      }
      nodelist {
          # Change/uncomment/add node sections to match cluster configuration
      
          node {
              # Hostname of the node
              name: node-1
              # Cluster membership node identifier
              nodeid: 1
              # Address of first link
              ring0_addr: NODE1_INTERNAL_IP
              # When knet transport is used it's possible to define up to 8 links
              #ring1_addr: 192.168.1.1
          }
          node {
              name: node-2
              nodeid: 2
              ring0_addr: NODE2_INTERNAL_IP
          }
          node {
              name: node-3
              nodeid: 3
              ring0_addr: NODE3_INTERNAL_IP
          }
          # ...
      }
      

      Sustituye NODE1_INTERNAL_IP, NODE2_INTERNAL_IP y NODE3_INTERNAL_IP por las direcciones IP internas de cada nodo.

Transferir los archivos de configuración mediante Cloud Storage

  1. Sube los archivos de clave de autenticación y de configuración de corosync generados desde node-1 a tu segmento de Cloud Storage:

    sudo gcloud storage cp /etc/corosync/authkey gs://BUCKET_NAME/
    sudo gcloud storage cp  /etc/corosync/corosync.conf gs://BUCKET_NAME/
    

    Sustituye BUCKET_NAME por el nombre del segmento que has creado anteriormente.

  2. Descarga los archivos Authkey y de configuración en node-2 y node-3:

    sudo gcloud storage cp gs://BUCKET_NAME/authkey /etc/corosync/
    sudo gcloud storage cp gs://BUCKET_NAME/corosync.conf /etc/corosync/
    

    Sustituye BUCKET_NAME por el nombre del bucket al que se transfirieron los archivos de configuración de Corosync.

  3. Actualiza los permisos de los archivos de node-2 y node-3:

    sudo chmod 400 /etc/corosync/authkey
    sudo chmod 400 /etc/corosync/corosync.conf
    

Reiniciar y verificar la comunicación del clúster

  1. Reinicia los servicios Pacemaker y Corosync en node-1, node-2 y node-3:

    sudo systemctl restart pacemaker corosync
    
  2. Para confirmar el estado del clúster, ejecuta el comando en node-1:

    sudo crm status
    

    Deberían aparecer los tres nodos online.

Configurar el clúster

A continuación, configurará el clúster de Pacemaker creando un recurso para el grupo de disponibilidad Always On de SQL Server.

  1. Ejecuta el siguiente comando en node-1 para definir las propiedades del clúster:

    sudo crm configure property stonith-enabled=false
    sudo crm configure property cluster-recheck-interval=2min
    sudo crm configure property start-failure-is-fatal=true
    

    Para obtener más información, consulta Opciones de clúster.

  2. Autoriza los nodos del clúster ejecutando el comando en node-1. Usa la contraseña que configuraste anteriormente para la cuenta de hacluster:

    sudo pcs cluster auth -u hacluster
    

    Deberías ver que los tres nodos están autorizados.

  3. Instala el agente de recursos de SQL Server para integrarlo con Pacemaker en node-1, node-2 y node-3:

    sudo apt-get install mssql-server-ha
    
  4. Vuelve a node-1 y crea un recurso de grupo de disponibilidad en el clúster:

    1. Ejecuta el gestor de recursos de clúster.

      sudo crm
      
    2. Escribe configure para acceder al menú de configuración.

    3. Introduce la siguiente configuración.

      primitive aoag1-cluster \
      ocf:mssql:ag \
      params ag_name="aoag1" \
      meta failure-timeout=60s \
      op start timeout=60s \
      op stop timeout=60s \
      op promote timeout=60s \
      op demote timeout=10s \
      op monitor timeout=60s interval=10s \
      op monitor timeout=60s on-fail=demote interval=11s role="Master" \
      op monitor timeout=60s interval=12s role="Slave" \
      op notify timeout=60s
      ms ms-ag1 aoag1-cluster \
      meta master-max="1" master-node-max="1" clone-max="3" \
      clone-node-max="1" notify="true"
      
    4. Escribe commit para confirmar los cambios.

    5. Escribe exit para salir del gestor de recursos del clúster.

    6. Verifica la configuración.

      sudo crm status
      

      Deberías ver que node-1 se ha convertido en el nodo principal. Node-2 y node-3 deben definirse como nodos secundarios.

Configurar el balanceador de carga y el agente de escucha del grupo de disponibilidad

En esta sección, creará una dirección IP virtual y un recurso de comprobación del estado en el clúster mediante un balanceador de carga TCP passthrough interno que enruta el tráfico al grupo de disponibilidad.

  1. Vuelve a Cloud Shell y reserva una dirección IP estática que usarás como IP del clúster:

    gcloud compute addresses create aoag1-cluster \
    --region REGION \
    --subnet SUBNET_NAME
    CLUSTER_ADDRESS=$(gcloud compute addresses describe aoag1-cluster \
    --region $(gcloud config get-value compute/region) \
    --format=value\(address\)) && \
    echo "Cluster IP address: $CLUSTER_ADDRESS"
    

    Sustituye REGION y SUBNET_NAME por la región y la subred en las que se han desplegado las VMs Linux.

  2. Crea grupos de instancias sin gestionar para cada uno de los nodos del clúster y asígnalos al grupo de instancias que acabas de crear. Ejecuta los siguientes comandos en Cloud Shell:

    gcloud compute instance-groups unmanaged create node-1-uig \
    --zone=REGION-a
    gcloud compute instance-groups unmanaged add-instances node-1-uig \
    --zone=REGION-a \
    --instances=node-1
    
    gcloud compute instance-groups unmanaged create node-2-uig \
    --zone=REGION-b
    gcloud compute instance-groups unmanaged add-instances node-2-uig \
    --zone=REGION-b \
    --instances=node-2
    
    gcloud compute instance-groups unmanaged create node-3-uig \
    --zone=REGION-c
    gcloud compute instance-groups unmanaged add-instances node-3-uig \
    --zone=REGION-c \
    --instances=node-3
    

    Sustituye REGION por la región en la que se han desplegado las VMs Linux.

  3. Crea una comprobación del estado TCP. Los balanceadores de carga usan comprobaciones del estado para determinar qué instancias de backend responden correctamente al tráfico.

    gcloud compute health-checks create tcp aoag1-healthcheck \
    --port=HEALTH_CHECK_PORT --proxy-header=NONE \
    --check-interval=10 --timeout=10 --unhealthy-threshold=2 \
    --healthy-threshold=2
    

    Elige y sustituye HEALTH_CHECK_PORT por el valor de un puerto que esté libre y que se encuentre en el intervalo privado 49152-65535 . Por ejemplo, 60000.

    Para obtener más información, consulta el resumen de las comprobaciones del estado.

  4. Añade etiquetas de red a los nodos de tu clúster. La regla de cortafuegos usa la etiqueta de red para la comprobación del estado:

    gcloud compute instances add-tags node-1 \
    --tags NETWORK_TAG_NAME \
    --zone REGION-a
    gcloud compute instances add-tags node-2 \
    --tags NETWORK_TAG_NAME \
    --zone REGION-b
    gcloud compute instances add-tags node-3 \
    --tags NETWORK_TAG_NAME \
    --zone REGION-c
    

    Sustituye NETWORK_TAG_NAME por el nombre de la etiqueta de red.

  5. Crea una regla de cortafuegos para permitir que las comprobaciones del estado lleguen a los nodos del clúster en función del nombre de la etiqueta:

    gcloud compute firewall-rules create mssql-aoag1-fw-rule \
    --network VPC_NAME \
    --action ALLOW \
    --direction INGRESS \
    --source-ranges 35.191.0.0/16,130.211.0.0/22 \
    --target-tags NETWORK_TAG_NAME \
    --rules tcp:HEALTH_CHECK_PORT
    

    Para obtener más información, consulta Reglas de cortafuegos para comprobaciones del estado.

  6. Crea el servicio de backend del balanceador de carga:

    gcloud compute backend-services create aoag1-backend \
    --load-balancing-scheme internal \
    --health-checks aoag1-healthcheck \
    --no-connection-drain-on-failover \
    --drop-traffic-if-unhealthy \
    --failover-ratio 1.0 \
    --region REGION \
    --global-health-checks
    
  7. Añade los tres grupos de instancias sin gestionar al servicio de backend:

    gcloud compute backend-services add-backend aoag1-backend \
    --instance-group node-1-uig \
    --instance-group-zone REGION-a \
    --region REGION
    
    gcloud compute backend-services add-backend aoag1-backend \
    --instance-group node-2-uig \
    --instance-group-zone REGION-b \
    --failover \
    --region REGION
    
    gcloud compute backend-services add-backend aoag1-backend \
    --instance-group node-3-uig \
    --instance-group-zone REGION-c \
    --failover \
    --region REGION
    
  8. Define una regla de reenvío para tu balanceador de carga. Una regla de reenvío especifica el protocolo y los puertos en los que el balanceador de carga acepta tráfico:

    gcloud compute forwarding-rules create aoag1-fwd-rule \
    --load-balancing-scheme internal \
    --address CLUSTER_ADDRESS \
    --subnet SUBNET_NAME \
    --region REGION \
    --backend-service aoag1-backend \
    --ports ALL
    

    Sustituye CLUSTER_ADDRESS por la dirección IP que has reservado anteriormente.

    Para obtener más información, consulta Reglas de reenvío.

  9. Para completar la configuración y comprobar si el balanceador de carga de red está configurado correctamente, instala y configura el HAProxy tcp listener en node-1, node-2 y node-3:

    1. Instala HAProxy.

      sudo apt-get install haproxy
      

    2. Elige Y para completar la instalación.

    3. Edita el archivo haproxy.cfg.

      sudo vi /etc/haproxy/haproxy.cfg
      
    4. En la sección de valores predeterminados de la haproxy.cfg file, cambia el modo a tcp.

    5. Añade la siguiente sección al final del archivo haproxy.cfg

      #---------------------------------------------------------------
      # Set up health check listener for SQL Server Availability Group
      #---------------------------------------------------------------
      listen healthcheck
      bind *:HEALTH_CHECK_PORT
      

      Sustituye HEALTH_CHECK_PORT por el puerto de comprobación del estado seleccionado anteriormente. Por ejemplo, 6000.

    6. Inicia el servicio para confirmar que está configurado correctamente:

      sudo systemctl start haproxy.service
      sudo systemctl enable haproxy.service
      sudo systemctl restart haproxy.service
      
    7. Ve a la página Balanceo de carga y haz clic en tu balanceador de carga. Observa los tres grupos de instancias sin gestionar. Ahora deberían mostrarse como correctos.

      Ir a Balanceo de carga

      • También puede ejecutar el siguiente comando en Cloud Shell para ver el estado del servicio backend.

        gcloud compute backend-services get-health aoag1-backend \
        --region REGION
        

        Sustituye REGION por la región en la que se han desplegado las VMs Linux.

    8. Cuando los tres grupos de instancias no gestionados estén en buen estado, continúa con el siguiente paso.

      sudo systemctl restart haproxy.service
      
  10. Crea el recurso de comprobación del estado en Pacemaker:

    1. Conéctate por SSH a node-1 y crea un recurso de comprobación de estado para el servicio HAProxy en tu clúster de Pacemaker:

      sudo pcs resource create aoag1-healthcheck \
      service:haproxy \
      op monitor interval=10s timeout=20s
      
    2. Comprueba que el recurso de comprobación del estado se haya iniciado en el nodo principal node-1:

      sudo crm status
      
    3. Si el recurso de comprobación del estado no se inicia en el nodo principal, muévelo con los siguientes comandos:

      sudo pcs resource move aoag1-healthcheck node-1
      sudo pcs resource clear aoag1-healthcheck
      

      Verás que la comprobación del estado del balanceador de carga solo será correcta para node-1.

      Ir a Balanceo de carga

  11. Crea un recurso de dirección IP virtual en tu clúster de Pacemaker:

    1. Vuelve a SSH en node-1 y busca el nombre de la interfaz de red de tu nodo. Lo necesitarás en el siguiente paso.

      ip -c link
      
    2. Crea el recurso de dirección IP virtual.

      sudo pcs resource create aoag1-vip ocf:heartbeat:IPaddr2 \
      ip="CLUSTER_ADDRESS" nic=NIC_NAME cidr_netmask=32 \
      op monitor interval=3600s timeout=60s
      

      Sustituye NIC_NAME por el nombre de la interfaz de red del paso anterior y CLUSTER_ADDRESS por la dirección IP reservada.

    3. Comprueba que el recurso de dirección IP virtual se haya iniciado en el host principal.

      sudo crm status
      
    4. Si el recurso de dirección IP virtual no se inicia en el nodo principal, muévelo con los siguientes comandos.

      sudo pcs resource move aoag1-vip node-1
      
    5. Agrupa los recursos de comprobación del estado y de dirección IP virtual.

      sudo pcs resource group add aoag1-group \
      aoag1-healthcheck aoag1-vip
      
    6. Crea una restricción que coloque el nuevo grupo en el mismo nodo que el principal.

      sudo pcs constraint colocation add master aoag1-group with master ms-ag1 score=INFINITY
      

Crear un receptor para el grupo de disponibilidad de SQL Server

Las conexiones a SQL Server con grupos de disponibilidad deben usar un nombre de escucha de grupo de disponibilidad en lugar del nombre del servidor. Si se produce una conmutación por error, el receptor redirigirá automáticamente las conexiones al nuevo nodo principal del clúster.

  1. Vuelve a SSMS y conéctate a la base de datos node-1.

  2. Ejecuta la siguiente consulta:

    ALTER AVAILABILITY GROUP aoag1
    ADD LISTENER 'aoag1-listener' (
        WITH IP (('CLUSTER_ADDRESS','255.255.255.0')), PORT=1433
    );
    GO
    

    Sustituye CLUSTER_ADDRESS por la dirección IP reservada.

Configurar un vallado STONITH

STONITH es una estrategia de aislamiento para mantener la integridad de los nodos de un clúster de alta disponibilidad. El servicio STONITH funciona a nivel de nodo y protege el clúster de los nodos que no responden o que se encuentran en un estado desconocido. Recomendamos el fence_gcedispositivo de valla especializado para Compute Engine Google Cloud.

Configurar dispositivos de valla

  1. Comprueba si el agente de valla fence_gce para Compute Engine está instalado en node1:

    sudo pcs stonith list | grep fence_gce
    

    Para obtener más información, consulta estos artículos:

  2. En node-1, cree los recursos de tipo de valla fence_gce para cada uno de los nodos participantes:

    sudo pcs stonith create node-1-fence fence_gce \
    plug=node-1 \
    zone=REGION-a \
    project=PROJECT_ID \
    pcmk_reboot_timeout=300 pcmk_monitor_retries=4 pcmk_delay_max=30 \
    op monitor interval="300s" timeout="120s" \
    op start interval="0" timeout="60s"
    
    sudo pcs stonith create node-2-fence fence_gce \
    plug=node-2 \
    zone=REGION-b \
    project=PROJECT_ID \
    pcmk_reboot_timeout=300 pcmk_monitor_retries=4 pcmk_delay_max=30 \
    op monitor interval="300s" timeout="120s" \
    op start interval="0" timeout="60s"
    
    sudo pcs stonith create node-3-fence fence_gce \
    plug=node-3 \
    zone=REGION-c \
    project=PROJECT_ID \
    pcmk_reboot_timeout=300 pcmk_monitor_retries=4 pcmk_delay_max=30 \
    op monitor interval="300s" timeout="120s" \
    op start interval="0" timeout="60s"
    

    Sustituye REGION por la región en la que se han implementado las VMs Linux y PROJECT_ID por el ID de tu proyecto.

  3. Puedes probar el estado de los agentes de valla ejecutando el comando de estado:

    sudo fence_gce -o status -n node-1 --zone=REGION-a
    sudo fence_gce -o status -n node-2 --zone=REGION-b
    sudo fence_gce -o status -n node-3 --zone=REGION-c
    
  4. Crea restricciones de ubicación para tus dispositivos de vallas geográficas para asegurarte de que solo se ejecuten en las instancias previstas:

    sudo pcs constraint location node-1-fence avoids node-1
    sudo pcs constraint location node-2-fence avoids node-2
    sudo pcs constraint location node-3-fence avoids node-3
    
  5. Habilita el aislamiento en tu clúster de Pacemaker y define el tiempo de espera del aislamiento del clúster:

    sudo pcs -f stonith_cfg property set stonith-enabled=true
    sudo pcs property set stonith-timeout="300s"
    
  6. Comprueba el estado del clúster:

    sudo crm status
    

Probar los dispositivos de vallado

Una vez que hayas configurado los dispositivos de valla, te recomendamos que los pruebes siguiendo estos pasos.

  1. Detener la valla en node-2:

    1. Conéctate a node-1 y ejecuta el siguiente comando para probar el dispositivo de valla asociado a node-2 desde tu clúster.

      fence_gce -o off -n node-2 --zone=REGION-b
      
    2. Comprueba el estado del clúster.

      sudo crm status
      
    3. También verás que node-2 está desactivado en Compute Engine.

      Ir a Compute Engine

  2. Reinicia la valla el node-2:

    1. Vuelve a node-1 y reinicia la instancia ejecutando el siguiente comando.

      fence_gce -o on -n node-2 --zone=REGION-b
      
    2. Comprueba el estado del clúster en Pacemaker y Compute Engine. Al cabo de poco tiempo, verás que node-2 vuelve a estar online.

      sudo crm status
      

Configurar Corosync para el reinicio retrasado

Para evitar problemas de tiempo y asegurar que se realiza el orden de operaciones adecuado en caso de que se aplique una medida de aislamiento, recomendamos retrasar el reinicio del servicio Corosync durante 60 segundos.

Para obtener más información, consulta el artículo de la base de conocimientos de Red Hat.

  1. Crea un archivo drop-in de systemd que establezca un retraso en el inicio del servicio Corosync en node-1, node-2 y node-3:

    1. Abre corosync.service para editarlo.

      sudo systemctl edit corosync.service
      

    2. Añade las siguientes líneas, guarda el archivo y cierra el editor.

      [Service]
      ExecStartPre=/bin/sleep 60
      
    3. Vuelve a cargar el gestor de servicios y comprueba si se ha tenido en cuenta la configuración.

      sudo systemctl daemon-reload
      systemctl status corosync.service --no-pager
      
      

      Si ves la sección Drop-in, significa que los ajustes del archivo drop-in se han tenido en cuenta correctamente.

Prueba de conmutación por error

Ahora puedes probar si la conmutación por error funciona correctamente.

  1. Conéctate a la VM de Windows en node-4 mediante Escritorio Remoto:
  2. Abre una sesión de PowerShell:
  3. Ejecuta la siguiente secuencia de comandos:

    while ($True){
      $Conn = New-Object System.Data.SqlClient.SqlConnection
      $Conn.ConnectionString = "Server=CLUSTER_ADDRESS;User ID=sa;Password=SA_PASSWORD;Initial Catalog=master"
      $Conn.Open()
    
      $Cmd = New-Object System.Data.SqlClient.SqlCommand
      $Cmd.Connection = $Conn
      $Cmd.CommandText = "SELECT @@SERVERNAME"
    
      $Adapter = New-Object System.Data.SqlClient.SqlDataAdapter $Cmd
      $Data = New-Object System.Data.DataSet
      $Adapter.Fill($Data) | Out-Null
      $Data.Tables[0] + (Get-Date -Format "MM/dd/yyyy HH:mm:ss")
    
      Start-Sleep -Seconds 2
    }
    

    Sustituye CLUSTER_ADDRESS por la dirección IP del receptor y SA_PASSWORD por la contraseña de la cuenta SA en SQL Server.

    Cada 2 segundos, la secuencia de comandos se conecta a SQL Server mediante el agente de escucha del grupo de disponibilidad o el agente de escucha de DNN y consulta el nombre del servidor.

    Deja que el script se ejecute.

  4. Vuelve a SSH en node-1 y ejecuta los comandos para activar una conmutación por error a node-2:

    sudo pcs resource move ms-ag1 node-2 --master
    sudo pcs resource move aoag1-group  node-2
    sudo pcs resource move aoag1-vip node-2
    
  5. Vuelve a la sesión de PowerShell en node-4:

    1. Observa el resultado de la secuencia de comandos en ejecución y verás que el nombre del servidor cambia de node-1 a node-2 como resultado de la conmutación por error.
  6. Vuelve a node-1 e inicia una conmutación por error a node-1:

    sudo pcs resource move ms-ag1 node-1 --master
    sudo pcs resource move aoag1-group  node-1
    sudo pcs resource move aoag1-vip node-1
    
  7. Vuelve a PowerShell en node-4 y detén la secuencia de comandos pulsando Ctrl+C.