在 Linux 上配置使用多写入者磁盘的 SQL Server 故障切换集群实例

如需在 Compute Engine 的两个不同可用区中实现 SQL Server 的高可用性,您可以部署使用多写入者磁盘的 Linux 版 SQL Server 故障切换集群实例 (FCI)。与传统的无共享架构不同,此配置允许您同时将不同可用区中的节点连接到同一磁盘。本指南介绍了如何使用 Google Cloud Hyperdisk 的低延迟同步复制功能,在 Compute Engine 中的 Linux 上部署高可用性 SQL Server FCI。

这种设计可确保即使在不太可能发生的可用区中断情况下,SQL Server 仍保持可用。将用于集群编排的 Pacemaker 与 Compute Engine 的跨可用区弹性相结合,可为需要共享存储简单性的任务关键型数据库工作负载提供稳健的高性能解决方案。

使用多写入者磁盘实现高可用性的优势

在 Linux 上使用具有多写入者磁盘的 SQL Server FCI 而不是 Always On 可用性组 (AG),可消除管理多个数据副本的复杂性以及 AG 配置产生的同步开销。

与在每个节点上使用完整数据副本的 AG 架构相比,共享卷架构在存储方面也更高效。在镜像场景中,共享卷还可以降低磁盘费用。

此架构的主要亮点

  • 可用区级冗余:在极少数发生节点故障或可用区中断时提供数据保护。
  • 简化管理:与 Always On 可用性组相比,可降低管理多个数据副本的复杂性。
  • 存储效率:利用单个共享卷存储数据和日志,并使用多写入器功能进行优化。
  • Linux 原生编排:使用行业标准高可用性扩展 (HAE) 实现无缝故障切换。

