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 se vuelve inaccesible. 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.

Objetivos

Costes

En este tutorial se usan componentes facturables de Google Cloud, como los siguientes:

Usa la calculadora de precios para generar una estimación de costes basada en el uso previsto.

Antes de empezar

Para seguir este tutorial, necesitas un Google Cloud proyecto. Puedes crear uno o seleccionar un proyecto que ya hayas creado:

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    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 ordenador 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 de tu 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 ella 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úster 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, instale Pacemaker y configure 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 habías configurado 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ás una dirección IP virtual y un recurso de comprobación de estado en el clúster mediante un balanceador de carga TCP interno de pases 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 de 49152 a 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 gestionadas 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 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.

    Limpieza

    Cuando hayas terminado el tutorial, puedes eliminar los recursos que has creado para que dejen de usar cuota y generar cargos. En las siguientes secciones se explica cómo eliminar o desactivar dichos recursos.

    Eliminar el proyecto

    La forma más fácil de evitar que te cobren es eliminar el proyecto que has creado para el tutorial.

    Para ello, sigue las instrucciones que aparecen a continuación:

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.