在 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. 确保您的 Google Cloud 项目已启用结算功能

  3. 确保已为您的 Google Cloud 项目启用 NetApp Cloud Volumes API
  4. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 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. 选择 Developer 版本作为 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. 连接到节点 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 gsutil cp /var/opt/mssql/data/my_ag_certificate.cer gs://BUCKET_NAME/
      sudo gsutil 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 gsutil cp gs://BUCKET_NAME/my_ag_certificate.cer /var/opt/mssql/data/
      sudo gsutil 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 引擎搭配使用。在本部分中,您将在每个虚拟机上安装和配置 Pacemaker。

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

在本部分中,您将为 Pacemaker 创建新的 SQL Server 账号,用于登录每个 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 Secrets 文件夹中:

    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 gsutil cp /etc/corosync/authkey gs://BUCKET_NAME/
    sudo gsutil cp  /etc/corosync/corosync.conf gs://BUCKET_NAME/
    

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

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

    sudo gsutil cp gs://BUCKET_NAME/authkey /etc/corosync/
    sudo gsutil 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. 运行 Cluster Resource Manager。

      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 服务在节点级层运行,保护集群免受无响应或未知状态的节点的影响。我们建议使用专门针对 Google Cloud 上的 Compute Engine 设计的 fence_gce 防护设备。

设置围栏设备

  1. 检查 fence_gce - Compute Engine 围栏代理是否已安装到 node1 上:

    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. 您可以通过运行 status 命令来测试防护代理的状态:

    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. 您还会看到 node-2 在 Compute Engine 中处于关闭状态。

      转到 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 普适性文件,用于设置 Corosync 服务在 node-1node-2node-3 上启动的延迟时间:

    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
      
      

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

测试故障切换

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

  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. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。