在本地环境中,如果发生故障切换,您可以让 WSFC 执行 ARP 通知,以通知网络设备某个 IP 地址发生了变化。但是,Google Cloud会忽略 ARP 通知。因此,您必须实现内部负载均衡器(请参阅运行 Windows Server 故障切换集群

架构

本文假定您已掌握 SQL Server、Active Directory 和 Compute Engine 的基本知识。

目标

本教程介绍如何完成以下任务来实现目标:

  • 在 Linux 上创建 SQL Server 部署。
  • 创建、挂接和配置多写入者磁盘。
  • 配置 Pacemaker 集群。
  • 设置负载均衡器。
  • 执行故障切换测试。

费用

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

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

准备工作

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

    1. 在 Google Cloud 控制台的项目选择器页面上,选择或创建 Google Cloud 项目。

      选择或创建项目所需的角色

      • 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
      • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予角色

      转到“项目选择器”

    2. 验证是否已为您的 Google Cloud 项目启用结算功能

    3. 在 Google Cloud 控制台中,激活 Cloud Shell。

      激活 Cloud Shell

准备项目和网络

如需准备 Google Cloud 项目和 VPC 以部署 SQL Server FCI,请执行以下操作:

  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。

创建集群节点

部署两个虚拟机作为集群节点,并部署第三个虚拟机作为专用客户端,以验证连接性和故障切换性能。

  1. 初始化以下变量,这些变量将用于剩余的命令。

    BOOT_DISK_SIZE=50
    BOOT_IOPS=10000
    BOOT_THROUGHPUT=400
    DATA_IOPS=10000
    DATA_THROUGHPUT=400
    DATA_DISK_SIZE=200
    REGION=$(gcloud config get-value compute/region)
    ZONE1=$REGION-a
    ZONE2=$REGION-b
    SUBNET=SUBNET_NAME
    MACHINE_TYPE=c3-standard-8
    VPC_NAME=VPC_NAME
    
  2. 创建两个区域级磁盘,一个用于数据,另一个用于日志。如需允许两个实例访问磁盘,请使用 --access-mode=READ_WRITE_MANY 标志为两个磁盘启用多写入者模式。

    gcloud compute disks create sqlfci-mw-data-disk \
    --size=$DATA_DISK_SIZE \
    --type=hyperdisk-balanced-high-availability \
    --region=$REGION \
    --replica-zones=$ZONE1,$ZONE2 \
    --provisioned-iops=$DATA_IOPS \
    --provisioned-throughput=$DATA_THROUGHPUT \
    --access-mode=READ_WRITE_MANY
    
    gcloud compute disks create sqlfci-mw-log-disk \
    --size=$DATA_DISK_SIZE \
    --type=hyperdisk-balanced-high-availability \
    --region=$REGION \
    --replica-zones=$ZONE1,$ZONE2 \
    --provisioned-iops=$DATA_IOPS \
    --provisioned-throughput=$DATA_THROUGHPUT \
    --access-mode=READ_WRITE_MANY
    
  3. 创建 Linux 虚拟机,并挂接您创建的多写入者磁盘。

    gcloud compute instances create node-1 \
    --boot-disk-size=$BOOT_DISK_SIZE \
    --boot-disk-type=hyperdisk-balanced \
    --boot-disk-provisioned-iops=$BOOT_IOPS \
    --boot-disk-provisioned-throughput=$BOOT_THROUGHPUT \
    --zone $ZONE1 \
    --machine-type $MACHINE_TYPE \
    --subnet $SUBNET \
    --image-family ubuntu-2204-lts \
    --image-project ubuntu-os-cloud \
    --disk="name=sqlfci-mw-data-disk,scope=regional,mode=rw" \
    --disk="name=sqlfci-mw-log-disk,scope=regional,mode=rw" \
    --scopes=compute-rw,trace,service-control,service-management,pubsub,monitoring-write,logging-write,storage-rw \
    --tags=sqlfci
    
    gcloud compute instances create node-2 \
    --boot-disk-size=$BOOT_DISK_SIZE \
    --boot-disk-type=hyperdisk-balanced \
    --boot-disk-provisioned-iops=$BOOT_IOPS \
    --boot-disk-provisioned-throughput=$BOOT_THROUGHPUT \
    --zone $ZONE2 \
    --machine-type $MACHINE_TYPE \
    --subnet $SUBNET \
    --image-family ubuntu-2204-lts \
    --image-project ubuntu-os-cloud \
    --disk="name=sqlfci-mw-data-disk,scope=regional,mode=rw" \
    --disk="name=sqlfci-mw-log-disk,scope=regional,mode=rw" \
    --scopes=compute-rw,trace,service-control,service-management,pubsub,monitoring-write,logging-write,storage-rw \
    --tags=sqlfci
    
  4. 创建将用于测试连接的 Windows 客户端虚拟机 cl-node

    gcloud compute instances create cl-node \
    --boot-disk-size=100 \
    --boot-disk-type=hyperdisk-balanced \
    --machine-type $MACHINE_TYPE \
    --image-family windows-2025 \
    --image-project windows-cloud \
    --zone $ZONE1 \
    --subnet $SUBNET \
    --scopes=compute-rw,trace,service-control,service-management,pubsub,monitoring-write,logging-write,storage-rw
    

创建内部负载均衡器

  1. 为集群和负载均衡器预留 IP 地址。

    gcloud compute addresses create sqlfci-lb-ipaddress \
    --region=$REGION \
    --subnet=$SUBNET \
    --purpose="SHARED_LOADBALANCER_VIP"
    CLUSTER_ADDRESS=$(gcloud compute addresses describe sqlfci-lb-ipaddress \
    --region $REGION \
    --format=value\(address\)) && \
    echo "Cluster IP address: $CLUSTER_ADDRESS"
    
  2. 为集群创建健康检查。

    gcloud compute health-checks create tcp sqlfci-healthcheck \
    --port="60008" \
    --region=$REGION \
    --check-interval=3 \
    --timeout=2 \
    --unhealthy-threshold=2 \
    --healthy-threshold=5
    
  3. 如需允许连接到健康检查端口,请创建防火墙规则。

    gcloud compute firewall-rules create "allow-sqlfci-healthcheck-60008" \
    --allow "tcp:60008" \
    --target-tags sqlfci \
    --network $VPC_NAME \
    --source-ranges="35.191.0.0/16,130.211.0.0/22" \
    --priority="1000"
    

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

  4. 为集群节点创建实例组。

    gcloud compute instance-groups unmanaged create sqlfci-1-uig \
    --zone=$ZONE1
    gcloud compute instance-groups unmanaged add-instances sqlfci-1-uig \
    --zone=$ZONE1 \
    --instances=node-1
    
    gcloud compute instance-groups unmanaged create sqlfci-2-uig \
    --zone=$ZONE2
    gcloud compute instance-groups unmanaged add-instances sqlfci-2-uig \
    --zone=$ZONE2 \
    --instances=node-2
    
  5. 创建负载均衡器后端服务。

    gcloud compute backend-services create sqlfci-backend-services \
    --region=$REGION \
    --load-balancing-scheme="INTERNAL" \
    --protocol="TCP" \
    --health-checks=sqlfci-healthcheck \
    --health-checks-region=$REGION
    
    gcloud compute backend-services add-backend sqlfci-backend-services \
    --region=$REGION \
    --instance-group=sqlfci-1-uig \
    --instance-group-zone=$ZONE1
    
    gcloud compute backend-services add-backend sqlfci-backend-services \
    --region=$REGION \
    --instance-group=sqlfci-2-uig \
    --instance-group-zone=$ZONE2
    
  6. 创建负载均衡器转发规则。

    gcloud compute forwarding-rules create "sqlfci-forwarding-rule" \
    --load-balancing-scheme=INTERNAL \
    --network=$VPC_NAME \
    --subnet=$SUBNET \
    --region=$REGION \
    --address=$CLUSTER_ADDRESS \
    --ip-protocol="TCP" \
    --ports="ALL" \
    --backend-service=sqlfci-backend-services \
    --backend-service-region=$REGION
    
  7. 创建 Cloud Storage 存储桶,以便将文件从主集群节点转移到辅助集群节点。

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

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

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

安装必要的软件

在将参与故障切换集群的两个 Linux 虚拟机(node-1node-2)上下载、安装和配置 SQL Server 引擎和集群管理。

  1. 使用 SSH 连接到每个虚拟机。如需了解详情,请参阅连接到 Linux 虚拟机控制 SSH 网络访问的最佳实践

  2. 更新了 node-1node-2 中的 hosts file

    1. 打开 hosts file 进行修改。

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

      转到 Compute Engine

      NODE1_INTERNAL_IP node-1
      NODE2_INTERNAL_IP node-2
      

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

  3. 检查虚拟机之间的通信。参与 Always On 可用性组的所有虚拟机都必须能够与其他虚拟机通信:返回到每个 Linux 虚拟机,从每个虚拟机运行命令,并验证所有虚拟机是否都可以相互通信。

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

    输出的结果应类似于以下内容:

    PING node-1 (10.128.0.37) 56(84) bytes of data.
    64 bytes from node-1 (10.128.0.37): icmp_seq=1 ttl=128 time=1.91 ms
    64 bytes from node-1 (10.128.0.37): icmp_seq=2 ttl=128 time=0.234 ms
    64 bytes from node-1 (10.128.0.37): icmp_seq=3 ttl=128 time=0.249 ms
    64 bytes from node-1 (10.128.0.37): icmp_seq=4 ttl=128 time=0.263 ms
    
  4. 安装 SQL Server 2025。

    1. 将 SQL Server 代码库添加到系统。

      curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
      curl -fsSL https://packages.microsoft.com/config/ubuntu/22.04/mssql-server-2025.list | sudo tee /etc/apt/sources.list.d/mssql-server-2025.list
      sudo apt-get update
      
    2. 安装 SQL Server。

      sudo apt-get install -y mssql-server
      
    3. 安装 SQL Server 开发者工具。 在将参与故障切换集群的两个 Linux 虚拟机上下载并安装 SQL Server 工具。

      curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
      sudo apt-get update
      
      sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18 unixodbc-dev
      
  5. 安装 Pacemaker。 Pacemaker 是一款开源高可用性资源管理器软件,可与 Corosync 集群引擎搭配使用。在本部分中,您将在两个集群虚拟机上安装 Pacemaker。

    1. node-1node-2 上安装 Pacemaker。

      sudo apt-get install -y pacemaker pcs fence-agents resource-agents pacemaker-cli-utils crmsh
      
    2. 为 Pacemaker 安装 SQL Server 资源代理。

      sudo apt-get install -y mssql-server-ha
      
  6. 如果您在虚拟机上启用了防火墙,请为 SQL Server 打开防火墙。

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

      sudo ufw status
      
    2. 如果状态为活跃,请运行以下命令以打开端口。 如果防火墙服务未运行,您可以忽略此步骤。

      sudo ufw allow 1433
      sudo ufw allow 5022
      sudo ufw reload
      

配置主数据库节点

在本部分中,您将初始化两个多写入者磁盘,并为每个磁盘设置卷组和逻辑组。

配置 LVM。

配置 LVM 设置。

  1. 备份现有配置。

    sudo cp /etc/lvm/lvm.conf /etc/lvm/lvm.conf.bak
    
  2. 更新系统 ID 源:

    sudo sed -i 's/^\(\s*system_id_source\s*=\s*\)"none"/\1"uname"/' /etc/lvm/lvm.conf
    
  3. 验证更改是否已成功完成。

    grep 'system_id_source *= *"uname"' /etc/lvm/lvm.conf
    
  4. 配置 LVM 卷组和逻辑卷。

    sudo pvcreate /dev/nvme0n2 /dev/nvme0n3
    sudo pvs
    sudo vgcreate vgdata /dev/nvme0n2
    sudo lvcreate -l 100%FREE -n lvdata vgdata
    sudo vgcreate vglogtmp /dev/nvme0n3
    sudo lvcreate -l 70%FREE  -n lvlog vglogtmp
    sudo lvcreate -l 100%FREE -n lvtmp vglogtmp
    sudo vgs -o+systemid
    
  5. 使用 64KB 块大小的 xfs 文件系统格式化卷。

    sudo mkfs.xfs -d su=64k,sw=1 -L data /dev/vgdata/lvdata -f
    sudo mkfs.xfs -d su=64k,sw=1 -L dblog /dev/vglogtmp/lvlog -f
    sudo mkfs.xfs -d su=64k,sw=1 -L tmp /dev/vglogtmp/lvtmp -f
    
  6. 验证卷是否已创建。

    sudo lvs
    

装载并格式化磁盘

为共享磁盘设置挂载点,并向 mssql 用户授予访问权限。

  1. 为新卷创建装载点。

    sudo mkdir /mssql
    sudo mkdir -p /mssql/db_data
    sudo mkdir -p /mssql/db_log
    sudo mkdir -p /mssql/db_temp
    
  2. 将 LVM 卷装载到装载点。

    sudo mount /dev/vgdata/lvdata /mssql/db_data
    sudo mount /dev/vglogtmp/lvlog /mssql/db_log
    sudo mount /dev/vglogtmp/lvtmp /mssql/db_temp
    
  3. mssql 用户设置为装载点的所有者。

    sudo chown mssql:mssql /mssql/db_data
    sudo chown mssql:mssql /mssql/db_log
    sudo chown mssql:mssql /mssql/db_temp
    
  4. 配置 SQL Server:

    1. 设置将主数据库迁移到共享存储空间的变量,然后运行 mssql-conf 工具。

      sudo MSSQL_MASTER_DATA_FILE="/mssql/db_data/master.mdf" MSSQL_MASTER_LOG_FILE="/mssql/db_data/mastlog.ldf" /opt/mssql/bin/mssql-conf setup
      
    2. 为 SQL Server 版本选择开发者版本,然后接受许可协议。

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

    3. 为 SA 账号指定密码。

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

      systemctl status mssql-server --no-pager
      

配置 SQL Server 和 Pacemaker

  1. 为 Pacemaker 创建 SQL Server 用户。 将 SA_PASSWORD 替换为 SQL Server 上 SA 账号的密码,并将 PA_PASSWORD 替换为将用于 pacemaker 账号的密码。

    QUERY="
    CREATE LOGIN [pacemaker] with PASSWORD= N'PA_PASSWORD';
    ALTER SERVER ROLE [sysadmin] ADD MEMBER [pacemaker];
    GO"
    
    /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
    
  2. 将 Pacemaker 登录名和密码添加到 SQL Server Secret 文件夹。

    {
      echo 'pacemaker'
      echo PA_PASSWORD'
    } | sudo tee /var/opt/mssql/secrets/passwd > /dev/null
    sudo chown root:root /var/opt/mssql/secrets/passwd
    sudo chmod 400 /var/opt/mssql/secrets/passwd
    
  3. 更新 SQL Server 配置以使用新的数据、日志和临时位置。您还将设置 SQL Server 建议的设置。

    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /mssql/db_data
    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /mssql/db_log
    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultdumpdir /mssql/db_log
    sudo /opt/mssql/bin/mssql-conf traceflag 9944 3979 on
    sudo /opt/mssql/bin/mssql-conf set control.alternatewritethrough 0
    sudo /opt/mssql/bin/mssql-conf set control.writethrough 1
    

将 TempDB 移至共享磁盘

  1. 获取 TempDB 文件列表,并使用这些文件创建 Alter 查询。此查询将在下一步中用于设置 TempDB 文件的新位置。

    QUERY="
    SET NOCOUNT ON;
    SELECT 'ALTER DATABASE tempdb MODIFY FILE (NAME = [' + f.name + '],' + ' FILENAME = ''/mssql/db_temp/' + f.name + CASE WHEN f.type = 1 THEN '.ldf' ELSE '.mdf' END + ''');' FROM sys.master_files f WHERE f.database_id = DB_ID(N'tempdb');"
    
    /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
    
  2. 捕获上一个命令的输出。 您将使用此输出结果来构成要执行的下一个命令。

    QUERY="QUERY_OUTPUT"
    

    使用输出的查询示例:

    QUERY="
    ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev], FILENAME = '/mssql/db_temp/tempdev.mdf');
    ALTER DATABASE tempdb MODIFY FILE (NAME = [templog], FILENAME = '/mssql/db_temp/templog.ldf');
    ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev2], FILENAME = '/mssql/db_temp/tempdev2.mdf');
    ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev3], FILENAME = '/mssql/db_temp/tempdev3.mdf');"
    

  3. 执行生成的 SQL 命令以移动 TempDB 文件。

    /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
    
  4. 重启 SQL Server 服务以使更改生效。

    sudo systemctl restart mssql-server.service
    
  5. 验证 TempDB 文件是否已创建。

    ls -l /mssql/db_temp/
    
  6. 验证 SQL Server 服务是否正在运行。

    systemctl status mssql-server --no-pager
    

配置 HAProxy

  1. hacluster 设置新密码。

    sudo passwd hacluster
    
  2. 如需完成设置并测试网络负载均衡器是否设置正确,请在两个集群节点上安装并配置 HAProxy tcp listener

    1. 安装 HAProxy。

      sudo apt-get install haproxy
      
    2. 输入 Y 以完成安装。

    3. 修改 haproxy.cfg 文件。

      sudo vi /etc/haproxy/haproxy.cfg
      
    4. haproxy.cfg filedefaults 部分中,将模式更改为 tcp

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

      #---------------------------------------------------------------
      # Set up health check listener for SQL Server Availability Group
      #---------------------------------------------------------------
      listen healthcheck
      bind *:60008
      
  3. 启动 HAProxy 服务。

    sudo systemctl start haproxy.service
    sudo systemctl status haproxy.service
    
  4. 停止并停用 HAProxy 服务。

    sudo systemctl stop haproxy.service
    sudo systemctl disable haproxy.service
    
  5. 使用以下命令将机器密钥文件上传到 Cloud Storage。

    sudo gcloud storage cp /var/opt/mssql/secrets/machine-key gs://BUCKET_NAME/
    

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

  6. 停止并停用 SQL Server 服务。从这一刻起,服务将由集群控制。

    sudo systemctl stop mssql-server.service
    sudo systemctl disable mssql-server.service
    
  7. 卸载共享存储空间。

    sudo umount /mssql/db_data
    sudo umount /mssql/db_log
    sudo umount /mssql/db_temp
    
  8. 清理现有的默认集群配置。

    sudo pcs cluster destroy
    

配置辅助节点

  1. 为 LVM 卷创建装载点。您无需格式化磁盘,因为此磁盘已与 node-1 共享。您在配置 node-1 时已格式化磁盘并配置了 LVM 卷。

    sudo mkdir /mssql
    sudo mkdir -p /mssql/db_data
    sudo mkdir -p /mssql/db_log
    sudo mkdir -p /mssql/db_temp
    
    sudo chown mssql:mssql /mssql/db_data
    sudo chown mssql:mssql /mssql/db_log
    sudo chown mssql:mssql /mssql/db_temp
    
  2. 配置 SQL Server。

    1. 如需将主数据库迁移到共享数据磁盘,请设置以下变量,然后运行 mssql-conf 工具以应用更改。

      sudo MSSQL_MASTER_DATA_FILE="/mssql/db_data/master.mdf" MSSQL_MASTER_LOG_FILE="/mssql/db_data/mastlog.ldf" /opt/mssql/bin/mssql-conf setup
      
    2. 为 SQL Server 版本选择开发者版本,然后接受许可协议。

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

    3. 为 SA 账号指定密码。

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

      systemctl status mssql-server --no-pager
      
  3. 为 Pacemaker 集群创建 SQL Server 用户。 将 SA_PASSWORD 替换为 SQL Server 上 SA 账号的密码,并将 PA_PASSWORD 替换为将用于 pacemaker 账号的密码。

    QUERY="
    CREATE LOGIN [pacemaker] with PASSWORD= N'PA_PASSWORD';
    ALTER SERVER ROLE [sysadmin] ADD MEMBER [pacemaker];
    GO"
    
    /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
    
  4. 将 Pacemaker 登录名和密码添加到 SQL Server Secret 文件夹。

    {
      echo 'pacemaker'
      echo 'PA_PASSWORD'
    } | sudo tee /var/opt/mssql/secrets/passwd > /dev/null
    sudo chown root:root /var/opt/mssql/secrets/passwd
    sudo chmod 400 /var/opt/mssql/secrets/passwd
    
  5. 更新 SQL Server 配置以使用新的数据、日志和临时位置。您还将设置 SQL Server 建议的设置。

    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /mssql/db_data
    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /mssql/db_log
    sudo /opt/mssql/bin/mssql-conf set filelocation.defaultdumpdir /mssql/db_log
    sudo /opt/mssql/bin/mssql-conf traceflag 9944 3979 on
    sudo /opt/mssql/bin/mssql-conf set control.alternatewritethrough 0
    sudo /opt/mssql/bin/mssql-conf set control.writethrough 1
    
  6. 将 TempDB 移至共享数据磁盘。

    1. 获取 TempDB 文件列表,并使用这些文件创建 Alter 查询。

      QUERY="
      SET NOCOUNT ON;
      SELECT 'ALTER DATABASE tempdb MODIFY FILE (NAME = [' + f.name + '],' + ' FILENAME = ''/mssql/db_temp/' + f.name + CASE WHEN f.type = 1 THEN '.ldf' ELSE '.mdf' END + ''');' FROM sys.master_files f WHERE f.database_id = DB_ID(N'tempdb');"
      
      /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
      
    2. 捕获上一个命令的输出。您将使用此输出结果来构成要执行的下一个命令。

      QUERY="QUERY_OUTPUT"
      

      使用输出的查询示例:

      QUERY="
      ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev], FILENAME = '/mssql/db_temp/tempdev.mdf');
      ALTER DATABASE tempdb MODIFY FILE (NAME = [templog], FILENAME = '/mssql/db_temp/templog.ldf');
      ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev2], FILENAME = '/mssql/db_temp/tempdev2.mdf');
      ALTER DATABASE tempdb MODIFY FILE (NAME = [tempdev3], FILENAME = '/mssql/db_temp/tempdev3.mdf');"
      
    3. 如需移动 TempDB 文件,请执行生成的 SQL 命令。

      /opt/mssql-tools18/bin/sqlcmd -No -S localhost -U sa -P 'SA_PASSWORD' -Q "$QUERY"
      
    4. 如需使更改生效,请重启 SQL Server 服务。

      sudo systemctl restart mssql-server.service
      
    5. 验证 SQL Server 服务是否正在运行。

      sudo systemctl status mssql-server --no-pager
      
    6. 验证是否已创建 TempDB 文件。

      ls -l /mssql/db_temp/
      
  7. 停止并暂时停用 SQL Server 服务。

    sudo systemctl stop mssql-server.service
    sudo systemctl disable mssql-server.service
    
  8. 为确保两个节点都使用相同的 SQL Server 密钥,请从 node-1 下载计算机密钥文件。

    sudo rm /var/opt/mssql/secrets/machine-key
    sudo gcloud storage cp gs://BUCKET_NAME/machine-key /var/opt/mssql/secrets/machine-key
    sudo chown mssql:mssql /var/opt/mssql/secrets/machine-key
    sudo chmod 0600  /var/opt/mssql/secrets/machine-key
    
  9. 配置 LVM 设置。

    1. 备份现有配置。

      sudo cp /etc/lvm/lvm.conf /etc/lvm/lvm.conf.bak
      
    2. 更新系统 ID 源。

      sudo sed -i 's/^\(\s*system_id_source\s*=\s*\)"none"/\1"uname"/' /etc/lvm/lvm.conf
      

      运行以下命令,验证更改:

      cat /etc/lvm/lvm.conf | grep uname
      

      输出的结果应类似于以下内容:

      #     Set the system ID from the hostname (uname) of the system.
      system_id_source = "uname"
      
    3. 验证更改是否已成功完成。

      grep 'system_id_source *= *"uname"' /etc/lvm/lvm.conf
      
  10. hacluster 设置新密码。

    sudo passwd hacluster
    
  11. 如需完成设置并测试网络负载均衡器是否设置正确,请在两个集群节点上安装并配置 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 *:60008
      
    6. 启动 HAProxy 服务。

      sudo systemctl start haproxy.service
      sudo systemctl status haproxy.service
      
  12. 停止并停用 HAProxy 服务。

    sudo systemctl stop haproxy.service
    sudo systemctl disable haproxy.service
    
  13. 清理现有的默认集群配置。

    sudo pcs cluster destroy
    

