openEuler HA 存储+业务双节点集群部署

openEuler HA 存储+业务双节点集群部署

 1 需求

  • 支持存储+业务双活模式,存储双活采用DRBD。比如:ha01提供MySQL数据库服务,httpd业务系统服务;ha02提供FreeSWITCH通信服务。如果ha01宕机,则MySQL和httpd服务自动迁移至ha2上。
  • 要求MySQL和FreeSWITCH都基于docker部署。文件系统使用GFS2(openEuler内核原生支持)。
  • 对外提供统一的IP地址访问。

2 方案架构概述

节点 主业务 备业务 共享存储
ha01 MySQL+httpd FreeSWITCH(备) /dev/drbd0 → /data/shared (GFS2)
ha02 FreeSWITCH MySQL+httpd(备) /dev/drbd0 → /data/shared (GFS2)

资源组设计:

  • Group A(MySQL+httpd+VIP):优先运行于ha01,故障时切换到ha02。
  • Group B(FreeSWITCH+VIP):优先运行于ha02,故障时切换到ha01

资源自动链:DRBD->DLM->GFS2->业务资源组。

3 环境准备

IP 主机名 操作系统
10.32.0.90 ha01 openEuler 24.03 (LTS-SP4)
10.32.0.91 ha02 openEuler 24.03 (LTS-SP4)
10.32.0.92 vip ha01组业务虚拟IP
10.32.0.93 vip ha02组业务虚拟IP

两台节点均需执行

3.1 基础配置

# 设置主机名(ha01执行)
hostnamectl set-hostname ha01
# (ha02执行)
hostnamectl set-hostname ha02

# 编辑 /etc/hosts
cat >> /etc/hosts << EOF
10.32.0.90 ha01
10.32.0.91 ha02
EOF

# 关闭防火墙(测试环境)
systemctl stop firewalld
systemctl disable firewalld

# 关闭 SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

 3.2 安装软件包

安装依赖库

dnf install -y corosync pacemaker pcs fence-agents drbd-utils docker haproxy httpd patch make gcc gcc-c++ kernel-devel flex perl automake libtool elfutils-libelf-devel

源码编译drbd

dnf install -y patch make gcc gcc-c++ kernel-devel flex perl \
automake libtool elfutils-libelf-devel

# 下载源码
wget https://pkg.linbit.com/downloads/drbd/9/drbd-9.3.3.tar.gz
tar -xzvf drbd-9.3.3.tar.gz

# 编译并安装
make -j
make install

安装依赖库

dnf install -y e2fsprogs-devel glib2-devel libtool autoconf automake \
    python3-devel uuid-devel libaio-devel readline-devel ncurses-devel \
    zlib-devel libxml2-devel

 3.3 配置集群用户并启动服务

# 设置 hacluster 密码(两节点设为相同,本处密码为操作系统用户密码)
passwd hacluster

# 启动 pcsd 服务
systemctl start pcsd
systemctl enable pcsd

# 启动 Docker
systemctl start docker
systemctl enable docker

3.4 节点认证(仅在ha01上执行)

pcs host auth ha01 ha02 -u hacluster

3.5 创建集群(仅在ha01上执行)

pcs cluster setup hacluster ha01 addr=10.32.0.90 ha02 addr=10.32.0.91 --start
pcs cluster enable --all
pcs property set stonith-enabled=false
pcs property set no-quorum-policy=ignore

4 配置DRBD双主模式

4.1 用LVM将多块硬盘聚合成一个大设备(所有节点)

# 1. 准备物理卷(PV)
pvcreate /dev/sdb /dev/sdc /dev/sdd

# 2. 创建卷组(VG),命名为 vg_drbd
vgcreate vg_drbd /dev/sdb /dev/sdc /dev/sdd

# 3. 创建逻辑卷(LV),命名为 lv_data(假设用全部空间)
lvcreate -l 100%FREE -n lv_data vg_drbd

