找回密码
 立即注册
首页 业界区 业界 容器云后端存储NFS高可用适配

容器云后端存储NFS高可用适配

强怀梅 2025-8-22 15:24:05
容器云后端存储NFS高可用适配方案

1. 背景及痛点

​                经规划数据中心生产环境各大生产业务系统将全部迁移至长沙,为提高数据安全性,在存储架构上首先应该保障高可用,并做备份方案!但是容器云KubeGien本身自带的存储方案 NFS,是不具备高可用性的,这受限于NFS本身的单点架构特点,因此准备做此次适配。
2. 方案选型

方案数据同步VIP 漂移DRBD 主备切换是否自动故障转移风险NFS + DRBD + Keepalived✅ 自动✅ 自动❌ 需手动❌ 手动干预Split-brain 风险低NFS + DRBD + Pacemaker/Corosync✅ 自动✅ 自动✅ 自动✅ 全自动如果没配 STONITH,split-brain 风险高分布式存储(CephFS/GlusterFS/XSKY)✅ 自动多副本✅ VIP/原生访问无需切换✅ 天生高可用成本高,架构复杂目前,已经做了XSKY的适配和测试,但是由于内部环境的一些限制,XSKY暂时还不满足现状,所以选用NFS+DRBD+Pacemaker/Corosync的方案,前期为了低风险,防止出现 Split-Brain(脑裂),暂时不启用Pacemaker/Corosync,选用NFS + DRBD + Keepalived架构方案。
3. 架构概览

3.1 架构原理


  • 两台服务器通过 DRBD块级别同步(主从),同步模式选 Protocol C(同步写),保证数据写入安全。
  • 两台机器运行 NFS 服务,只有主节点对外提供 NFS(通过 Keepalived 提供 VIP),主节点挂了时 VIP 漂移到备节点并把 DRBD 切换为主,从而继续提供 NFS。
  • Kubernetes 指向 VIP 挂载 NFS(StorageClass / PersistentVolume 的 server 使用 VIP)。
优点:实现近实时(同步)数据一致性、主节点故障后自动切换;对现有 NFS 工作负载透明。

  • Pacemaker/Corosync: 集群管理软件。负责:

    • 监控两台服务器的健康状态(心跳)。
    • 管理一个虚拟IP(VIP),客户端只连接这个IP。
    • 提升DRBD资源为主(Primary)或降为备(Secondary)。
    • 挂载DRBD设备(现在是/dev/drbd0)到目录(如/nfs_share)。
    • 启动和停止NFS服务。

3.2 数据流向


  • 客户端通过 VIP 写入数据到 主节点 的NFS服务。
  • 主节点的NFS服务将数据写入它挂载的目录 /nfs_share。
  • /nfs_share 对应着块设备 /dev/drbd0。
  • DRBD 立即将写入 /dev/drbd0 的块数据,通过网络同步到备节点的 /dev/drbd0 设备上。
  • 至此,数据已经安全地存在了两台服务器的硬盘上。
3.3 故障切换(Failover)

在加入Pacemaker/Corosync集群前,采用人工切换方式,大概1-2分钟,具体切换方案这里不再赘述!
加入Pacemaker/Corosync集群后:

  • 主节点宕机后, Pacemaker 会检测到。
  • 在备节点上执行以下操作:
    a. 将备节点的 DRBD 设备提升为 主(Primary)
    b. 将 DRBD 设备挂载到 /nfs_share。
    c. 启动 NFS 服务。
    d. 将 VIP 绑定到备节点的网卡上。
  • 客户端重连 VIP,服务恢复。整个过程数据零丢失(因为是同步复制)。
4. 方案落地

4.1 环境准备

假设我们有两台服务器,保证时钟同步(建议 chrony/ntp):

  • nfs-node1: 10.62.107.14
  • nfs-node2:  10.62.107.15
  • 虚拟IP (VIP):  10.62.107.16
  • 共享数据目录: /nfs_share
  • DRBD 资源名: nfs_res
  • DRBD 使用的磁盘: 两台服务器上各有一块未使用的磁盘 /dev/sdb
  • 双向网络连通、无防火墙阻挡(drbd 使用 7789、keepalived 使用 VRRP 协议 112;NFS 视版本开放相应端口)
4.2 部署安装