完成集群配置

返回到 node-1 以继续配置集群。

  1. hacluster 用户身份进行身份验证。

    sudo pcs host auth node-1 node-2 -u hacluster -p "HA_PASSWORD"
    
  2. 创建名为 ubuntu_fci 的集群。

    sudo pcs cluster setup ubuntu_fci node-1 addr="NODE1_INTERNAL_IP" node-2 addr="NODE2_INTERNAL_IP" --start --enable
    
  3. 为双节点集群设置 no-quorum-policy。

    sudo pcs property set no-quorum-policy="ignore"
    
  4. 创建虚拟 IP 地址集群资源。

    sudo pcs resource create pcs-cluster-vip ocf:heartbeat:IPaddr2 ip="CLUSTER_ADDRESS" cidr_netmask=32 nic=ens3 op monitor interval=30s
    

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

  5. 为所有共享卷创建集群资源对象。

    sudo pcs resource create vgdata ocf:heartbeat:LVM-activate vgname=vgdata vg_access_mode=system_id activation_mode=exclusive
    sudo pcs resource create vglogtmp ocf:heartbeat:LVM-activate vgname=vglogtmp vg_access_mode=system_id activation_mode=exclusive
    sudo pcs resource create data_dir ocf:heartbeat:Filesystem device="/dev/mapper/vgdata-lvdata" directory="/mssql/db_data" fstype="xfs"
    sudo pcs resource create log_dir ocf:heartbeat:Filesystem device="/dev/mapper/vglogtmp-lvlog" directory="/mssql/db_log" fstype="xfs"
    sudo pcs resource create tmp_dir ocf:heartbeat:Filesystem device="/dev/mapper/vglogtmp-lvtmp" directory="/mssql/db_temp" fstype="xfs"
    
  6. 创建资源组,并将所有已创建的对象添加到新组中。

    sudo pcs resource group add sql_group pcs-cluster-vip vgdata vglogtmp data_dir log_dir tmp_dir
    
  7. 为 Microsoft SQL Server 服务创建集群资源,并将其添加到现有资源组。

    sudo pcs resource create sql_fci ocf:mssql:fci  op stop timeout=60s --group sql_group
    
  8. 为 HAProxy 创建集群资源,并将其添加到同一组中。

    sudo pcs resource create pcs-healthcheck systemd:haproxy.service op monitor interval=20s timeout=30s --group sql_group
    
  9. 创建用于控制资源启动顺序的集群限制。

    sudo pcs constraint order set  pcs-cluster-vip vgdata vglogtmp data_dir log_dir tmp_dir sql_fci pcs-healthcheck
    