# 4. 此时设备路径为 /dev/vg_drbd/lv_data,用于 DRBD

4.2 创建DRBD资源文件(所有节点)

编译/etc/drbd.d/r0.res

resource r0 {
    protocol C;
    startup {
        become-primary-on both;
    }
    net {
        allow-two-primaries yes;
        cram-hmac-alg sha1;
        shared-secret "Z8m2qP5tR7xW9nJ3kL1cV6fG4yB8oU0=";
    }
    on ha01 {
        device /dev/drbd0;
        disk /dev/vg_drbd/lv_data;          # ← 替换为 LVM 逻辑卷路径
        address 10.32.0.90:7789;
        meta-disk internal;
    }
    on ha02 {
        device /dev/drbd0;
        disk /dev/vg_drbd/lv_data;          # ← 两台节点路径必须一致
        address 10.32.0.91:7789;
        meta-disk internal;
    }
}

4.3 初始化并启动DRBD(所有节点)

drbdadm create-md r0
drbdadm up r0

 4.4 建立初步同步

在ha01执行:

drbdadm primary --force r0

等待同步完成后(用 drbdadm status r0 查看状态变为 UpToDate/UpToDate),再在 ha02 执行:

drbdadm primary r0

验证双主状态:

drbdadm status r0
# 应显示两个节点均为 Primary 角色

节点ha01:

image

 节点ha02:

image

5 配置GFS2集群文件系统

5.1 安装GFS2工具

两个节点执行

dnf install -y gfs2-utils dlm lvm2-lockd

GFS2 的核心不是文件系统,而是:

GFS2
 |
 DLM (Distributed Lock Manager)
 |
 Corosync
 |
 Pacemaker

所以需要两个节点:

systemctl enable dlm

但不要马上启动。生产环境应该让Pacemaker管理。

5.2 确认DRBD保持不变

即:

image

 以及

image

5.3 创建LVM lock

 两个节点启用

systemctl enable lvmlockd
systemctl start lvmlockd

5.4 创建GFS2

只执行一次(在ha01)

mkfs.gfs2 \
-p lock_dlm \
-j 2 \
-t ha_cluster:gfs2 \
/dev/drbd0

参数:

-p lock_dlm #使用集群锁:DLM
-j 2 #必须为2,因为是2个节点

image

6 启动DLM

 创建资源:

pcs resource create dlm ocf:pacemaker:controld \
op monitor interval=30s

pcs resource update dlm allow_stonith_disabled=true
pcs resource cleanup dlm
pcs resource enable dlm
pcs status

image

 7 手动验证GFS2双节点挂载

不要马上交给Pacemaker。先测试。

两个节点执行:

mkdir -p /data/shared
mount -t gfs2 /dev/drbd0 /data/shared
mount | grep gfs2

image

测试:

ha01:

echo hello > /data/shared/test.txt

ha02:

cat /data/shared/test.txt

返回:

image

说明:DRBD+DLM+GFS2完成。

测试完需要手工卸载,然后完成后续工作

umount /data/shared

 8 GFS2加入Pacemaker

创建资源:

pcs resource create gfs2_data Filesystem \
device="/dev/drbd0" \
directory="/data/shared" \
fstype="gfs2" \
options="noatime"

然后

pcs resource clone gfs2_data

查看状态

pcs status

image

9 配置VIP

 创建虚拟IP

pcs resource create VirtualIP IPaddr2 ip=10.32.0.92 cidr_netmask=23 op monitor interval=30s

10 DRBD加入Pacemaker

下确认两个节点

drbdadm status r0

输出为

role:Primary
peer role:Primary
disk:UpToDate

image

由于这是前面手动维护的DRBD双主。所以这里需要进行调整:

10.1 进入维护模式,防止Pacemaker自动干预:

pcs property set maintenance-mode=true

确认:

pcs status

image

10.2  停止GFS2

pcs resource delete gfs2_data --force

两个节点执行

