4、NFS服务搭建:在Linux上部署NFS Server、配置exports、防火墙与权限设置

说到Kubernetes的持久化存储,NFS绝对是个老朋友了。虽然现在有各种分布式存储方案,但NFS在实验室环境、小规模集群中依然很能打。特别是我们要跑vLLM模型推理,模型文件动不动几十G,用NFS共享给多个节点,是最省事的方案。

我个人习惯在Ubuntu 22.04上部署NFS Server。当然CentOS也差不多,就是包管理器换成yum。嗯,这里要注意,生产环境我建议用CentOS Stream或者RHEL,稳定性更好。

4.1 安装NFS Server

先更新包索引,然后安装nfs-kernel-server。这个包包含了NFS服务端的所有组件。

# Ubuntu/Debian
sudo apt update
sudo apt install nfs-kernel-server -y

# CentOS/RHEL
sudo yum install nfs-utils -y
sudo systemctl enable nfs-server
sudo systemctl start nfs-server

安装完成后,检查一下服务状态:

sudo systemctl status nfs-server

看到 active (running) 就对了。我记得有一次在CentOS 7上装完发现服务没起来,排查了半天,原来是rpcbind没启动。所以这里提醒一下,NFS依赖rpcbind,务必确保它也在运行。

4.2 创建共享目录

我们要给vLLM模型文件准备一个专门的目录。我个人习惯把共享数据放在 /data 下,结构清晰。

sudo mkdir -p /data/vllm-models
sudo chown nobody:nogroup /data/vllm-models
sudo chmod 755 /data/vllm-models

为什么用nobody?因为NFS默认的匿名用户映射就是nobody。你想想看,如果多个Kubernetes节点上的Pod用不同的UID访问,权限会乱成一锅粥。用nobody统一映射,省心。

4.3 配置exports文件

这是NFS的核心配置文件。说白了,就是告诉NFS:哪些目录可以共享,共享给谁,有什么权限。

sudo vim /etc/exports

添加以下内容:

/data/vllm-models 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

我来解释一下这几个参数:

参数 说明
rw 读写权限。如果只读,用ro
sync 同步写入。数据写完才返回,安全但慢一点
no_subtree_check 禁用子树检查。提升性能,我一般都会加上
no_root_squash 允许root用户保留权限。Kubernetes Pod有时需要root权限写文件
⚠️ 注意: no_root_squash 有安全风险。如果客户端被攻破,攻击者可以以root身份操作服务端文件。在可信网络内使用没问题,但别暴露到公网。

配置完以后,执行以下命令生效:

sudo exportfs -a
sudo systemctl restart nfs-server

检查共享是否成功:

sudo showmount -e localhost

输出应该类似:

Export list for localhost:
/data/vllm-models 192.168.1.0/24

4.4 防火墙设置

NFS依赖多个端口。除了2049这个主端口,还有rpcbind的111端口,以及mountd、lockd等动态端口。我曾经在项目中遇到过,防火墙没配好,客户端挂载时一直卡住,超时后才报错。

最稳妥的做法是直接放行NFS服务:

# Ubuntu (ufw)
sudo ufw allow from 192.168.1.0/24 to any port nfs
sudo ufw allow from 192.168.1.0/24 to any port 111
sudo ufw reload

# CentOS (firewalld)
sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.1.0/24
sudo firewall-cmd --permanent --zone=trusted --add-service=nfs
sudo firewall-cmd --permanent --zone=trusted --add-service=rpc-bind
sudo firewall-cmd --reload

如果你用的是云服务器,记得在安全组里也放行这些端口。嗯,这里要注意,有些云厂商的安全组规则不支持端口范围,那就得把NFS的端口固定下来。

固定NFS端口的方法:

# 编辑 /etc/nfs.conf
sudo vim /etc/nfs.conf

# 找到 [nfsd] 部分,添加:
[nfsd]
port=2049

# 找到 [mountd] 部分,添加:
[mountd]
port=20048

# 重启服务
sudo systemctl restart nfs-server

这样mountd就固定在了20048端口,防火墙规则就好写了。

4.5 权限设置详解

权限问题,是NFS使用中最容易踩坑的地方。我见过太多人挂载成功但读写失败,最后发现是权限没配好。

核心原则:服务端和客户端的UID/GID必须一致。或者用匿名映射。

对于vLLM模型文件,我建议这样设置:

# 在服务端创建专用用户
sudo useradd -r -s /sbin/nologin vllm
sudo chown -R vllm:vllm /data/vllm-models
sudo chmod 755 /data/vllm-models

然后在所有Kubernetes节点上创建相同UID的用户:

sudo useradd -r -u 999 -s /sbin/nologin vllm

这样Pod以UID 999运行时,就能正常读写NFS共享目录了。

💡 小技巧: 如果不想在每个节点创建用户,可以在Pod的securityContext里指定runAsUser。但要注意,NFS服务端必须有对应的UID权限。

4.6 客户端挂载测试

在任意一台Kubernetes节点上测试挂载:

# 安装nfs客户端
sudo apt install nfs-common -y

# 创建挂载点
sudo mkdir -p /mnt/vllm-models

# 挂载
sudo mount -t nfs 192.168.1.100:/data/vllm-models /mnt/vllm-models

# 验证
df -h | grep vllm
ls -la /mnt/vllm-models

如果一切正常,你就能看到共享目录的内容了。测试读写:

# 写测试
echo "hello vllm" | sudo tee /mnt/vllm-models/test.txt

# 读测试
cat /mnt/vllm-models/test.txt

# 清理
sudo rm /mnt/vllm-models/test.txt

读写都没问题的话,就可以配置开机自动挂载了:

echo "192.168.1.100:/data/vllm-models /mnt/vllm-models nfs defaults 0 0" | sudo tee -a /etc/fstab

4.7 性能调优建议

vLLM模型文件比较大,NFS的性能直接影响模型加载速度。我分享几个调优参数:

参数 推荐值 说明
rsize/wsize 1048576 (1MB) 读写块大小,越大吞吐越高
noatime 启用 不更新访问时间,减少IO
hard 启用 硬挂载,NFS服务重启后自动重连
intr 启用 允许中断挂起的NFS操作

挂载时加上这些参数:

sudo mount -t nfs -o rsize=1048576,wsize=1048576,noatime,hard,intr 192.168.1.100:/data/vllm-models /mnt/vllm-models
📌 核心要点:
  • NFS Server安装后务必检查rpcbind服务
  • exports配置中no_root_squash要谨慎使用
  • 防火墙放行NFS相关端口(2049、111、mountd)
  • 权限问题:服务端和客户端UID保持一致
  • 性能调优:增大rsize/wsize,启用noatime

好了,NFS服务端就搭好了。接下来我们就可以在Kubernetes里创建PV和PVC,让Pod用上这个共享存储了。

NFS服务搭建核心流程 ① 安装NFS Server nfs-kernel-server ② 创建共享目录 /data/vllm-models ③ 配置exports rw,sync,no_root_squash ④ 防火墙设置 放行2049/111端口 ⑤ 权限设置 UID映射/匿名用户 ⑥ 客户端挂载 mount -t nfs ⑦ 性能调优与验证 rsize/wsize/noatime/hard 完整流程:安装 → 目录 → 配置 → 防火墙 → 权限 → 挂载 → 调优
专注资料整理