设置 STONITH 防护

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

设置防护设备

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

    sudo pcs stonith list | grep fence_gce
    

    有关详情,请参阅:

  2. 配置集群防护资源。

    sudo pcs stonith create node-1-fence fence_gce \
    plug=node-1 \
    zone=ZONE1 \
    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=ZONE2 \
    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"
    

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

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

    sudo fence_gce -o status -n node-1 --zone=ZONE1
    sudo fence_gce -o status -n node-2 --zone=ZONE2
    

    输出的结果应类似于以下内容:

    Status: ON
    

ZONE1ZONE2 替换为在其中部署 Linux 虚拟机的可用区。

  1. 为防护设备创建位置限制条件,以确保它们仅在预期实例上运行。

    sudo pcs constraint location node-1-fence avoids node-1
    sudo pcs constraint location node-2-fence avoids node-2
    
  2. 在 Pacemaker 集群中启用防护并设置集群防护超时。

    sudo pcs -f stonith_cfg property set stonith-enabled=true
    sudo pcs property set stonith-timeout="300s"
    
  3. 清理集群启动流程。

    sudo pcs resource cleanup
    
  4. 检查集群状态。

    sudo crm status
    

    输出的结果应类似于以下内容:

      Cluster Summary:
        * Stack: corosync
        * Current DC: node-1 (version 2.1.2-ada5c3b36e2) - partition with quorum
        * Last updated: Tue Jun  2 21:36:47 2026
        * Last change:  Mon Apr 27 12:31:58 2026 by root via crm_resource on node-1
        * 2 nodes configured
        * 10 resource instances configured
    
      Node List:
        * Online: [ node-1 node-2 ]
    
      Full List of Resources:
        * Resource Group: sql_group:
          * pcs-cluster-vip   (ocf:heartbeat:IPaddr2):         Started node-2
          * vgdata    (ocf:heartbeat:LVM-activate):    Started node-2
          * vglogtmp  (ocf:heartbeat:LVM-activate):    Started node-2
          * data_dir  (ocf:heartbeat:Filesystem):      Started node-2
          * log_dir   (ocf:heartbeat:Filesystem):      Started node-2
          * tmp_dir   (ocf:heartbeat:Filesystem):      Started node-2
          * sql_fci   (ocf:mssql:fci):                 Started node-2
          * pcs-healthcheck   (systemd:haproxy.service):       Started node-2
        * node-1-fence       (stonith:fence_gce):     Started node-2
        * node2-fence        (stonith:fence_gce):     Started node-1
    

