1 简介
MooseFS 是开源、轻量、兼容 POSIX 的分布式文件系统,可以把多台普通服务器的磁盘整合为统一存储池,对外像本地文件一样挂载使用,无需改造上层业务代码。
核心组件
- Master Server(管理主节点)
保存全集群元数据:目录树、权限、文件位置、分片映射;统一调度读写。社区版默认单主,存在单点风险;商业 Pro 版支持多主高可用MooseFS。 - Metalogger(元数据备份节点)
定时同步 Master 的元数据日志,Master 宕机后,可以用它恢复元数据,实现故障兜底。 - Chunk Server(数据存储节点)
存放真实业务数据;文件会被切分成固定大小 Chunk(默认 64MB),自动多副本分散在不同节点,副本数可自定义,实现冗余容错;支持横向扩容,新增机器直接加入集群扩容容量。 - Client(客户端 mfsmount)
通过 FUSE 挂载 MFS 存储到本地目录,标准 POSIX 接口,支持 ls/cp/mkdir、软硬链接、权限控制,普通程序直接读写,不用专用 SDK
主要特性
- POSIX 兼容:上层应用直接读写,和普通 Linux 文件无差别
- 数据多副本:自动分片 + 跨机器副本,硬盘 / 节点坏了数据不丢失(软 RAID)
- 在线扩容:随时新增 ChunkServer,不停机扩容存储
- 回收站(trash):删除文件可恢复,误删防护
- Web 监控界面(mfscgiserv):自带可视化面板,查看容量、节点状态
- 快照功能:支持文件系统快照备份
- 轻量易部署:组件简单,依赖少,运维门槛低,适合中小型集群、实训环境
官方文档:https://docs.moosefs.com/
2 部署
2.1 准备工作
实验需使用四个 rocky9.6 的虚拟机
| 虚拟机名称 | IP | 角色 |
|---|---|---|
| server1 | 192.168.40.171 | master |
| server2 | 192.168.40.172 | chunkserver |
| server4 | 192.168.40.174 | chunkserver |
| server5 | 192.168.40.175 | client |
所有节点执行以下命令,添加 MooseFS 官方 YUM 软件源
bash
[root@server1 ~]# curl "https://repository.moosefs.com/RPM-GPG-KEY-MooseFS" > /etc/pki/rpm-gpg/RPM-GPG-KEY-MooseFS
[root@server1 ~]# curl "http://repository.moosefs.com/MooseFS-4-el8.repo" > /etc/yum.repos.d/MooseFS.repo

server1 安装 MooseFS 主管理服务、网页监控组件和集群命令行管理工具,部署 Master 管理节点
bash
[root@server1 ~]# yum install moosefs-master moosefs-cgi moosefs-cgiserv moosefs-cli
server2 安装 MooseFS 数据分片存储服务,作为 ChunkServer 存储节点
bash
[root@server2 ~]# yum install moosefs-chunkserver
server4 安装 MooseFS 数据分片存储服务,也作为 ChunkServer 存储节点
bash
[root@server4 ~]# yum install moosefs-chunkserver
server5 安装 MooseFS 客户端挂载工具,用于挂载访问分布式文件系统
bash
[root@server5 ~]# yum install moosefs-client
所有节点添加 mfsmaster 解析
bash
[root@server1 ~]# vim /etc/hosts

server2、4、5同上
2.2 master 配置
直接启动 moosefs-master 主管理服务和网页监控服务,并设置开机自启
bash
[root@server1 ~]# systemctl enable --now moosefs-master.service
[root@server1 ~]# systemctl enable --now moosefs-gui.service

访问前端网页http://192.168.40.171:9425,可以查看 master 状态

2.3 server 配置
关闭 server2 和 server4,分别添加一块新硬盘,用来存放 MFS 的数据块 chunk,参与 MFS 集群的数据共享


分区

设置开机自动挂载
bash
[root@server2 ~]# mkdir /mnt/ssd01
[root@server2 ~]# blkid

bash
[root@server2 ~]# vim /etc/fstab

bash
[root@server2 ~]# systemctl daemon-reload
# systemd 重新读取挂载单元配置
[root@server2 ~]# mount -a
# 读取 /etc/fstab,尝试挂载所有配置条目
[root@server2 ~]# df
# 查看是否挂载成功
[root@server2 ~]# chown mfs.mfs /mnt/ssd01/
# 把 SSD 存储目录交给 mfs 账号读写,mfschunkserver 默认以 mfs 用户运行,如果目录还是 root 权限,服务启动时无法在 /mnt/ssd01 创建锁文件 .lock 和数据块,直接报 Permission denied 权限拒绝 启动失败
[root@server2 ~]# vim /etc/mfs/mfshdd.cfg
# 告诉 chunkserver ,把 /mnt/ssd01 这个挂载好的 SSD 分区,交给 MFS 用来存放分布式数据块(chunk)

启动服务
bash
[root@server2 ~]# systemctl enable --now moosefs-chunkserver
在前端查看

server4操作与server2相同

