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


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

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

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

目标

费用

本教程使用 Google Cloud的收费组件,包括:

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

准备工作

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

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

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. 确保已为您的 Google Cloud 项目启用 NetApp Cloud Volumes API
  4. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

准备项目和网络

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

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

    前往 Google Cloud 控制台

  2. 设置默认项目 ID

    gcloud config set project PROJECT_ID
    

    PROJECT_ID 替换为您的 Google 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/ZONE/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/ZONE/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/ZONE/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. 依次点击 File(文件)> Open(打开),然后打开 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. 点击 Start 按钮,然后在搜索栏中输入 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. 连接到节点 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 替换为您的 Google Cloud 项目的 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. 在 root 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. 针对每个 SQL Server 实例在 node-2node-3 上运行以下 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 Cluster Engine 搭配使用。在本部分中,您将在每个虚拟机上安装和配置 Pacemaker。

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

在本部分,您将为 Pacemaker 创建一个新的 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 密钥文件夹中:

    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

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

  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
    

    选择一个空闲且位于 49152-65535 的专用范围内的端口,并将 HEALTH_CHECK_PORT 替换为该端口的值。例如,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 是一种围栏策略,用于维护 HA 集群中节点的完整性。STONITH 服务在节点级运行,可保护集群免受无响应或处于未知状态的节点的影响。我们建议使用专门针对 Google Cloud上的 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 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.