在两台主机上执行(替换 yum -> dnf 若为 Rocky8/centos8):
  1. # 启用 EPEL
  2. sudo yum install -y epel-release
  3. # 安装 drbd-utils/drbd kernel module 以及 nfs + keepalived
  4. sudo yum install -y drbd-utils kmod-drbd nfs-utils keepalived   # 如在现有容器云操作nfs已安装则不需要再安装nfs-utils
  5. # 开启并启用必要服务(先手动启动配置)
  6. sudo systemctl enable --now nfs-server
  7. sudo # 等 drbd 同步完成(watch cat /proc/drbd 同步状态)
  8. sudo mkfs.xfs -f /dev/drbd0          # 或 ext4: mkfs.ext4 /dev/drbd0
  9. sudo mkdir -p /srv/nfs/share
  10. sudo mount /dev/drbd0 /srv/nfs/share
  11. # 可加入 /etc/fstab 持久挂载(use _netdev? 但 DRBD 管理下慎放)
  12. echo '/dev/drbd0 /srv/nfs/share xfs defaults 0 0' | sudo tee -a /etc/fstab
  13. # drbd module 会随 drbdadm 操作加载
  14. ## 验证
  15. drbdadm --version
  16. cat /proc/drbd
  17. ------------------------------------------------------------------------------------------------------
  18. # 针对 银河麒麟这样的国产化机器,可能无法加载epel-release,也下载不了drbd-utils 用户态工具,则可以按照下面的方法:
  19. #1. 一般都内置 DRBD 模块,开启即可
  20. modprobe drbd
  21. lsmod | grep drbd
  22. #2 源码安装drbd-utils 和 kmod-drbd
  23. # 2.1 安装编译工具
  24. yum groupinstall -y "Development Tools"
  25. yum install -y gcc gcc-c++ make automake autoconf libtool flex bison kernel-devel-$(uname -r) kernel-headers-$(uname -r)
  26. # 2.2 获取源码
  27. git clone https://github.com/LINBIT/drbd-utils.git
  28. cd drbd-utils
  29. ./autogen.sh
  30. ./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc --without-manual
  31. make
  32. make install
  33. # DRBD 内核模块如果系统没有,需要从 drbd 仓库编译:
  34. git clone https://github.com/LINBIT/drbd.git
  35. cd drbd
  36. make KDIR=/lib/modules/$(uname -r)/build
  37. make install
  38. ## 验证
  39. drbdadm --version
  40. cat /proc/drbd
复制代码
4.3 配置 DRBD (在两台节点上执行)


  • 磁盘及分区准备:
  1. # 清理分区表(谨慎)
  2. sudo sgdisk --zap-all /dev/sdb
  3. # 创建一个 single partition covering whole disk (example)
  4. /sbin/parted -s /dev/sdb mklabel gpt mkpart primary 1MiB 100%
  5. # 使用 /dev/sdb1 作为后端,或直接用 /dev/sdb
复制代码

  • 创建 DRBD 配置文件 /etc/drbd.d/nfs_res.res
在两台节点上创建 /etc/drbd.d/nfs_res.res(注意:resource name 与 device/hosts):
  1. cat > /etc/drbd.d/nfs_res.res << EOF
  2. resource nfs_res {
  3.     protocol C;  # 使用同步协议,确保数据强一致性
  4. #    startup {
  5. #        become-primary-on both;
  6. #    }
  7. #    disk {
  8. #        on-io-error detach;
  9. #    }
  10. #    net {
  11. #        cram-hmac-alg "sha1";
  12. #        shared-secret "my-secret-key"; # 设置一个密钥用于通信验证
  13. #        after-sb-0pri discard-zero-changes;
  14. #        after-sb-1pri discard-secondary;
  15. #        after-sb-2pri disconnect;
  16. #    }
  17.     on kubegien-arm-02 {
  18.         device    /dev/drbd0;
  19.         disk      /dev/vdb1;
  20.         address   10.62.107.14:7788;
  21.         meta-disk internal;
  22.     }
  23.     on kubegien-arm-03 {
  24.         device    /dev/drbd0;
  25.         disk      /dev/vdb1;
  26.         address   10.62.107.15:7788;
  27.         meta-disk internal;
  28.     }
  29. }
  30. EOF
复制代码
加权限:
  1. # 创建资源元数据
  2. drbdadm create-md nfs_res
  3. # 启用资源
  4. drbdadm up nfs_res
  5. # 在主节点上强制把数据覆盖到备(首次初始化仅在确认主节点数据为准时使用)
  6. drbdadm -- --overwrite-data-of-peer primary nfs_res
复制代码
8.2 主节点配置 /etc/keepalived/keepalived.conf
重要:把 interface eth0 改为实际网卡名。
两台机器的 virtual_router_id 必须一致(如 51),auth_pass 一致。
主节点优先级高(如 150),备节点低(如 100)。
示例(nfs-node1 主机,priority 150):
  1. # 在 nfs-node1 上执行
  2. drbdadm primary nfs_res --force