测试防护设备

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

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

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

      fence_gce -o off -n node-2 --zone=ZONE2
      

      输出的结果应类似于以下内容:

      Success: Powered OFF
      
    2. 检查集群状态。

      sudo crm status
      

      输出的结果应类似于以下内容:

        Cluster Summary:
          * Stack: corosync
          * Current DC: node-1 (version 2.1.2-ada5c3b36e2) - partition with quorum
          * Last updated: Tue Jun  2 21:52:00 2026
          * Last change:  Mon Apr 27 12:31:58 2026 by root via crm_resource on node-1
          * 2 nodes configured
          * 10 resource instances configured
    
        Node List:
          * Online: [ node-1 ]
          * OFFLINE: [ node-2 ]
    
        Full List of Resources:
          * Resource Group: sql_group:
            * pcs-cluster-vip   (ocf:heartbeat:IPaddr2): Started node-1
            * vgdata    (ocf:heartbeat:LVM-activate):    Started node-1
            * vglogtmp  (ocf:heartbeat:LVM-activate):    Started node-1
            * data_dir  (ocf:heartbeat:Filesystem):      Started node-1
            * log_dir   (ocf:heartbeat:Filesystem):      Started node-1
            * tmp_dir   (ocf:heartbeat:Filesystem):      Started node-1
            * sql_fci   (ocf:mssql:fci):                 Started node-1
            * pcs-healthcheck   (systemd:haproxy.service):       Started node-1
          * node-1-fence       (stonith:fence_gce):     Stopped
          * node-2-fence        (stonith:fence_gce):     Started node-1
    
    1. 您还会看到,Compute Engine 中的 node-2 已关闭。

      转到 Compute Engine

  2. node-2 上重启防护。

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

      fence_gce -o on -n node-2 --zone=ZONE2
      

      输出的结果应类似于以下内容:

      Success: Powered ON
      
    2. 检查 Pacemaker 和 Compute Engine 中的集群状态。过一段时间后,您会看到 node-2 重新上线。

       $ sudo crm status
      

