NFS双机热备高可用环境
一、 架构概述与设计目标
1.1 设计目标
- **高可用 (HA)**:通过 Keepalived 实现 NFS 服务的 VIP (Virtual IP) 漂移,当主节点故障时,备用节点自动接管服务,客户端无感知。
- 数据同步:通过 Rsync + Inotify 实现主备节点间共享数据的实时单向同步,确保备用节点上的数据与主节点一致。
- 服务监控:Keepalived 监控 NFS 服务进程,异常时尝试重启,重启失败则主动放弃 VIP,触发故障转移。
1.2 核心组件与架构
- NFS Server (主/备):提供实际的共享存储服务。
- Keepalived:提供 VIP (
172.16.60.244) 并监控 NFS 服务健康状态。 - Rsync + Inotify:实现主备节点
/data/k8s_storage目录的数据同步。 - **客户端 (K8s Nodes)**:通过 VIP 挂载 NFS,不感知后端物理服务器切换。

二、 环境准备
2.1 服务器规划
| 角色 | 主机名 | IP 地址 | 备注 |
|---|---|---|---|
| NFS Master | nfs-master | 172.16.60.235 | 初始 VIP 持有者 |
| NFS Slave | nfs-slave | 172.16.60.236 | 备用节点 |
| 虚拟 IP (VIP) | - | 172.16.60.244 | 供 K8s 集群挂载的地址 |
技术要求:
- 两台 NFS 节点服务器配置应尽可能一致。
- 建议为 NFS 共享目录 (
/data/k8s_storage) 使用独立的硬盘或分区。
2.2 基础系统配置
在两台节点服务器上执行:
1 | # 1. 关闭防火墙 |
三、 部署 NFS 服务 (主备节点相同操作)
3.1 安装与配置
1 | # 1. 安装 NFS 软件包 |
3.2 验证 NFS 服务
1 | # 查看本机 NFS 导出列表 |
四、 配置 Keepalived 实现高可用
核心要点:配置为**非抢占模式 (nopreempt)**,避免 VIP 在节点恢复后频繁来回切换,可能导致数据不一致。
4.1 安装 Keepalived
在两台节点上执行:
1 | yum install -y keepalived |
4.2 配置 Keepalived (主备差异)
- Master 节点 (
/etc/keepalived/keepalived.conf):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27! Configuration File for keepalived
global_defs {
router_id nfs_master
}
vrrp_script chk_nfs {
script "/etc/keepalived/nfs_check.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state BACKUP # 初始状态都设为 BACKUP
interface eth0
virtual_router_id 51
priority 100 # Master 优先级更高
advert_int 1
nopreempt # 关键:非抢占模式
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nfs
}
virtual_ipaddress {
172.16.60.244/24
}
} - Slave 节点:配置文件与 Master 几乎相同,仅需修改两处:
1
2
3
4
5
6
7
8
9global_defs {
router_id nfs_slave # 修改 router_id
}
...
vrrp_instance VI_1 {
...
priority 80 # 降低优先级
...
}
4.3 创建 NFS 健康检查脚本
在两台节点上创建 /etc/keepalived/nfs_check.sh:
1 |
|
赋予执行权限:chmod +x /etc/keepalived/nfs_check.sh
4.4 启动与验证 Keepalived
1 | systemctl enable --now keepalived |
故障转移测试:
- 在持有 VIP 的 Master 节点上停止 keepalived:
systemctl stop keepalived。 - 观察 VIP 是否漂移到 Slave 节点 (
ip addr命令)。 - 注意:由于是非抢占模式,当原 Master 节点恢复后,VIP 不会自动漂回。
五、 配置 Rsync + Inotify 实现数据同步
核心逻辑:只有当前持有 VIP 的节点,才启动 inotifywait 监控进程,将数据同步到对端。 避免双向同步导致数据循环和冲突。
5.1 安装软件包
在两台节点上执行:
1 | yum install -y rsync inotify-tools |
5.2 配置 Rsync 服务端
- Master 节点 (
/etc/rsyncd.conf):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21uid = root
gid = root
use chroot = 0
port = 873
hosts allow = 172.16.60.0/24
max connections = 0
timeout = 300
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
log format = %t %a %m %f %b
transfer logging = yes
[master_web]
path = /data/k8s_storage
comment = master_web
ignore errors
read only = no
list = no
auth users = rsync
secrets file = /etc/rsyncd.passwd - Slave 节点:配置与 Master 基本相同,仅修改模块名:
1
2
3[slave_web] # 修改此处
path = /data/k8s_storage
...
5.3 配置 Rsync 认证
在两台节点上创建密码文件:
1 | # 1. 服务端密码文件 (`/etc/rsyncd.passwd`) |
5.4 启动 Rsync 服务
1 | systemctl enable --now rsyncd |
5.5 配置自动同步脚本 (核心)
原理:每个节点都运行一个监控脚本 (vip_monitor.sh),定期检查本机是否持有 VIP。如果持有,则启动数据同步进程 (rsync_inotify.sh) 同步到对端;如果不持有,则杀死本机的同步进程。
创建数据同步脚本 (
/opt/rsync_inotify.sh):- Master 节点内容 (同步到 Slave):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
host=172.16.60.236 # Slave IP
src=/data/k8s_storage/
des=slave_web # Slave 的 rsync 模块名
password=/opt/rsyncd.passwd
user=rsync
inotifywait=/usr/bin/inotifywait
$inotifywait -mrq --timefmt '%Y%m%d %H:%M' --format '%T %w%f%e' \
-e modify,delete,create,attrib $src \
| while read files; do
rsync -avzP --delete --timeout=100 --password-file=${password} $src $user@$host::$des
echo "${files} was rsynced" >> /tmp/rsync.log 2>&1
done - Slave 节点内容 (同步到 Master):只需修改
host和des变量为 Master 的信息。
- Master 节点内容 (同步到 Slave):
创建 VIP 监控脚本 (
/opt/vip_monitor.sh):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
VIP_NUM=`ip addr | grep 244 | wc -l`
RSYNC_INOTIRY_NUM=`ps -ef | grep /usr/bin/inotifywait | grep -v grep | wc -l`
if [ ${VIP_NUM} -ne 0 ]; then
# 本机持有 VIP
if [ ${RSYNC_INOTIRY_NUM} -eq 0 ]; then
# 如果同步进程未启动,则启动它
nohup sh /opt/rsync_inotify.sh &
fi
else
# 本机不持有 VIP
if [ ${RSYNC_INOTIRY_NUM} -ne 0 ]; then
# 如果同步进程正在运行,则杀死它
pkill -f rsync_inotify.sh
pkill -f inotifywait
fi
fi创建持续运行脚本 (
/opt/rsync_monit.sh):1
2
3
4
5
6
while [ "1" = "1" ]
do
/bin/bash /opt/vip_monitor.sh > /dev/null 2>&1
sleep 5 # 每5秒检查一次VIP状态
done设置开机自启与启动:
1
2
3
4
5
6
7chmod +x /opt/*.sh
# 将以下内容添加到 /etc/rc.local (并确保 rc.local 有执行权限)
echo "nohup /bin/bash /opt/rsync_monit.sh &" >> /etc/rc.local
chmod +x /etc/rc.d/rc.local
# 立即启动
nohup /bin/bash /opt/rsync_monit.sh &
六、 最终验证与总结
6.1 功能验证
- VIP 漂移与数据同步:
- 在 VIP 当前所在节点 (如 Master) 的
/data/k8s_storage创建文件。 - 观察文件是否自动同步到对端节点。
- 停止当前节点的
keepalived,触发 VIP 漂移。 - 在新的 VIP 持有节点上创建文件,观察同步是否反向进行。
- 在 VIP 当前所在节点 (如 Master) 的
- NFS 服务故障:
- 在 VIP 持有节点上强制停止 NFS 服务 (
systemctl stop nfs-server)。 - 观察
nfs_check.sh脚本是否会重启 NFS,如果重启失败,VIP 是否漂移。
- 在 VIP 持有节点上强制停止 NFS 服务 (
6.2 部署到 Kubernetes
在 K8s 的 PersistentVolume (PV) 定义中,使用 VIP (172.16.60.244) 作为 NFS 服务器地址。这样,无论后端哪台物理服务器实际提供服务,K8s 集群都能持续访问存储。
6.3 关键注意事项
- 非抢占模式:是此架构稳定性的关键,避免脑裂和数据不一致。
- 单向同步:确保同一时刻只有一端向另一端同步数据。
- 网络与性能:主备节点间网络延迟会影响同步实时性。对于超大规模或IO密集型场景,需评估
rsync性能是否满足。 - 数据一致性:
rsync不是分布式文件系统,在主备切换瞬间,如果数据未完全同步,可能存在极小时间窗口的数据不一致风险。对于极高一致性要求场景,需考虑更高级的存储方案(如 Ceph/GlusterFS)。 - 安全:生产环境应使用更复杂的
rsync密码,并考虑使用 SSH 隧道加密同步流量。