在 Linux 上使用 Always On 可用性组和 Pacemaker 设置 SQL Server 集群


本教程介绍了如何使用 Always On 可用性组 (AOAG) 和 Pacemaker 在 Linux 上部署 Microsoft SQL Server 数据库系统,以作为高可用性 (HA) 和灾难恢复 (DR) 解决方案。在本文档中,灾难是主数据库发生故障或不可用的事件。

当主数据库所在的区域发生故障或无法访问时,主数据库可能会发生故障。即使区域可用并正常运行,主数据库也可能由于系统错误而发生故障。在这些情况下,灾难恢复是让辅助数据库可供客户端继续进行处理的过程。

本教程面向数据库架构师、管理员和工程师。

目标

费用

本教程使用 Trusted Cloud by S3NS的计费组件,包括:

您可使用价格计算器根据您的预计使用情况来估算费用。

准备工作

在本教程中,您需要一个 Trusted Cloud 项目。您可创建一个新项目,也可选择已创建的项目:

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

    Go to project selector

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

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

    Activate Cloud Shell

    准备项目和网络

    如需准备 Trusted Cloud 项目和 VPC 以部署 SQL Server Always On 可用性组,请执行以下操作:

    1. 在 Trusted Cloud 控制台中,点击激活 Cloud Shell 激活 Cloud Shell。 按钮,以打开 Cloud Shell

      前往 Trusted Cloud 控制台

    2. 设置默认项目 ID

      gcloud config set project PROJECT_ID
      

      PROJECT_ID 替换为您的 Trusted Cloud 项目的 ID。

    3. 设置默认区域:

      gcloud config set compute/region REGION
      

      REGION 替换为要在其中部署的区域的 ID。

    4. 设置默认可用区:

      gcloud config set compute/zone ZONE
      

      ZONE 替换为要在其中部署的可用区的 ID。 它应该是上一步中指定区域内的有效可用区。

    创建 Linux 虚拟机

    为了实现 SQL Server 集群的高可用性和仲裁,请部署三个 Linux 虚拟机 (VM) 来托管 SQL Server 集群。

    1. 初始化以下变量:

      PD_SIZE=30
      MACHINE_TYPE=n2-standard-8
      
    2. 创建 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
      

      SUBNET_NAME 替换为您的 VPC 子网的名称。

    3. 更新 node-1node-2node-3 上的 Hosts 文件:

      1. 使用 SSH 连接到每个虚拟机。如需了解详情,请参阅“连接到 Linux 虚拟机”文档
      2. 打开 hosts 文件进行修改。

        sudo vi /etc/hosts
        
      3. 找到每个 Linux 虚拟机的内部 IP 地址,并将主机条目附加到文件底部。

        转到 Compute Engine

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

        NODE1_INTERNAL_IPNODE2_INTERNAL_IPNODE3_INTERNAL_IP 替换为每个 Linux 虚拟机的内部 IP 地址。

    4. 检查虚拟机之间的通信。参与 Always On 可用性组的所有虚拟机都必须能够与其他虚拟机通信:

      1. 返回到每个 Linux 虚拟机,从每个虚拟机运行命令,并验证所有虚拟机是否都可以相互通信。

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

    安装和配置 SQL Server

    在将参与 Always On 可用性组的三个 Linux 虚拟机上下载、安装和配置 SQL Server 引擎。

    1. 通过 SSH 连接到 node-1node-2node-3,然后运行以下步骤:

      1. 导入代码库公钥。

        wget -qO- https://packages.microsoft.com/keys/microsoft.asc \
        | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
        
      2. 注册 SQL Server Ubuntu 代码库。

        sudo add-apt-repository \
        "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/mssql-server-2019.list)"
        
      3. 更新软件包索引文件并安装 SQL Server。

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

      1. 运行 mssql-conf 工具。

        sudo /opt/mssql/bin/mssql-conf setup
        
      2. 为 SQL Server 版本选择开发者版本,然后接受许可协议。

        开发者版本包含所有企业版功能,但只能用于非生产环境。如需详细了解 SQL Server 版本Microsoft 许可,请参阅相关文档。

      3. 为 SA 账号指定密码。

      4. 验证 mssql-server 服务正在运行。

        systemctl status mssql-server --no-pager
        
    3. 如果您在虚拟机上启用了防火墙,请为 SQL Server 打开防火墙:

      1. 运行以下命令,检查 Uncomplicated Firewall 是否已安装并启用。

        sudo ufw status
        
      2. 如果状态为活跃,请运行以下命令以打开端口。

        sudo ufw allow 1433
        sudo ufw allow 5022
        sudo ufw reload
        

    连接到 SQL Server

    此时,SQL Server 已安装。如需连接到它,请在同一 VPC 中创建 Windows 机器,安装 SQL Server Management Studio (SSMS),以连接到虚拟机上新创建的 SQL Server 实例:

    1. 创建 Windows 虚拟机:

      1. 返回到 Cloud Shell 并运行以下命令。

        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. 使用远程桌面连接到 node-4 上的 Windows 虚拟机:

    3. 更新 node-4 上的 hosts 文件:

      1. 以管理员模式打开记事本。
      2. 依次点击文件 > 打开,然后打开 hosts 文件。

        c:\Windows\System32\drivers\etc\hosts
        
      3. 将主机条目附加到文件底部。

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

        NODE1_INTERNAL_IPNODE2_INTERNAL_IPNODE3_INTERNAL_IP 替换为每个虚拟机的相应内部 IP 地址。

      4. 保存并退出。

    4. 验证与 Linux 虚拟机的连接:

      1. 连接到 node-4 上的 Windows 虚拟机
      2. 点击开始按钮,然后在搜索栏中输入“powershell”。
      3. 点击以打开 Windows PowerShell ISE 应用。
      4. 通过执行以下命令来测试连接。

        ping node-1
        ping node-2
        ping node-3
        
    5. 按照以下步骤安装 Microsoft SQL Server Management Studio (SSMS):

      1. 使用远程桌面连接到 node-4 上的 Windows 虚拟机。

      2. 在 RDP 会话中,最小化所有窗口,然后启动 Windows PowerShell ISE 应用。

      3. 在 PowerShell 提示符中,下载并执行 SSMS 安装程序。

        Start-BitsTransfer `
        -Source "https://aka.ms/ssmsfullsetup" `
        -Destination "$env:Temp\ssms-setup.exe"
        & $env:Temp\ssms-setup.exe
        
      4. 在 SSMS 安装程序中,点击 Install

      5. 接受提示以允许进行更改。

      6. 安装完成后,点击 Restart 来重启远程机器。此操作会关闭此 RDP 会话。

    6. 连接到 node-1 上的 SQL Server 实例:

      1. 使用 RDP 返回 node-4 虚拟机。

      2. 打开 SSMS 并使用以下参数连接到 node-1

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

        如需了解详情,请参阅《使用 SQL Server Management Studio 连接到 SQL Server 实例》文档。

      3. 输入安装期间创建的 SA 账号的密码。

      4. 选择信任服务器证书

      5. 点击连接

    启用 Always On 可用性组

    在 Linux 上,您必须先创建可用性组,然后才能将其添加为由 Pacemaker 管理的资源:

    1. 为参与可用性组的每个 SQL Server 实例启用 Always On 可用性组功能。在 node-1node-2node-3 上运行以下命令:

      sudo /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1
      sudo systemctl restart mssql-server
      
    2. 使用 SSMS 连接到属于可用性组中的主要主机的实例:

      1. 打开新的查询窗口。

      2. 运行以下代码段以创建加密密钥、证书和私钥。

        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'
        );
        

        ENCRYPTION_KEY_PASSWORDPRIVATE_KEY_PASSWORD 替换为加密密钥和私钥的密码。

    转移证书和密钥文件

    在之前的步骤中创建的证书和密钥文件需要移至 SQL Server 的辅助节点。您可以通过多种方法将证书和密钥文件移至 node-2node-3 上的辅助节点。

    如需了解其他转移选项,请参阅将文件转移到 Linux 虚拟机

    使用 Cloud Storage 转移证书和密钥文件

    创建 Cloud Storage 以将文件从主集群节点转移到辅助集群节点。

    1. 创建 Cloud Storage 存储桶,请运行以下命令:

      1. 返回 Cloud Shell,运行以下命令:

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

        BUCKET_NAME 替换为要创建的存储桶的名称。将 PROJECT_ID 替换为您的 Trusted Cloud by S3NS 项目的 ID,并将 REGION 替换为您想要部署存储桶的区域的 ID。

      如需了解详情,请参阅创建存储桶

    2. 返回 node-1node-2node-3 上的 SSH,以初始化 Google Cloud CLI:

      1. 运行以下命令以初始化 Google Cloud CLI。

        gcloud init
        
      2. 选择 option [1] 以使用预安装的服务账号。

      3. 输入项目的名称。

      4. 针对相应问题输入 n,以设置默认区域和可用区。

    3. 返回 node-1 以将文件复制到 Cloud Storage:

      1. 运行以下命令,将新创建的这两个文件上传到您的 Cloud Storage。

        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/
        

        BUCKET_NAME 替换为创建的存储桶的名称。

    4. 返回 node-2node-3,以从 Cloud Storage 复制文件:

      1. 将这两个文件从 Cloud Storage 下载到 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/
        

        BUCKET_NAME 替换为创建的存储桶的名称。

      2. 在根 shell 中运行命令,以更改 node-2node-3 上文件的所有权。

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

    设置数据库镜像端点

    在本部分中,您将使用 SQL Server 集群中每个节点共享的加密密钥和证书创建数据库端点,以确保数据复制安全。

    1. 返回 node-4 上的 Windows 虚拟机,以创建数据库镜像端点:

      1. 使用 SSMS 连接到 node-1node-2node-3 上的 SQL Server 数据库。按照连接到 SQL Server 中的步骤进行操作,使用 node-1node-2node-3 作为服务器名称以及您为 SA 账号设置的相应密码。

      2. 通过复制的文件在辅助虚拟机 node-2node-3 上创建证书。使用您在主节点上创建证书和密钥时提供的密码。

        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'
        );
        

        ENCRYPTION_KEY_PASSWORDPRIVATE_KEY_PASSWORD 替换为加密密钥和私钥的密码。

      3. 返回 SSMS,针对 node-1node-2node-3 运行 T-SQL 命令,以创建数据库镜像端点。

        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;
        

    创建和配置 Always On 可用性组

    接下来,使用 SQL Server Management Studio 创建 SQL Server Always On 可用性组,并使用之前创建的端点进行复制。

    1. 返回 Windows 虚拟机并打开 SSMS:

      1. 连接到 node-1 上的 SQL Server 数据库引擎,然后打开新的查询窗口。
    2. 创建数据库并备份数据库,为复制做好准备:

      USE MASTER;
      
      CREATE DATABASE [bookshelf];
      ALTER DATABASE [bookshelf] SET RECOVERY FULL;
      BACKUP DATABASE [bookshelf]
      TO DISK = N'/var/opt/mssql/data/bookshelf.bak';
      
    3. 创建 Always On 可用性组:

      1. 在 SSMS 中针对 node-1node-2node-3 运行以下 T-SQL 命令。这样可确保启用端点,并确保每个节点上的 SQL Server 已准备好进行数据复制。

        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. node-1 上运行以下 T-SQL 命令以创建 AOAG。

        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. node-2node-3 上对每个 SQL Server 实例运行以下 T-SQL 命令,以加入新的可用性组。

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

      您已创建名为 bookshelf 的新数据库,并将该新数据库添加到在 node-1 上运行的 SQL Server 实例中名为 aoag1 的新可用性组。Node-2node-3 已添加到可用性组,bookshelf 数据库中的数据将跨所有三个节点在 SQL Server 实例之间同步复制。

    安装和配置 Pacemaker

    Pacemaker 是一款开源高可用性资源管理器软件,可与 Corosync 集群引擎搭配使用。在本部分中,您将在每个虚拟机上安装和配置 Pacemaker。

    为 Pacemaker 集群管理器创建 SQL Server 登录

    在本部分中,您将创建一个新的 SQL Server 账号,供 Pacemaker 用于登录每个 SQL Server 实例并管理可用性组。

    1. node-1node-2node-3 上运行以下 T-SQL 命令:

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

      PACEMAKER_LOGIN_PASSWORD 替换为 pacemaker 账号的密码。

    2. 运行 T-SQL 命令,向可用性组授予 Pacemaker 登录权限:

      GRANT ALTER, CONTROL, VIEW DEFINITION ON AVAILABILITY GROUP::[aoag1] TO [pacemaker];
      GRANT VIEW SERVER STATE TO [pacemaker];
      GO
      
    3. 返回 node-1node-2node-3 上的 SSH,以运行命令将 Pacemaker 登录名和密码保存在 SQL Server Secret 文件夹中:

      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
      

      PACEMAKER_LOGIN_PASSWORD 替换为 pacemaker 账号的密码。

    安装 Pacemaker

    接下来,在所有 Linux 虚拟机上安装 Pacemaker 并设置登录账号以进行资源管理。

    1. 为 pacemaker 打开防火墙端口:

      1. node-1node-2node-3 上运行以下命令,检查 Uncomplicated Firewall 是否已安装并启用。

        sudo ufw status
        
      2. 如果已启用 ufw,请在 node-1node-2node-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. node-1node-2node-3 上安装 Pacemaker:

      sudo apt-get install -y pacemaker pacemaker-cli-utils crmsh resource-agents  fence-agents corosync python3-azure pcs
      
    3. node-1node-2node-3 上为 hacluster 用户设置新密码:

      sudo passwd hacluster
      

    设置 Corosync

    现在,您将配置 Corosync 以管理集群成员资格和集群中的消息传递。

    1. node-1 上为 Corosync 创建身份验证密钥:

      sudo corosync-keygen
      
    2. 修改 Corosync 配置文件:

      1. 返回 node-1 并修改 corosync.conf 文件。

        sudo vi /etc/corosync/corosync.conf
        
      2. 更新突出显示的部分。在修改后,文件应如以下示例所示。

        # 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
            }
            # ...
        }
        

        NODE1_INTERNAL_IPNODE2_INTERNAL_IPNODE3_INTERNAL_IP 替换为每个节点的内部 IP 地址。

    使用 Cloud Storage 转移配置文件

    1. 将生成的身份验证密钥和 corosync 配置文件从 node-1 上传到 Cloud Storage 存储桶:

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

      BUCKET_NAME 替换为之前创建的存储桶的名称。

    2. 将 Authkey 和配置文件下载到 node-2node-3

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

      BUCKET_NAME 替换为在其中转移 Corosync 配置文件的存储桶的名称。

    3. 更新 node-2node-3 上文件的权限:

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

    重启并验证集群通信

    1. node-1node-2node-3 上重启 Pacemaker 和 Corosync 服务:

      sudo systemctl restart pacemaker corosync
      
    2. 通过在 node-1 上运行命令来确认集群的状态:

      sudo crm status
      

      您应该会看到所有三个节点均处于在线状态。

    设置集群

    接下来,您将通过为 SQL Server Always On 可用性组创建新资源来设置 Pacemaker 集群。

    1. node-1 上运行以下命令以设置集群属性:

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

      如需了解详情,请参阅集群选项

    2. 通过在 node-1 上运行命令来授权集群中的节点。使用之前为 hacluster 账号设置的密码:

      sudo pcs cluster auth -u hacluster
      

      您应该会看到所有三个节点均已获得授权。

    3. node-1node-2node-3 上安装 SQL Server 资源代理,以便与 Pacemaker 集成:

      sudo apt-get install mssql-server-ha
      
    4. 返回 node-1,并在集群中创建可用性组资源:

      1. 运行集群资源管理器。

        sudo crm
        
      2. 输入 configure 进入配置菜单。

      3. 输入以下配置。

        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. 输入 commit 以提交更改。

      5. 输入 exit 以退出集群资源管理器。

      6. 验证配置:

        sudo crm status
        

        您应该会看到 node-1 已升级为主节点。Node-2node-3 应设置为次要节点。

    设置负载均衡器和可用性组监听器

    在本部分中,您将使用内部直通式 TCP 负载均衡器,在集群中创建虚拟 IP 地址和健康检查资源,将流量路由到可用性组。

    1. 返回 Cloud Shell,并预留一个将用作集群 IP 的静态 IP 地址:

      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"
      

      REGIONSUBNET_NAME 替换为在其中部署 Linux 虚拟机的区域和子网。

    2. 为每个集群节点创建非托管实例组,并将其分配给新创建的实例组。在 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
      

      REGION 替换在其中部署 Linux 虚拟机的区域。

    3. 创建 TCP 健康检查。 负载均衡器使用健康检查来确定哪些后端实例正确响应流量。

      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
      

      选择 HEALTH_CHECK_PORT 并将其替换为空闲且在 49152-65535 专用范围内的端口值。例如,60000。

      如需了解详情,请参阅健康检查概览

    4. 向集群节点添加网络标记。网络标记由防火墙规则用于健康检查:

      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
      

      NETWORK_TAG_NAME 替换为网络标记的名称。

    5. 创建防火墙规则,以允许健康检查根据标记名称访问集群节点:

      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
      

      如需了解详情,请参阅健康检查的防火墙规则

    6. 创建负载均衡器后端服务:

      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. 将这三个非托管式实例组添加到后端服务:

      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. 为您的负载均衡器定义转发规则。转发规则指定负载均衡器用于接受流量的协议和端口:

      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
      

      CLUSTER_ADDRESS 替换为之前预留的 IP 地址。

      如需了解详情,请参阅转发规则

    9. 如需完成设置并测试网络负载均衡器是否设置正确,请在 node-1node-2node-3 上安装并配置 HAProxy tcp listener

      1. 安装 HAProxy。

        sudo apt-get install haproxy
        

      2. 选择 Y 以完成安装。

      3. 修改 haproxy.cfg 文件。

        sudo vi /etc/haproxy/haproxy.cfg
        
      4. haproxy.cfg file 的默认值部分中,将模式更改为 tcp

      5. 将以下部分附加到 haproxy.cfg 文件的末尾

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

        HEALTH_CHECK_PORT 替换为之前选择的健康检查端口。例如,6000。

      6. 启动服务以确认其配置正确无误:

        sudo systemctl start haproxy.service
        sudo systemctl enable haproxy.service
        sudo systemctl restart haproxy.service
        
      7. 前往“负载均衡”页面,点击您的负载均衡器。观察您的三个非托管实例组,它们现在应报告为健康状况良好。

        转到“负载均衡”

        • 或者,您也可以在 Cloud Shell 中运行以下命令,查看后端服务的状态。

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

          REGION 替换在其中部署 Linux 虚拟机的区域。

      8. 三个非托管式实例组均报告健康状况良好后,请继续执行下一步。

        sudo systemctl restart haproxy.service
        
    10. 在 Pacemaker 中创建健康检查资源:

      1. 通过 SSH 连接到 node-1,并在 pacemaker 集群中为 HAProxy 服务创建健康检查资源:

        sudo pcs resource create aoag1-healthcheck \
        service:haproxy \
        op monitor interval=10s timeout=20s
        
      2. 检查健康资源是否已在主节点 node-1 上启动:

        sudo crm status
        
      3. 如果健康检查资源未在主节点上启动,请使用以下命令进行移动:

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

        您将看到,负载均衡器的健康检查仅对 node-1 是健康状况良好的。

        转到“负载均衡”

    11. 在 Pacemaker 集群中创建虚拟 IP 地址资源:

      1. 返回 node-1 上的 SSH,然后找到节点的网络接口名称。下一步操作将会用到该地址。

        ip -c link
        
      2. 创建虚拟 IP 地址资源。

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

        NIC_NAME 替换为上一步中的网络接口名称,并将 CLUSTER_ADDRESS 替换为预留的 IP 地址。

      3. 检查虚拟 IP 地址资源是否已在主要主机上启动。

        sudo crm status
        
      4. 如果虚拟 IP 地址资源未在主节点上启动,请使用以下命令进行移动。

        sudo pcs resource move aoag1-vip node-1
        
      5. 将健康检查和虚拟 IP 地址资源分组在一起。

        sudo pcs resource group add aoag1-group \
        aoag1-healthcheck aoag1-vip
        
      6. 创建一个限制条件,以用于在主组所在的节点上定位新组。

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

    为 SQL Server 可用性组创建监听器

    与具有可用性组的 SQL Server 连接时,应使用可用性组监听器名称,而不是服务器名称。如果发生故障切换,监听器会自动将连接重定向到集群中的新主节点。

    1. 返回 SSMS 并连接到 node-1 数据库。

    2. 请运行以下查询:

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

      CLUSTER_ADDRESS 替换为预留的 IP 地址。

    设置 STONITH 防护

    STONITH 是一种防护策略,用于维护高可用性集群中节点的完整性。STONITH 服务在节点级别运行,可保护集群免受无响应或处于未知状态的节点影响。我们建议使用专用于 Trusted Cloud by S3NS上的 Compute Engine 的 fence_gce 防护设备。

    设置防护设备

    1. 检查 node1 上是否安装了 Compute Engine 的 fence_gce(防护代理):

      sudo pcs stonith list | grep fence_gce
      

      如需了解详情,请参阅以下主题:

    2. node-1 上,为每个参与节点创建 fence_gce 防护类型资源:

      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"
      

      REGION 替换为在其中部署 Linux 虚拟机的区域,并将 PROJECT_ID 替换为您的项目 ID。

    3. 您可以运行状态命令来测试防护代理的状态:

      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. 为防护设备创建位置限制条件,以确保它们仅在预期实例上运行:

      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. 在 Pacemaker 集群中启用防护并设置集群防护超时:

      sudo pcs -f stonith_cfg property set stonith-enabled=true
      sudo pcs property set stonith-timeout="300s"
      
    6. 检查集群状态:

      sudo crm status
      

    测试防护设备

    设置防护设备后,我们建议您按以下步骤对其进行测试。

    1. 停止对 node-2 的防护:

      1. 连接到 node-1 并运行以下命令,以从集群中测试与 node-2 关联的防护设备。

        fence_gce -o off -n node-2 --zone=REGION-b
        
      2. 检查集群状态。

        sudo crm status
        
      3. 您还会看到,Compute Engine 中的 node-2 已关闭。

        转到 Compute Engine

    2. node-2 上重启防护:

      1. 返回 node-1 并再次运行以下命令来重启实例。

        fence_gce -o on -n node-2 --zone=REGION-b
        
      2. 检查 Pacemaker 和 Compute Engine 中的集群状态。过一段时间后,您会看到 node-2 重新上线。

        sudo crm status
        

    配置 Corosync 以实现延迟重启

    为避免出现时间问题,并确保在执行防护操作时按正确的顺序执行操作,我们建议将 Corosync 服务的重启延迟 60 秒。

    如需了解详情,请参阅 Red Hat 知识库文章

    1. 创建一个 systemd 普适性文件,用于在 node-1node-2node-3 上设置 Corosync 服务启动延迟:

      1. 打开 corosync.service 进行修改。

        sudo systemctl edit corosync.service
        

      2. 附加以下代码行,保存文件并退出编辑器。

        [Service]
        ExecStartPre=/bin/sleep 60
        
      3. 重新加载服务管理器,并检查配置是否已纳入考虑范围。

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

        如果您看到“普适性”部分,则表示系统已成功考虑普适性文件中的设置

    测试故障切换

    您现在可以测试故障切换是否按预期工作。

    1. 通过远程桌面连接到 node-4 上的 Windows 虚拟机:
    2. 打开 PowerShell 会话:
    3. 运行以下脚本:

      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
      }
      

      CLUSTER_ADDRESS 替换为监听器 IP 地址,并将 SA_PASSWORD 替换为 SQL Server 上 SA 账号的密码。

      该脚本每两秒使用可用性组监听器或 DNN 监听器连接到 SQL Server 一次,并查询服务器名称。

      让该脚本保持运行。

    4. 返回 node-1 上的 SSH,然后运行命令以触发故障切换到 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. 返回 node-4 上的 PowerShell 会话:

      1. 观察正在运行的脚本的输出,并注意服务器名称因故障切换从 node-1 更改为 node-2
    6. 返回 node-1 并启动向 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. 返回 node-4 上的 Powershell,然后按 Ctrl+C 停止脚本。

    清理

    完成本教程后,您可以清理您创建的资源,让它们停止使用配额,以免产生费用。以下部分介绍如何删除或关闭这些资源。

    删除项目

    为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

    要删除项目,请执行以下操作:

    1. In the Trusted 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.