复制代码
8.3 备节点配置 /etc/keepalived/keepalived.conf
在nfs-node2(备)上 state BACKUP,priority 100。virtual_router_id 保持一致。
check_nfs.sh 示例(放 /usr/local/bin/check_nfs.sh,确保可执行):
  1. watch -n 1 'drbdadm status nfs_res'
  2. # 或
  3. cat /proc/drbd
复制代码
启动 Keepalived:
  1. # 等 drbd 同步完成(watch cat /proc/drbd 同步状态)
  2. sudo mkfs.xfs -f /dev/drbd0          # 或 ext4: mkfs.ext4 /dev/drbd0
  3. sudo mkdir -p /srv/nfs/share
  4. sudo mount /dev/drbd0 /srv/nfs/share
  5. # 可加入 /etc/fstab 持久挂载(use _netdev? 但 DRBD 管理下慎放)
  6. echo '/dev/drbd0 /srv/nfs/share xfs defaults 0 0' | sudo tee -a /etc/fstab
复制代码
检查 VIP 是否在主机上(ip addr)并能被其他机器 ping 通。
  1. /srv/nfs/share 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)
复制代码

  • 在主节点应该能看到 VIP 10.62.107.200
  • 停止主节点 systemctl stop nfs-server,VIP 应该漂移到备节点
  • 恢复主节点 systemctl start nfs-server,VIP 会回切
4.4 首次同步与切换验证


  • 主nfs节点创建测试文件:
  1. sudo exportfs -ra
  2. sudo systemctl restart nfs-server
复制代码

  • 在备机上查看(在备机如果未挂载 /dev/drbd0 为 Secondary,它 不能 直接 mount 为读写。可临时把它切换为 Primary 来检查数据,或使用 drbdadm role 查看状态)。但可以使用 drbd-tools 命令查看同步状态。
  • 测试 VIP 漂移:


  • 模拟主节点失败:sudo systemctl stop keepalived nfs-server 或断网。
  • 备机应接管 VIP:ip addr on nfs-b shows VIP.
  • 在备机上把 DRBD 升为 PRIMARY(如果自动没有切换):
手动操作指南
  1. #!/bin/bash
  2. # 检查 DRBD + NFS 状态 (CSI NFS 场景)
  3. # 只有 Primary 且内核 nfsd 线程存在时返回 0
  4. # 1. 检查 DRBD 是否是 Primary
  5. if ! grep -q 'ro:Primary' /proc/drbd; then
  6.     exit 1
  7. fi
  8. # 2. 检查 NFS 内核线程是否存在
  9. if ! ps -ef | grep -q "[n]fsd"; then
  10.     exit 1
  11. fi
  12. # 3. 可选:确认导出目录是否存在
  13. if ! exportfs -v 2>/dev/null | grep -q '/YuanQiNFS'; then
  14.     exit 1
  15. fi
  16. exit 0
复制代码
建议通过 Keepalived 的健康脚本在主故障时自动让备机提升为 Primary。但自动提升有风险(可能导致 split-brain)——务必确保网络隔离场景有明确策略。
5. 容器云集成

Kubernetes 中所有 NFS PersistentVolumes / StorageClass 的 server 字段改为 VIP xxx
6. 扩展---  Pacemaker/Corosync 集群管理

配置 Pacemaker/Corosync 集群


  • 启动并启用 pcsd 服务 (在两台节点上执行)
    1. chmod +x /usr/local/bin/check_nfs.sh
    复制代码
  • 在其中一个节点上完成集群认证和初始化
    1. ! Configuration for Keepalived (NFS + DRBD)
    2. global_defs {
    3.     router_id NFS_HA
    4. }
    5. vrrp_script chk_nfs {
    6.     script "/usr/local/bin/check_nfs.sh"
    7.     interval 2
    8.     weight -20
    9.     fall 3
    10.     rise 2
    11. }
    12. vrrp_instance VI_NFS {
    13.     state MASTER
    14.     interface eth0              # 替换为实际网卡名
    15.     virtual_router_id 51
    16.     priority 150                # 主节点优先级高
    17.     advert_int 1
    18.     authentication {
    19.         auth_type PASS
    20.         auth_pass nfsdrbd
    21.     }
    22.     virtual_ipaddress {
    23.         10.62.107.200/24        # 设置 VIP,必须在 NFS 网络段内
    24.     }
    25.     track_script {
    26.         chk_nfs
    27.     }
    28. }
    复制代码
  • 禁用无关服务并设置集群属性
    1. global_defs {
    2.     router_id NFS_HA
    3. }
    4. vrrp_script chk_nfs {
    5.     script "/usr/local/bin/check_nfs.sh"
    6.     interval 2
    7.     weight -20
    8.     fall 3
    9.     rise 2
    10. }
    11. vrrp_instance VI_NFS {
    12.     state BACKUP
    13.     interface eth0
    14.     virtual_router_id 51
    15.     priority 100                # 比主节点低
    16.     advert_int 1
    17.     authentication {
    18.         auth_type PASS
    19.         auth_pass nfsdrbd
    20.     }
    21.     virtual_ipaddress {
    22.         10.62.107.200/24
    23.     }
    24.     track_script {
    25.         chk_nfs
    26.     }
    27. }
    复制代码