测试故障切换

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

  1. 为虚拟机实例创建用户名和密码
  2. 使用远程桌面连接到虚拟机,然后使用上一步中创建的用户名和密码登录。
  3. 通过远程桌面连接到 cl-node 上的 Windows 虚拟机。
  4. 打开 PowerShell 会话。
  5. 运行以下脚本连接到服务器。该脚本每五秒使用可用性组监听器连接到 SQL Server 一次,并查询服务器名称。

    while ($True){
      try {
        $Conn = New-Object System.Data.SqlClient.SqlConnection
        $Conn.ConnectionString = "Server=CLUSTER_ADDRESS;User ID=sa;Password=SA_PASSWORD;Initial Catalog=master"
        $Conn.Open()
    
        $Cmd =  $Conn.CreateCommand()
        $Cmd.CommandText = "SELECT SERVERPROPERTY('ComputerNamePhysicalNetBIOS')"
    
        $Result = $Cmd.ExecuteReader()
        if ($Result.Read()) {
          $currentNode = $Result.GetString(0)
          Write-Host "Current Node: $currentNode at $(Get-Date)"
        }
    
        $Conn.Close()
        Start-Sleep -Seconds 5
      }
      catch {
          Write-Host "SQL Connection Failed at $(Get-Date). Retrying..."
          Start-Sleep -Seconds 15 # Wait before retrying
      }
    }
    

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

    输出的结果应类似于以下内容:

      Current Node: node-1 at 06/09/2026 20:24:35
      Current Node: node-1 at 06/09/2026 20:24:40
      Current Node: node-1 at 06/09/2026 20:24:45
      Current Node: node-1 at 06/09/2026 20:24:50
      Current Node: node-1 at 06/09/2026 20:24:55
    

    让该脚本保持运行。

  6. 触发故障切换到 node-2:从 node-1 返回到 SSH 终端,然后运行以下命令。

    sudo pcs resource move sql_group node-2
    
  7. 返回 cl-node 上的 PowerShell 会话。

    1. 观察正在运行的脚本的输出,并注意服务器名称因故障切换从 node-1 更改为 node-2

    输出的结果应类似于以下内容:

      Current Node: node-1 at 06/09/2026 20:28:51
      Current Node: node-1 at 06/09/2026 20:28:56
      SQL Connection Failed at 06/09/2026 20:29:16. Retrying...
      Current Node: node-2 at 06/09/2026 20:29:31
      Current Node: node-2 at 06/09/2026 20:29:36
    
  8. 启动向 node-1 的故障恢复。在节点 1 的命令行中,运行以下命令

    sudo pcs resource move sql_group node-1
    
  9. 返回 cl-node 上的 PowerShell。按 Ctrl+C 停止该脚本。

清理

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

删除项目

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

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

  1. 在 Google Cloud 控制台中,前往管理资源页面。

    转到“管理资源”

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

后续步骤