mount | grep gfs2

如果仍然挂载则执行:

umount /data/shared

10.3 删除DLM

pcs resource delete dlm --force

10.4 清理失败的DRBD资源(如果有的话)

pcs resource delete drbd_r0 --force

10.5 检查DRBD本身

drbdadm status r0

应该还是:

r0 role:Primary
  disk:UpToDate
  ha02 role:Primary
    peer-disk:UpToDate

如果保持这个状态,说明存储没有受到影响

 

pcs resource cleanup
pcs resource refresh
pcs status

image

10.6 创建DRBD Pacemaker资源

pcs resource create drbd_r0 ocf:linbit:drbd \
    drbd_resource=r0 \
    op monitor interval=30s

然后马上转换为promotable:

pcs resource promotable drbd_r0 \
    promoted-max=2 \
    promoted-node-max=1 \
    clone-max=2 \
    clone-node-max=1 \
    notify=true

image

10.7 退出maintenance模式

pcs property set maintenance-mode=false

image

 验证DRBD

两个节点

drbdadm status r0

应该:

r0 role:Primary
  disk:UpToDate
  ha02 role:Primary
    peer-disk:UpToDate

10.8 恢复DLM

pcs resource create dlm ocf:pacemaker:controld \
    allow_stonith_disabled=true \
    op monitor interval=30s

创建clone

pcs resource clone dlm meta interleave=true

查看状态

pcs status

image

 10.9 恢复GFS2

创建资源

pcs resource create gfs2_data Filesystem \
    device="/dev/drbd0" \
    directory="/data/shared" \
    fstype="gfs2" \
    options="noatime" \
    op monitor interval=20s

设置GFS2克隆,GFS2必须双节点同时挂载

pcs resource clone gfs2_data meta interleave=true

添加启动顺序,必须

DRBD Primary
       ↓
DLM
       ↓
GFS2 mount

添加约束:

pcs constraint order promote drbd_r0-clone then start dlm-clone

然后

pcs constraint order start dlm-clone then start gfs2_data-clone

至此,存储高可用层已经跑通。

11 部署MySQL

11.1 创建共享目录

因为GFS2已经挂载

/data/shared

所以在其中一个节点执行:

mkdir -p /data/shared/mysql

11.2 创建MySQL Dockers容器(不要启动)

注意:因为Pacemaker后面接管,所有这里用dockers create。

所有节点:

docker create \
--name mysql \
--network host \
-v /data/shared/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=bsoft-media \
-e MYSQL_DATABASE=wvp \
bsoft-media-mysql:ori

11.3 创建systemd服务

在所有节点都创建

文件:

vim /etc/systemd/system/mysql-container.service

内容:

[Unit]
Description=Docker MySQL Container
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/bin/docker start mysql
ExecStop=/usr/bin/docker stop mysql

TimeoutStartSec=120
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target

重启加载

systemctl daemon-reload

测试

systemctl start mysql-container
docker ps
systemctl stop mysql-container
docker ps

输出如下图,表示正常

image

 11.4 Pacemaker接管

先确认:

pcs status

现在应该类似:

VirtualIP Started ha01
DRBD Master ha01 ha02
DLM Started
GFS2 Started

image

 创建资源:

pcs resource create mysql \
systemd:mysql-container \
op monitor interval=30s

pcs status显示如下结果,表示正常:

mysql-container Started ha01

image

 11.5 绑定运行节点

让MySQL默认在ha01:

pcs constraint location mysql prefers ha01=100

查看

pcs constraint

出现如下提示,表示绑定成功

Location Constraints:
  mysql prefers ha01

image

 11.6 绑定VIP

VIP和MySQL必须在同一个节点

pcs constraint colocation add mysql with VirtualIP INFINITY

设置顺序:

pcs constraint order start VirtualIP then mysql

这时,启动顺序为:

ha01:

VIP
 |
MySQL

故障转移时启动顺手为:

ha01 DOWN

VIP
 |
ha02
 |
MySQL

确认VIP和MySQL在同一个节点,即ha01上

image

 11.7 测试故障迁移

先模拟,测试Pacemaker是否自动拉起。

systemctl stop mysql-container

稍等2秒,查看状态,如下MySQL仍然运行在ha01上。说明Pacemaker工作正常:

image

测试节点故障(在ha01):

shutdown -h now

观察ha02(VIP MySQL成功跳转ha02) 

image

 ha01 修复后,VIP和MySQL又跳转回来了。

12 部署FreeSWITCH

12.1 创建共享目录

mkdir -p /data/shared/freeswitch/conf
mkdir -p /data/shared/freeswitch/recordings

第一次启动时,把镜像里的默认配置复制出来

docker run -d \
--name freeswitch-init \
--network host \
bsoft-switch:v1.0.0

复制配置

docker cp freeswitch-init:/usr/local/freeswitch/conf/. \
/data/shared/freeswitch/conf/

删除临时容器

12.2 创建容器FreeSWITCH(不要启动)

所有节点:

docker create \
--name freeswitch \
--network host \
-v /data/shared/freeswitch/conf:/usr/local/freeswitch/conf \
-v /data/shared/freeswitch/recordings:/usr/local/freeswitch/recordings \
bsoft-switch:v1.0.0

12.3 创建systemd服务

所有节点:

cat >/etc/systemd/system/freeswitch-container.service <<EOF
[Unit]
Description=Docker FreeSWITCH Container
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/bin/docker start freeswitch
ExecStop=/usr/bin/docker stop freeswitch

TimeoutStartSec=120
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target
EOF

刷新:

systemctl daemon-reload

12.4 Pacemaker接管

创建资源:

pcs resource create freeswitch \
systemd:freeswitch-container \
op monitor interval=30s

指定运行节点:

pcs constraint location freeswitch prefers ha02=100

查看:

pcs constraint

image

 freeswitch运行在正确的节点上:

image

 添加资源约束:

GFS2启动后启动

pcs constraint order start gfs2_data-clone then start freeswitch

GFS2不存在则不能运行

pcs constraint colocation add freeswitch with gfs2_data-clone INFINITY

12.5 调整现有MySQL VIP,需改成资源组

pcs constraint --full

应该有:

mysql with VirtualIP

如图:

image

  删除:

pcs constraint remove colocation-mysql-VirtualIP-INFINITY

创建Group A资源组

pcs resource group add group-db VirtualIP mysql

顺序非常重要

group-db:

VirtualIP
   |
 mysql

Pacemaker自动保证:

启动:

VIP
 ↓
mysql

停止:

mysql
 ↓
VIP

检查:

pcs status

应该类似如下输出,表示操作成功

Resource Group: group-db
 VirtualIP Started ha01
 mysql     Started ha01

如图:

image

 固定资源组group-db在ha01上:

pcs constraint location group-db prefers ha01=100

12.6 绑定VIP

创建Group B(FreeSWITCH) VIP:

pcs resource create VirtualIP-media \
ocf:heartbeat:IPaddr2 \
ip=10.32.0.93 \
cidr_netmask=23 \
op monitor interval=30s

创建Group B业务组:

pcs resource group add group-media VirtualIP-media freeswitch

形成:

group-media:

VirtualIP-media
       |
  freeswitch

 

image

 固定FreeSWITCH默认运行ha02。

 

13 故障测试

13.1 测试1 ha01宕机

执行:

pcs node standby ha01

期望:

ha02:

group-db:
  VIP 10.32.0.92
  mysql

同时:

group-media:
  VIP 10.32.0.93
  freeswitch

即,所有业务运行在ha02节点:

image

13.2 测试2 恢复ha01

pcs node unstandby ha01

Group A资源组业务迁移回ha01

image

 13.3 测试3 ha02宕机

期望:

ha01:

group-media:
  VIP 10.32.0.93
  freeswitch

同时:

group-db:
  VIP 10.32.0.92
  mysql

image

 13.4 测试4 恢复ha02

pcs node unstandby ha02

恢复原有运行规则:

image

14 启用Pacemaker STONITH(IPMI/Fence)

因为DRBD Dual Primary 环境,STONITH 不是可选项

所以,生产环境必须STONITH/Fencing

如果是物理机则走路线:

fence_ipmilan

如果是VMware ESXi则:

fence_vmware_soap

如果是KVM,用:

fence_virt

如果是华为/浪潮/戴尔/超微服务器,执行:

dmidecode -s system-manufacturer

本文用VMware ESXi。所以使用fence_vmware_soap,通过vCenter API控制虚拟电源。

Pacemaker
    |
    |
fence_vmware_soap
    |
    |
 vCenter Server
    |
    |
 VMware VM

14.1 安装fence agent

两个节点执行:

dnf install -y python3-requests  fence-agents-vmware-soap 

14.2 创建STONITH设备

记住VMware ESXi IP地址和登录信息:

image

 将下列命令中的IP、用户名、密码换成上图登录ESXi时使用的信息。

创STONITH设备

pcs stonith create fence-esxi fence_vmware_rest \
  ip="10.32.0.205" \
  username="root" \
  password="你的ESXi登录密码" \
  ssl_insecure="1" \
  pcmk_host_map="ha01:openEuler-ha01;ha02:openEuler-ha02"

可以看到fence-esxi在ha01或ha02其中一个节点上显示为Started,而不是Stopped。

image

 

14.3 开启全局STONITH开关

pcs property set stonith-enabled=true

14.4 调整集群仲裁策略(针对DRBD+GFS2)

由于只有2个节点,一旦心跳中断,两个节点都会失去多数派(Quorum)。未来防止GFS2备双主挂载损坏。执行以下命令,让失去仲裁的节点主动自杀(配合STONITH重启)

pcs property set no-quorum-policy=suicide

14.5 模拟围栏测试

pcs stonith fence ha02

此时在 ESXi 界面里看到 openEuler-ha02 虚拟机立刻重启(状态变灰再变绿)。如果这一步成功, STONITH 防线已经生效。

等ha02节点重启后,业务组又恢复原始状态:

image

 未来防止开机时GFS2抢跑,必须避免开机时GFS2比DLM先启动,导致挂载失败。所以规定启动顺序:

# 1. DRBD 必须先提升为主,才能启动 DLM 锁服务
pcs constraint order promote drbd_r0-clone then start dlm-clone

# 2. DLM 锁服务启动后,才能挂载 GFS2
pcs constraint order start dlm-clone then start gfs2_data-clone

# 3. GFS2 挂载好了,才能启动 MySQL 和 FreeSWITCH 业务组
pcs constraint order start gfs2_data-clone then start group-db
pcs constraint order start gfs2_data-clone then start group-media

配置DRBD的“脑裂自动裁决”机制,这是防止极端情况下数据损毁最后一道防线。编辑/etc/drbd.d/global_common.conf文件,net { ... } 部分中加入以下三行:

net {
    fencing resource-only;
    after-sb-0pri discard-zero-changes;
    after-sb-1pri discard-secondary;
    after-sb-2pri disconnect;
}

执行

drbdadm adjust r0

验证:

image

15 新增服务

以添加httpd服务为例。

  • 执行添加命令
pcs resource create httpd systemd:httpd --group group-db
  • 确认资源和启动顺序
Resource Group: group-db
    VirtualIP  (ocf::heartbeat:IPaddr2):        Started ha01
    mysql      (systemd:mysql-container):       Started ha01
    httpd      (systemd:httpd):                 Started ha01

调整顺序,如:

pcs resource group add group-db httpd --before mysql

 

posted @ 2026-07-20 15:09  钟齐峰  阅读(20)  评论(0)    收藏  举报