第四步:创建 Pacemaker 集群资源

非常重要:以下所有 pcs 命令只需在其中一个节点(如 nfs-node1)上执行一次即可。

  • 创建 DRBD 资源
    1. systemctl enable --now keepalived
    复制代码
  • 创建 DRBD 主从Promotion约束
    1. ip addr show  enp1s0 | grep VIP
    复制代码
  • 创建文件系统资源(用于格式化并挂载DRBD设备)
    1. echo "hello from a" | sudo tee /YuanQiNFS/hello_a.txt
    复制代码
  • 创建虚拟IP(VIP)资源
    1. # 在备机上  手动操作指南:
    2. sudo drbdadm primary --force nfs_res
    3. sudo mount /dev/drbd0 /YuanQiNFS    # 备机现在可以挂载并提供 NFS
    4. sudo systemctl start nfs-server
    复制代码
  • 创建NFS服务资源
    1. systemctl start pcsd
    2. systemctl enable pcsd
    复制代码
第五步:验证和测试


  • 检查集群状态
    1. # 1. 先设置集群用户密码 (在两台节点上设置相同的密码)
    2. echo 'hacluster:your_secure_password' | chpasswd
    3. # 2. 在 nfs-node1 上执行
    4. pcs cluster auth nfs-node1 nfs-node2 -u hacluster -p 'your_secure_password' --force
    5. pcs cluster setup --name nfs_cluster nfs-node1 nfs-node2 --force
    6. pcs cluster start --all
    7. pcs cluster enable --all
    复制代码
    你应该看到所有资源都在一个节点(如 nfs-node1)上正常运行 (Started)。
  • 在客户端挂载测试
    在另一台Linux客户端上:
    1. pcs property set stonith-enabled=false # 没有STONITH设备先禁用
    2. pcs property set no-quorum-policy=ignore # 两节点集群需要忽略quorum
    复制代码
  • 模拟故障转移测试 (非常重要!)

    • 方法A:手动切换
      1. pcs resource move drbd_clone nfs-node2# 查看 # 1. 先设置集群用户密码 (在两台节点上设置相同的密码)
      2. echo 'hacluster:your_secure_password' | chpasswd
      3. # 2. 在 nfs-node1 上执行
      4. pcs cluster auth nfs-node1 nfs-node2 -u hacluster -p 'your_secure_password' --force
      5. pcs cluster setup --name nfs_cluster nfs-node1 nfs-node2 --force
      6. pcs cluster start --all
      7. pcs cluster enable --all,等待所有资源都切换到 nfs-node2 上# 在客户端检查文件是否还在,是否可以继续写入
      复制代码
    • 方法B:暴力测试
      直接在 nfs-node1 上执行 reboot 或 echo c > /proc/sysrq-trigger (触发内核崩溃)。然后观察集群状态,资源应该会自动转移到 nfs-node2 上。

故障排除常用命令


  • # 1. 先设置集群用户密码 (在两台节点上设置相同的密码)
    echo 'hacluster:your_secure_password' | chpasswd

    # 2. 在 nfs-node1 上执行
    pcs cluster auth nfs-node1 nfs-node2 -u hacluster -p 'your_secure_password' --force
    pcs cluster setup --name nfs_cluster nfs-node1 nfs-node2 --force
    pcs cluster start --all
    pcs cluster enable --all - 查看集群整体状态
  • pcs resource debug-start  - 尝试手动启动一个资源并输出详细日志
  • drbdadm status  - 查看DRBD状态
  • journalctl -xe - 查看系统日志
  • pcs constraint - 查看所有约束
  • mount | grep drbd - 检查DRBD设备是否已挂载

来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册