补充知识点:SSD 与 HDD
- HDD(机械硬盘 //mnt/hdd01)
内部有旋转盘片 + 移动磁头,类似黑胶唱片,靠机械运动读写数据
✅ 优点:同容量便宜、容量可以做很大(8T/16T/20T),适合存大量不经常读写的冷数据
❌ 缺点:随机读写慢、寻道延迟高、怕震动、有噪音 - SSD(固态硬盘 //mnt/ssd01)
没有机械结构,纯闪存芯片电子读写,类似大号 U 盘
✅ 优点:读写速度快、随机 IO 极强、低延迟、抗震静音 ,适合频繁读写的热数据、高并发业务
❌ 缺点:同容量价格贵,有写入寿命(擦写次数上限)
| 对比项 | ChunkServer 使用 SSD | ChunkServer 使用 HDD |
|---|---|---|
| 读写性能 | 高并发、随机读写很快,集群整体响应低延迟 | 顺序读写尚可,随机读写慢,高并发容易卡顿 |
| 成本 | 贵,同容量更花钱 | 便宜,适合做大容量仓库存储 |
| 适合数据 | 热数据:频繁读写、小文件多、数据库、业务实时文件 | 冷数据:归档、备份、视频素材、大文件、长期存放很少访问 |
| MFS 用法 | 可单独划分存储类,指定文件存 SSD 节点 | 冷数据归档存放,扩容大容量存储空间 |
此处部署的 server2 和 server4 均使用 SSD,用于存放热数据,后续会新加一个 server3,使用 HDD,用于存放冷数据
2.4 client 配置
server5 作为 MFS 客户端节点 ,把整个 MFS 分布式集群,挂载到本机 /mnt/mfs,之后业务程序、用户读写 /mnt/mfs 就等同于访问整个集群的共享存储
bash
[root@server5 ~]# cd /etc/mfs
[root@server5 mfs]# mkdir /mnt/mfs
[root@server5 mfs]# mfsmount /mnt/mfs -H mfsmaster

访问前端

3 用法示例
为方便测试,新部署一台 server3 做 chunkserver,用于存放冷数据
bash
[root@server3 ~]# curl "https://repository.moosefs.com/RPM-GPG-KEY-MooseFS" > /etc/pki/rpm-gpg/RPM-GPG-KEY-MooseFS
[root@server3 ~]# curl "http://repository.moosefs.com/MooseFS-4-el8.repo" > /etc/yum.repos.d/MooseFS.repo
[root@server3 ~]# yum install moosefs-chunkserver
[root@server3 ~]# mkdir /mnt/hdd01
[root@server3 ~]# chown mfs.mfs /mnt/hdd01/
[root@server3 ~]# vim /etc/mfs/mfshdd.cfg

bash
[root@server3 ~]# vim /etc/hosts

bash
[root@server3 ~]# systemctl enable --now moosefs-chunkserver

在 client 上可以管理全部共享数据
3.1 查看所有可用存储类
mfslistsclass:列出当前 MooseFS 所有可用的存储 class
bash
[root@server5 mfs]# mfslistsclass

- CP 系列(副本复制模式,传统多副本)
- 2CP = 2 copies
完整保存 2 份一模一样的数据块,可容忍 1 台 chunkserver 故障 - 3CP = 3 copies
完整保存 3 份一模一样的数据块,可容忍 2 台 chunkserver 故障
优点:读写性能好;缺点:存储空间开销大
- EC 系列(Erasure Code 纠删码模式,编码冗余,节省空间)
格式:ECk+m → k 份数据分片 + m 份校验分片,总共 k+m 台节点存放
- EC4+1
原始数据切成 4 份数据片,额外生成 1 份校验片,一共 5 片分散存储
✅ 允许损坏任意 1 片 (任意一台 chunkserver 挂掉,数据可恢复)
存储开销:(4+1)/4 = 1.25 倍(相比 2CP 的 2 倍、3CP 的 3 倍,省空间) - EC8+1
原始数据切成 8 份数据片,额外生成 1 份校验片,一共 9 片分散存储
✅ 允许损坏任意 1 片
存储开销:(8+1)/8 = 1.125 倍,更加节省磁盘
EC 特点:磁盘利用率更高;但是写入、重构恢复时 CPU 开销更大,适合冷数据归档存储
3.2 获取文件 / 目录绑定的存储类
bash
[root@server5 ~]# cd /mnt/mfs
[root@server5 mfs]# mkdir dir1
[root@server5 mfs]# mkdir dir2
[root@server5 mfs]# mfssclass get dir1/
# 查看目录 dir1/ 当前绑定的存储类规则

2CP = 2 copies ,代表这个目录 dir1/ 的存储副本策略:文件保存 2 份副本
在 MooseFS 里,带末尾 / 和不带 /,查询结果完全一样,没有功能区别

3.3 查看文件 chunk 副本分布位置
bash
[root@server5 mfs]# cd dir1/
[root@server5 dir1]# cp /etc/passwd .
[root@server5 dir1]# mfsfileinfo passwd
副本存在173和174上

bash
[root@server5 dir1]# mfssclass get .

输出 .: 2CP 含义:当前目录 dir1 的存储冗余策略是 2CP(双副本)
3.4 定义、绑定副本存放策略
-K:Keep,持久保存副本
数字*:副本数量,各自任选任意节点
bash
[root@server5 mfs]# mfsscadmin create -K 1* hot_1cp
[root@server5 mfs]# mfslistsclass
[root@server5 mfs]# cd dir1/
[root@server5 dir1]# mfssclass set hot_1cp -r .
# 递归把当前目录下所有目录、已存在全部文件,统一设置存储类为 hot_1cp(热数据单副本)
[root@server5 dir1]# mfsfileinfo passwd

bash
[root@server5 dir1]# mfssclass get passwd
[root@server5 dir1]# mfssclass get .
[root@server5 dir1]# mfscheckfile passwd

bash
[root@server5 dir1]# cd ..
[root@server5 mfs]# cd dir2/
[root@server5 dir2]# mfssclass get .
[root@server5 dir2]# cp /etc/fstab .
[root@server5 dir2]# mfsfileinfo fstab

3.5 ChunkServer 本地数据目录
bash
[root@server2 ~]# cd /mnt/ssd01/

MFS 为了防止单目录文件过多导致性能下降,采用 2 级哈希散列目录:
- 第一层:
00 ~ FF共 256 个文件夹 - 第二层:每个文件夹内部存放真实的 chunk 文件,命名格式类似
0000000000000002_00000001.mfs
MooseFS 里,任意文件会被切分成固定大小的数据块,叫做 Chunk (默认 64MiB)。
每一个 Chunk 在整个集群内拥有全局唯一的 64 位无符号整数编号 ,这个编号就是 Chunk ID 。例如:0000000000000002 就是 Chunk ID;后面 _00000001 是版本号,和目录路由无关。
Chunk ID 做哈希取前两位十六进制,决定 chunk 放进哪个 00~FF 文件夹,实现文件均匀打散。
完整路由规则
- 拿到 Chunk ID(十进制大整数),转为 16 位十六进制字符串(固定补齐前导零,16 字节,64bit)
- 取整个十六进制字符串的【第一个字节 = 前两位十六进制字符】
- 这两位字符就是一级目录名:范围
00 ~ FF,一共 256 个文件夹 - 进入该一级目录后,直接存放完整命名的 chunk 文件:
ChunkID_版本.mfs
3.6 添加标签
标签打在每一台 chunkserver 上,再用 mfsscadmin 创建存储类匹配标签,控制副本存放节点。标签只能是单个英文字母 A-Z,一台 chunkserver 可以打多个标签。
server2 打标签 A
bash
[root@server2 ssd01]# vim /etc/mfs/mfschunkserver.cfg
[root@server2 ssd01]# systemctl reload moosefs-chunkserver.service

server3 打标签 B
bash
[root@server3 ~]# vim /etc/mfs/mfschunkserver.cfg
[root@server3 ~]# systemctl reload moosefs-chunkserver.service

server3 打标签 C
bash
[root@server4 ~]# vim /etc/mfs/mfschunkserver.cfg
[root@server4 ~]# systemctl reload moosefs-chunkserver.service

前端网页可以查看

新建存储策略 1CP_A
规则 -K A:保留1 份副本,副本必须必须存放在配置了标签 A 的 ChunkServer 上
bash
[root@server5 dir2]# cd ..
[root@server5 mfs]# mfsscadmin create -K A 1CP_A
[root@server5 mfs]# mfssclass set -r 1CP_A dir1/
[root@server5 mfs]# mfssclass get dir1/
[root@server5 mfs]# cd dir1/
[root@server5 dir1]# mfsfileinfo passwd
副本存在 server2 即打了标签 A 的 ChunkServer 上

列出集群全部存储类 + 完整规则定义,可以看到创建的存储策略
bash
[root@server5 dir1]# mfsscadmin list -l

创建双副本存储策略,副本分别存 A、B 标签节点,递归给当前目录绑定该存储类
bash
[root@server5 dir1]# cd ../dir2/
[root@server5 dir2]# mfsfileinfo fstab
[root@server5 dir2]# mfsscadmin create -K A,B 2CP_AB
[root@server5 dir2]# mfssclass set -r 2CP_AB .

递归给 dir3 绑定 3CP 存储策略,三个ChunkServer都存副本
bash
[root@server5 dir2]# cd ..
[root@server5 mfs]# mkdir dir3
[root@server5 mfs]# mfsgetsclass dir3
[root@server5 mfs]# mfssclass set -r 3CP dir3/
[root@server5 mfs]# cp /etc/hosts dir3/
[root@server5 mfs]# cd dir3/
[root@server5 dir3]# mfsfileinfo hosts

加多个标签,用空格隔开即可,S即 SSD,H即 HDD
bash
[root@server2 ssd01]# vim /etc/mfs/mfschunkserver.cfg
[root@server2 ssd01]# systemctl reload moosefs-chunkserver.service

bash
[root@server3 ~]# vim /etc/mfs/mfschunkserver.cfg
[root@server3 ~]# systemctl reload moosefs-chunkserver.service

bash
[root@server4 ~]# vim /etc/mfs/mfschunkserver.cfg
[root@server4 ~]# systemctl reload moosefs-chunkserver.service

前端网页查看

创建多标签存储类 2CP_SH ,一共 2 份持久副本,一份存在带标签 S 的 ChunkServer,一份存在带标签 H 的 ChunkServer

3.7 回收站
创建 /mnt/meta 目录,以元数据模式(-m)挂载 MooseFS,进入挂载点后可看到 trash(回收站)目录,存放被删除的文件
bash
[root@server5 dir3]# cd ../..
[root@server5 mnt]# mkdir meta
[root@server5 mnt]# mfsmount -m /mnt/meta/
[root@server5 mnt]# cd /mnt/meta/

MooseFS 回收站不直接显示原始文件名,而是以文件 inode / 文件 ID 作为目录名存放删除文件。每个目录内才存放原文件、原始路径等信息
bash
[root@server5 meta]# cd trash/
[root@server5 trash]# ls

恢复文件
bash
[root@server5 trash]# rm -fr /mnt/mfs/dir1/passwd
# 删除 MooseFS 业务文件
[root@server5 trash]# mfsgettrashtime /mnt/mfs/dir1/
# 查看目录回收站保留时长(单位:秒),文件超过这个时间,会被自动清理,**无法恢复**
[root@server5 trash]# find -name *passwd*
# 在回收站所有子目录递归检索,匹配名字包含 passwd 的被删除文件
[root@server5 trash]# mv ./004/00000004\|dir1\|passwd undel/
[root@server5 trash]# ll /mnt/mfs/dir1/
undel 是 trash 内部系统专用恢复目录 ,把回收站里被删除的文件 mv 移动到 undel/ , MooseFS 自动将文件还原回原始路径 /mnt/mfs/dir1/passwd
命令里 \| 必须加反斜杠转义,shell 才能识别文件名里的竖线符号

4 pacemaker 高可用
现准备下线 server3,用于给 master 做备节点,其中还存放有文件

先给文件备份,保证server3上没有数据
bash
[root@server5 trash]# cd /mnt/mfs/
[root@server5 mfs]# mfsgetsclass dir3/
[root@server5 mfs]# mfsgetsclass dir2/
[root@server5 mfs]# mfsgetsclass dir1/
[root@server5 mfs]# mfscreatesclass -K A,C 2CP_AC
[root@server5 mfs]# mfssetsclass -r 2CP_AC dir2/
[root@server5 mfs]# mfssetsclass -r 2CP_AC dir3/
[root@server5 mfs]# mfsgetsclass dir1/
[root@server5 mfs]# mfsgetsclass dir2/
[root@server5 mfs]# mfsgetsclass dir3/

此时 chunks 为0,可以下线

下线并移除
bash
[root@server3 ~]# systemctl disable --now moosefs-chunkserver.service

部署 pacemaker 前,停掉所有服务
bash
[root@server1 ~]# systemctl stop moosefs-master.service
[root@server2 ~]# systemctl stop moosefs-chunkserver.service
[root@server4 ~]# systemctl stop moosefs-chunkserver.service
编辑 rocky-addons.repo,把 highavailability 源启用,可以安装高可用集群套件
bash
[root@server1 ~]# cd /etc/yum.repos.d/
[root@server1 yum.repos.d]# vim rocky-addons.repo

bash
[root@server1 yum.repos.d]# yum install -y pacemaker corosync pcs fence-agents
| 软件 | 作用 |
|---|---|
| pacemaker | 集群资源管理器,负责故障转移、资源启停调度 |
| corosync | 集群消息通信层,节点间心跳、状态同步 |
| pcs | 集群命令行管理工具 |
| fence-agents | 隔离设备代理(stonith 设备,故障节点隔离,防止脑裂) |
server3也安装上述软件
启动服务,安装 pcs 包后自动生成 hacluster 用户,两节点密码必须相同
bash
[root@server1 yum.repos.d]# cd
[root@server1 ~]# systemctl enable --now pcsd
[root@server1 ~]# ssh-keygen
[root@server1 ~]# ssh-copy-id server3
[root@server1 ~]# echo westos | passwd --stdin hacluster
# 在 server1 本机,给 hacluster 用户设置密码 westos
[root@server1 ~]# ssh server3 'echo westos | passwd --stdin hacluster'
# 远程登录 server3,在对端机器同样把 hacluster 密码设置为 westos,所有集群节点的 hacluster 密码必须完全相同
[root@server1 ~]# id hacluster

在 server3 启动服务,验证密码是否设置成功
bash
[root@server3 yum.repos.d]# cd
[root@server3 ~]# systemctl enable --now pcsd
[root@server3 ~]# cat /etc/shadow

集群时间同步
bash
[root@server1 ~]# systemctl restart chronyd
[root@server3 ~]# systemctl restart chronyd
使用 hacluster 用户、密码 westos,完成 server1 和 server3 两台节点之间 pcs 集群认证,节点互信,后续才能组建集群
bash
[root@server1 ~]# pcs host auth server1 server3 -u hacluster -p westos

基于已完成 pcs host auth 认证的节点 server1、server3,生成集群配置文件,集群名称:mycluster
bash
[root@server1 ~]# pcs cluster setup mycluster server1 server3

在集群全部节点上启动 pacemaker + corosync 集群服务,并设置自启动
bash
[root@server1 ~]# pcs cluster start --all
[root@server1 ~]# pcs cluster enable --all

查看集群状态,server1 和 server3 在线,同时禁用 STONITH(隔离设备)
bash
[root@server1 ~]# pcs status
[root@server1 ~]# pcs property set stonith-enabled=false

针对双节点 Pacemaker 集群:丢失仲裁时,集群继续运行资源,不会自动停止业务
bash
[root@server1 ~]# pcs property set no-quorum-policy=ignore
[root@server1 ~]# pcs property list
# 查看 Pacemaker 集群全局属性,验证设置的 stonith-enabled、no-quorum-policy 是否生效

pcs resource create:创建集群资源VIP:自定义资源名称ocf:heartbeat:IPaddr2:资源代理(管理虚拟 IP)ip=192.168.40.100:虚拟 IP 地址cidr_netmask=24:子网掩码 255.255.255.0op monitor interval=30s:监控操作,每 30 秒检测一次 VIP 是否正常
bash
[root@server1 ~]# pcs resource create VIP ocf:heartbeat:IPaddr2 ip=192.168.40.100 cidr_netmask=24 op monitor interval=30s
[root@server1 ~]# pcs status
VIP 添加成功,且已绑定到节点上

所有节点添加VIP的解析
- Pacemaker 管理 192.168.40.100 这个 VIP 资源,可以在 server1 ↔ server3 自动切换
- 所有节点
/etc/hosts统一配置:192.168.40.100 mfsmaster - 不管 VIP 飘到 server1 还是 server3,所有机器解析 mfsmaster 永远指向这个浮动 VIP
bash
[root@server1 ~]# vim /etc/hosts

MooseFS Master 的元数据文件(mfsmaster.cfg、changelog、metadata)需要存放在共享存储
- 外置存储服务器提供 iSCSI Target(共享磁盘 LUN)
- server1、server3 安装 initiator,挂载这块共享块设备
- Pacemaker 控制:同一时间只允许其中一台节点挂载该共享盘(防止双写损坏数据)
- 配合约束:VIP、mfsmaster、文件系统资源三者同节点漂移
bash
[root@server1 ~]# yum install -y iscsi-initiator-utils
[root@server3 ~]# yum install -y iscsi-initiator-utils
server5关机,添加一块新硬盘

server5 即 client 作为共享存储服务器,对外提供一块共享块磁盘,给 Pacemaker 集群的 server1/server3 挂载,存放 MooseFS Master 元数据。
bash
[root@server5 ~]# yum install -y targetcli
[root@server5 ~]# systemctl enable --now target
[root@server5 ~]# targetcli
/> /backstores/block create my_disk /dev/nvme0n2
# 创建后端块存储:把本地磁盘 /dev/nvme0n2 命名为 my_disk
/> /iscsi create iqn.2026-08.com.example:mfsdata
# 创建 iSCSI Target(共享存储对外标识 IQN),自定义IQN名称,标识这个共享盘用于mfs元数据
/> /iscsi/iqn.2026-08.com.example:mfsdata/tpg1/luns create /backstores/block/my_disk
# 创建 LUN:把上面的 my_disk 映射给这个iSCSI目标
/> /iscsi/iqn.2026-08.com.example:mfsdata/tpg1/acls create iqn.2026-08.com.example:client
# 创建 ACL 访问控制:只允许 IQN = iqn.2026-08.com.example:client 的客户端连接
/> ls
# 确认无误后退出
/> exit
注意:这里给两台机器用同一条 ACL 并不会出现问题,但后续加入 SBD 服务,在重启时会产生大量报错,故建议使用两条,详见6.2.4

iSCSI Initiator 客户端即 server1 和 server3 配置,客户端 IQN 必须和 server5(target 服务端)ACL 里允许的名称完全一致,否则无法连接共享存储
bash
[root@server1 ~]# vim /etc/iscsi/initiatorname.iscsi

bash
[root@server1 ~]# scp /etc/iscsi/initiatorname.iscsi server3:/etc/iscsi/
[root@server1 ~]# iscsiadm -m discovery -t st -p 192.168.40.175
# 发现远端iSCSI Target


如果之前有发现失败的情况,执行systemctl restart iscsid,再执行上面的指令
登录本机已发现保存的全部 iSCSI Target
-m node:node 模式,管理已经发现保存的 iSCSI 目标-l=--login:登录(建立 iSCSI 会话,接入远端共享块设备)
bash
[root@server1 ~]# iscsiadm -m node -l
[root@server1 ~]# fdisk -l

server3 同上

分区
bash
[root@server1 ~]# fdisk /dev/sda

格式化后挂载
先将iSCSI共享分区/dev/sda1格式化后临时挂载到/mnt作为中转目录,把/var/lib/mfs中原有的 MFS 元数据完整复制至该共享分区;完成数据迁移后卸载/mnt,再将/dev/sda1正式挂载到/var/lib/mfs。挂载后/var/lib/mfs 下的旧文件还存在本地磁盘,但是被挂载盖住看不见了,访问/var/lib/mfs读写的实际是共享分区内的数据,无需修改MFS配置,后续可由 Pacemaker 控制节点间自动挂载切换,实现 mfsmaster 高可用
bash
[root@server1 ~]# mkfs.xfs /dev/sda1
[root@server1 ~]# mount /dev/sda1 /mnt/
[root@server1 ~]# df

把 mfsmaster 核心元数据迁移到共享存储
bash
[root@server1 ~]# chown mfs.mfs /mnt/
# 修改共享挂载目录 /mnt 的属主、属组为 mfs:mfs,MooseFS 的运行用户是 mfs,如果权限不对,mfsmaster 进程无法读写元数据文件,会启动失败
[root@server1 ~]# cd /var/lib/mfs/
# 进入本地原有 mfsmaster 元数据目录 /var/lib/mfs/
[root@server1 mfs]# cp -p * /mnt/
# 将全部元数据文件复制到共享磁盘 /mnt,-p 保留权限

bash
[root@server1 mnt]# cd
[root@server1 ~]# umount /mnt
[root@server1 ~]# mount /dev/sda1 /var/lib/mfs/
[root@server1 ~]# df

手动开启 moosefs-master 服务,测试服务是否正常
bash
[root@server1 ~]# systemctl start moosefs-master.service

bash
[root@server1 ~]# ll /var/lib/mfs/
[root@server1 ~]# systemctl stop moosefs-master.service
正常启动时有.back文件

卸载目录,继续配置 server3
bash
[root@server1 ~]# umount /var/lib/mfs
安装 moosefs-master 服务所需安装包
bash
[root@server3 ~]# yum install moosefs-master moosefs-cgi moosefs-cgiserv moosefs-cli
[root@server3 ~]# partprobe
[root@server3 ~]# ll /dev/sda1

直接挂载/var/lib/mfs/,测试服务启动是否正常
bash
[root@server3 ~]# mount /dev/sda1 /var/lib/mfs/
[root@server3 ~]# df
[root@server3 ~]# systemctl start moosefs-master.service
[root@server3 ~]# systemctl status moosefs-master.service

无误后手动关闭服务,取消挂载,并禁止两台机器的 moosefs-master 服务自启动,后续由 Pacemaker 完整管理
bash
[root@server3 ~]# systemctl stop moosefs-master.service
[root@server3 ~]# systemctl disable moosefs-master.service
[root@server3 ~]# umount /var/lib/mfs
bash
[root@server1 ~]# systemctl disable moosefs-master.service
创建共享磁盘资源 mfsdata ,交给 pacemaker 自动控制 /dev/sda1 是否挂载到 /var/lib/mfs,不再手动 mount/umount
pcs resource create mfsdata:新建集群资源,名称叫mfsdataocf:heartbeat:Filesystem:使用 Filesystem 文件系统资源代理,用来管理磁盘挂载 / 卸载device=/dev/sda1:要管理的 iSCSI 共享分区directory=/var/lib/mfs:挂载目录fstype=xfs:文件系统类型是 xfsop monitor interval=1min:每 1 分钟检测一次磁盘挂载状态,故障就触发切换
bash
[root@server1 ~]# pcs resource create mfsdata ocf:heartbeat:Filesystem device=/dev/sda1 directory=/var/lib/mfs fstype=xfs op monitor interval=1min
创建 MFS Master 服务资源 mfsmaster,pacemaker 自动启停 mfsmaster 服务
pcs resource create mfsmaster:新建资源,名称mfsmastersystemd:moosefs-master:调用 systemd 管理 moosefs-master 服务启停op monitor interval=30s:每 30 秒检查一次 mfsmaster 进程存活状态,挂了就迁移资源
bash
[root@server1 ~]# pcs resource create mfsmaster systemd:moosefs-master op monitor interval=30s
查看集群状态,这时VIP和资源不在同一节点

将虚拟 IP、共享磁盘挂载、MFS Master 服务划入名为 mfscluster 的资源组,三者绑定在同一节点,故障时整体迁移,实现完整的 mfsmaster 高可用集群调度
bash
[root@server1 ~]# pcs resource group add mfscluster VIP mfsdata mfsmaster

开启 moosefs-chunkserver 服务,状态正常
bash
[root@server2 ~]# systemctl start moosefs-chunkserver.service
[root@server4 ~]# systemctl start moosefs-chunkserver.service

此时 master 只显示VIP

client 接入分布式 MooseFS 文件系统,数据正常
bash
[root@server5 ~]# mfsmount /mnt/mfs -H mfsmaster
[root@server5 ~]# cd /mnt/mfs/dir2
[root@server5 dir2]# mfsfileinfo fstab

当前资源在 server1

把 server1 设置为待机模式
bash
[root@server1 ~]# pcs node standby
server3 接管

server1 恢复正常
bash
[root@server1 ~]# pcs node unstandby
server1上线,但不会主动接管,变成备节点

5 断电重启后恢复元数据
突然断电后重启虚拟机,会造成元数据丢失,mfsmaster 服务启动失败
资源在 server3,但两台 master 的 mfsmaster 服务均启动失败

在server3上查看元数据metadata.mfs,没有

进行恢复操作前必须停止 mfsmaster 服务,否则文件占用会复制失败或数据错乱
bash
[root@server3 ~]# cd /var/lib/mfs
[root@server3 mfs]# cp metadata.mfs.back metadata.mfs
# 用备份元数据覆盖损坏 / 丢失的主元数据文件,完成元数据恢复
[root@server3 mfs]# chown -R mfs:mfs /var/lib/mfs
[root@server3 mfs]# mfsmaster -c /etc/mfs/mfsmaster.cfg
# 手动指定配置文件,前台启动 mfsmaster 服务,用来测试元数据是否恢复成功

恢复成功,尝试启动服务
bash
[root@server3 mfs]# cd
[root@server3 ~]# pcs resource enable mfsmaster
[root@server3 ~]# pcs status

- VIP、mfsdata 文件系统 已经在 server3 正常 Started
- mfsmaster:Stopped
- 两个节点 server1、server3 尝试启动
moosefs‑master.service全都失败result 'failed'
大概率是lock 文件残留 ,清理 lock 文件,对 mfsmaster 资源执行清理操作:清除该资源历史故障记录、失败计数;清空集群保存的资源上次失败状态;让集群重新尝试调度、启动这个资源
bash
[root@server3 ~]# systemctl stop moosefs-master
[root@server3 ~]# rm -f /var/lib/mfs/.mfsmaster.lock
[root@server3 ~]# ll /var/lib/mfs/
[root@server3 ~]# pcs resource cleanup mfsmaster

集群状态正常,删除失败记录
bash
[root@server3 ~]# pcs resource cleanup mfsmaster
# 重置资源的"失败计数"和"失败历史",并强制 Pacemaker 重新探测资源当前的真实状态
[root@server3 ~]# pcs status

server1 的 moosefs-master 服务恢复正常
server3 依旧不正常

手动迁移资源到 server3,尝试恢复
bash
[root@server3 ~]# pcs resource move mfscluster server3
[root@server3 ~]# pcs resource clear mfscluster
# 移除因手动操作(move 或 ban)而产生的临时位置限制
服务恢复正常

6 添加 SBD 服务
6.1 简介
SBD = STONITH Block Device(基于块设备的 STONITH 隔离) ,全称也常被释义为 Storage-Based Death,是 Pacemaker 高可用集群里核心的隔离(Fencing/STONITH)机制,用来防止脑裂(split-brain),保护共享存储数据安全。
- 基础组成部件
-
共享 SBD 块设备
所有集群节点都能读写的同一块独立磁盘 / 分区,专门用于存储两类信息:各节点周期性上报的存活心跳记录、用于隔离故障节点的投毒消息(poison pill)。
-
Watchdog 看门狗
看门狗分为物理硬件看门狗(物理服务器)和软件模拟看门狗
softdog(虚拟机实验环境)。运行规则:SBD 守护进程必须周期性向看门狗发送 "喂狗" 信号;一旦长时间收不到喂狗信号,看门狗会直接强制整机重启。
-
sbd 守护进程 + Corosync/Pacemaker
sbd 负责读写共享盘心跳、解析投毒指令、操作看门狗;Corosync 负责集群节点间通信与故障判定;Pacemaker 负责资源调度。
- 正常运行流程
- 集群全部节点启动
sbd服务,服务启动后加载看门狗驱动,持续对本机看门狗执行喂狗操作。 - 每个节点周期性向共享 SBD 磁盘写入自身心跳,宣告本机存活。
- 所有节点读取共享磁盘上其他节点的心跳记录,互相感知在线状态。
- Pacemaker 根据集群状态,在正常节点上启动资源组(VIP、共享磁盘挂载、mfsmaster),对外提供服务。
- 故障判定、投毒、隔离完整流程
- 集群网络出现中断,Corosync 无法收到某个节点的通信报文,同时共享盘读取到该节点心跳超时,集群判定此节点故障。
- 正常运行的节点向共享 SBD 块设备写入一条投毒消息,标记目标故障节点,下达隔离重启指令。
- 故障节点上运行的 sbd 进程读取到共享磁盘内属于自己的投毒指令。
- sbd 立刻停止向本机看门狗发送喂狗信号。
- 看门狗等待超时,直接强制重启故障节点。
- 故障节点重启过程中,释放挂载的共享磁盘、释放虚拟 IP 等集群资源。
- Pacemaker 确认节点隔离完成后,将整套资源组迁移至健康节点,重新启动 mfsmaster 服务,业务继续对外提供访问。
- 节点恢复上线流程
- 被隔离的节点完成重启,系统启动后 sbd 服务先行启动,重新喂看门狗,读取共享磁盘信息。
- 确认无针对本机的投毒指令后,节点正常加入集群,上报心跳。
- 集群管理员可根据业务需求,决定是否将资源回迁到此节点。
6.2 部署
6.2.1 准备共享磁盘
/dev/sda /dev/sdb 这种名字是内核动态分配 ,新增磁盘、重启 VMware 之后顺序会乱,sda/sdb 会漂移,绝对不能写 /dev/sdb1 到 pacemaker Filesystem 资源
bash
ll /dev/disk/by-id/
蓝色部分 by-id 是固定标识,不会变

此时集群内的资源还是写的 /dev/sdb1
bash
[root@server1 ~]# pcs resource config mfscluster

为防止漂移,建议写固定的 by-id
bash
[root@server1 ~]# ls -l /dev/disk/by-id/ | grep sda1

scsi‑1LIO‑ORG_xxx‑part1scsi‑36001405d4addb7b547f411c81c91ecc9‑part1scsi‑SLIO‑ORG_xxx‑part1wwn‑0x6001405d4addb7b547f411c81c91ecc9‑part1
四个等价,2、4选其一使用
1、3(带 LIO‑ORG)是 iSCSI Target 的 Inquiry 别名,如果 targetcli 改名字,这个 by‑id 名字会变,故不推荐使用
bash
[root@server1 ~]# pcs resource update mfsdata device="/dev/disk/by-id/wwn-0x6001405d4addb7b547f411c81c91ecc9-part1"

需要新加一块磁盘,用作SBD
这里我是在装了 targetcli 的机器上创建的磁盘,但生产上不推荐,可以直接跳过这部分,用第二种做法
方法一
server5 关机,新加一块 1G 的磁盘

server1 和server3 上装需要的软件
bash
dnf install -y sbd fence-agents-sbd
使用本机磁盘 /dev/nvme0n3,也就是新加的 1GB 磁盘,通过 targetcli 创建后端存储并新建 LUN 导出 iSCSI 共享盘
bash
[root@server5 ~]# targetcli
/> /backstores/block/ create sbd_disk /dev/nvme0n3
# 创建后端块存储:命名sbd_disk,使用本机分区 /dev/nvme0n3
/> /iscsi/iqn.2026-08.com.example:mfsdata/tpg1/luns create /backstores/block/sbd_disk
# 创建iSCSI目标,把上面的sbd_disk映射成LUN对外共享
/> exit

登出再登录,清理旧会话、重新挂载识别共享磁盘
bash
[root@server1 ~]# iscsiadm -m node -T iqn.2026-08.com.example:mfsdata -p 192.168.40.175 --logout
[root@server1 ~]# iscsiadm -m discovery -t st -p 192.168.40.175
[root@server1 ~]# iscsiadm -m node -T iqn.2026-08.com.example:mfsdata -p 192.168.40.175:3260 --login
[root@server1 ~]# lsblk
server3 操作相同
在server1叫 sdb

server3叫 sdc

出现这样情况的原因是两台机器共用一条 ACL,后续机器重启会产生大量报错,虽不影响系统功能,但为避免这种情况,两台机器需不同的 ACL,同样可参考6.2.4
bash
[root@server1 ~]# ls -l /dev/disk/by-id/ | grep "sdb$"

bash
[root@server3 ~]# ls -l /dev/disk/by-id/ | grep "sdc$"

第二条和第四条 by-id 相同,说明是同一块共享磁盘,这样就已经准备好了
方法二
在存放虚拟机文件的同级目录下创建一个空文件夹,用于存放新建的磁盘

找到此地址并复制

以管理员身份运行cmd

创建磁盘

文件夹里出现

在server1和server3都执行以下操作添加磁盘,但注意,虚拟机的快照必须全部删除







找到虚拟机的.vmx文件,用记事本打开

添加以下配置
bash
disk.locking = "FALSE"
disk.EnableUUID = "TRUE"
scsi1.sharedBus = "virtual"
scsi1:0.mode = "independent-persistent"
scsi1:0.present = "TRUE"
# 以上必须添加,以下做优化
# disk.locking="FALSE":关闭 VMware 磁盘锁,允许多台虚机同时打开同一块 vmdk;不加会报磁盘被占用
# disk.EnableUUID="TRUE":让 Linux 识别磁盘 UUID,SBD、udev 依赖
# scsi1.sharedBus="virtual":SCSI 总线共享,多虚机共享该 SCSI 总线
diskLib.dataCacheMaxSize = "0"
diskLib.dataCacheMaxReadAheadSize = "0"
diskLib.DataCacheMinReadAheadSize = "0"
diskLib.dataCachePageSize = "4096"
diskLib.maxUnsyncedWrites = "0"
保存退出,用 lsblk 指令即可看到这块磁盘
为防止漂移,还是推荐用 by-id
SBD 直接使用整块裸设备,不用分区和格式化
此种方式也建议添加两条 ACL,详见6.2.4
6.2.2 部署
在两台节点均安装
bash
yum install -y sbd fence-agents-sbd
加载 softdog 软件看门狗,出现/dev/watchdog即为成功
bash
[root@server1 ~]# modprobe softdog
[root@server1 ~]# echo "softdog" >> /etc/modules-load.d/softdog.conf
[root@server1 ~]# ls -l /dev/watchdog

bash
[root@server3 ~]# modprobe softdog
[root@server3 ~]# echo "softdog" >> /etc/modules-load.d/softdog.conf
[root@server3 ~]# ls -l /dev/watchdog

初始化 SBD,仅在一个节点执行,使用 by-id 稳定路径,防止盘符漂移
bash
[root@server1 ~]# sbd -d /dev/disk/by-id/wwn-0x600140570774c2ab6b94304b73c85aeb create

为集群节点分配专属心跳槽位,仅在一个节点执行
bash
[root@server1 ~]# sbd -d /dev/disk/by-id/wwn-0x600140570774c2ab6b94304b73c85aeb allocate server1
[root@server1 ~]# sbd -d /dev/disk/by-id/wwn-0x600140570774c2ab6b94304b73c85aeb allocate server3

查看槽位分配结果,输出两个节点,状态均为 clear,表示槽位空闲、状态正常
bash
[root@server1 ~]# sbd -d /dev/disk/by-id/wwn-0x600140570774c2ab6b94304b73c85aeb list

配置 SBD 主配置文件,两个节点均执行
bash
[root@server1 ~]# vim /etc/sysconfig/sbd


启动 SBD 服务并验证,两个节点均执行
bash
[root@server1 ~]# systemctl enable sbd
[root@server1 ~]# systemctl restart corosync pacemaker
[root@server1 ~]# systemctl status sbd


集成 Pacemaker 集群,开启 STONITH 隔离,仅在一个节点执行
bash
[root@server1 ~]# pcs stonith create sbd-stonith fence_sbd pcmk_host_list="server1 server3"
# 创建 SBD 隔离资源
[root@server1 ~]# pcs property set stonith-enabled=true
# 开启集群隔离开关
[root@server1 ~]# pcs status

集群状态正常,配置成功
6.2.3 测试与排错
在备节点隔离主节点,命令返回 Node: server3 fenced 表示隔离指令已成功下发
bash
[root@server1 ~]# pcs stonith fence server3

主节点 SSH 连接随即断开,系统开始强制重启

预期结果
server3 先变为 OFFLINE,重启完成后自动恢复为 Online;业务资源组整体漂移到 server1,VIP、共享磁盘、业务服务依次启动,全部为 Started 状态,Failed Resource Actions 区域为空,无业务启动失败记录

节点状态正常,但资源状态不正常,server1的 mfsmaster 启动失败,且在server3 重启后,资源会自动漂移回server3

隔离操作历史正常

显示元数据加载失败

在server1和3上编辑/usr/lib/systemd/system/moosefs-master.service文件
-a = auto-recover 自动元数据恢复
bash
[root@server1 ~]# vim /usr/lib/systemd/system/moosefs-master.service
[root@server1 ~]# systemctl daemon-reload

server1 查看 mfsmaster 旧进程残留并清除
bash
[root@server1 ~]# ss -tulnp | grep 9419
[root@server1 ~]# kill -9 <pid>
清除失败记录
bash
[root@server1 ~]# pcs resource cleanup mfsmaster
[root@server1 ~]# pcs resource cleanup mfsdata
查看集群状态
bash
[root@server1 ~]# pcs status

手动测试,move 资源到 server1,服务恢复正常
bash
[root@server1 ~]# pcs resource move mfsmaster server1

清除 pcs resource move 产生的临时位置约束,不再强制把 mfsmaster 绑定在某个节点上,资源恢复自动故障转移能力
bash
[root@server1 ~]# pcs resource clear mfsmaster
重新测试,在 server3 隔离 server1
bash
[root@server3 ~]# pcs stonith fence server1

server1重启
在server3查看集群状态,资源全部迁移到server3,server1下线

server1重启之后上线,资源不会回迁到server1

查看隔离操作历史,正常

6.2.4 补充
由于我的两个 master 用的同一条 ACL,虚拟机重启之后,会出现大量iscsi连接报错

需要为两个节点各自独立添加自己唯一的 Initiator IQN 到 ACL 白名单
由于当前资源在server1,在 target 的 ACL 白名单里新增一条,放行 server3 的独立 IQN

修改 initiator IQN 后重建 iscsi 会话
bash
[root@server3 ~]# iscsiadm -m node -u
[root@server3 ~]# iscsiadm -m node -o delete
[root@server3 ~]# vim /etc/iscsi/initiatorname.iscsi

bash
[root@server3 ~]# systemctl restart iscsid
[root@server3 ~]# iscsiadm -m discovery -t st -p 192.168.40.175
[root@server3 ~]# iscsiadm -m node -l
[root@server3 ~]# lsblk
刚添加磁盘时,在server3被识别为sdc,现重新识别为sdb

再次测试,隔离server1,重启时没有报错
