news 2026/9/15 17:15:54

kubeasz 实战:NFS 服务器搭建与 Kubernetes 动态 PV 供应

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kubeasz 实战:NFS 服务器搭建与 Kubernetes 动态 PV 供应

kubeasz 实战:NFS 服务器搭建与 Kubernetes 动态 PV 供应

【免费下载链接】kubeasz使用Ansible脚本安装K8S集群,介绍组件交互原理,方便直接,不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz

NFS(Network File System)允许系统将本地目录和文件共享给网络上的其他主机,使远程用户和应用程序访问这些文件时如同访问本地文件一样。本文以 kubeasz 项目为背景,完整讲解 NFS 服务器的安装、/etc/exports共享目录配置、常用参数语义与客户端挂载方法,并进一步结合仓库中nfs-provisioner的部署模板与测试用例,演示如何将 NFS 作为 Kubernetes 的底层存储,通过 StorageClass 实现动态 PV 供应。读完本文,你将能够独立搭建 NFS 服务端、正确配置共享权限,并让集群应用通过 PVC 自动获得持久化存储。

NFS 核心概念与适用场景

NFS 基于 RPC 协议工作,服务端将目录“导出”(export),客户端通过挂载操作把远程目录接入本地文件系统。其典型价值在于:多个客户端(或 Kubernetes 中的多个 Pod)可以同时读写同一份数据,天然支持ReadWriteMany访问模式,非常适合作为日志采集、共享配置、中间件数据卷等场景的底层存储。

在 kubeasz 中,NFS 的定位是“集群存储的底层提供者”。仓库文档 08-cluster-storage.md 明确指出:Kubernetes 用 PV/PVC 抽象存储资源,而 NFS、iSCSI 等通过插件方式提供具体实现,nfs-provisioner(即 nfs-subdir-external-provisioner)可以在 NFS 目录上动态创建 PV。因此,搭建一个可用、权限正确的 NFS 服务器,是后续启用动态存储供应器的前提。

安装 NFS 服务端

Ubuntu / Debian 系

Ubuntu 16.04 及之后的 Debian 系发行版,使用以下命令安装 NFS 内核服务:

apt install nfs-kernel-server

安装完成后,/etc/exports是 NFS 服务端最核心的配置文件,负责定义哪些目录、以何种权限共享给哪些客户端。

CentOS / RHEL 系

CentOS 7 等红帽系发行版对应的服务端软件包为nfs-utils

yum install nfs-utils

说明:nfs-utils在红帽系中同时包含服务端与客户端组件,启动的服务名为nfs-server;Ubuntu 系服务端包为nfs-kernel-server,客户端则需单独安装nfs-common

配置 /etc/exports 共享目录

编辑/etc/exports文件,为每个需要共享的目录单独写一行,格式如下:

NFS共享目录路径 客户机IP或者名称(参数1,参数2,...,参数n)

示例:

/home *(ro,sync,insecure,no_root_squash) /share 192.168.1.0/24(rw,sync,insecure,no_subtree_check,no_root_squash)

第一个示例将/home共享给所有主机且只读;第二个示例将/share共享给192.168.1.0/24网段,允许读写并关闭子树检查与 root 压缩。

参数详解

| 参数 | 说明 | | :- | :- | | ro | 只读访问 | | rw | 读写访问 | | sync | 所有数据在请求时写入共享 | | async | nfs 在写入数据前可以响应请求 | | secure | nfs 通过 1024 以下的安全 TCP/IP 端口发送 | | insecure | nfs 通过 1024 以上的端口发送 | | wdelay | 如果多个用户要写入 nfs 目录,则归组写入(默认) | | no_wdelay | 如果多个用户要写入 nfs 目录,则立即写入;当使用 async 时无需此设置 | | hide | 在 nfs 共享目录中不共享其子目录 | | no_hide | 共享 nfs 目录的子目录 | | subtree_check | 如果共享 /usr/bin 之类的子目录时,强制 nfs 检查父目录的权限(默认) | | no_subtree_check | 不检查父目录权限 | | all_squash | 共享文件的 UID 和 GID 映射匿名用户 anonymous,适合公用目录 | | no_all_squash | 保留共享文件的 UID 和 GID(默认) | | root_squash | root 用户的所有请求映射成如 anonymous 用户一样的权限(默认) | | no_root_squash | root 用户具有根目录的完全管理访问权限 | | anonuid=xxx | 指定 nfs 服务器 /etc/passwd 文件中匿名用户的 UID | | anongid=xxx | 指定 nfs 服务器 /etc/passwd 文件中匿名用户的 GID |

与 Kubernetes 配合时的两个关键注意事项

  • 注 1:最小化授权客户端范围。尽量指定主机名、IP 或 IP 段,避免对全网开放共享。若在 k8s 集群中配合 nfs-client-provisioner 使用,这里需要指定Pod 的 IP 段,否则 nfs-client-provisioner Pod 无法启动,报错mount.nfs: access denied by server while mounting。这是因为 NFS 授权校验的是发起挂载请求的源地址,而 provisioner Pod 的 IP 属于集群 Pod 网段,若/etc/exports未放行该网段,挂载即被拒绝。
  • 注 2:insecure参数必须添加。经测试,缺少该参数会导致客户端挂载失败,同样报错mount.nfs: access denied by server while mounting。原因是 NFS 挂载请求可能来自 1024 以上的高位端口,而默认的secure模式只接受 1024 以下端口的请求。

配置修改完成后,可用exportfs -ra重新导出并检查语法,或重启服务使其生效。

启动 NFS 服务端

配置完成后,在终端执行以下命令启动服务:

systemctl start nfs-kernel-server.service

如需开机自启,追加systemctl enable nfs-kernel-server.service。红帽系对应为systemctl start nfs-server。验证导出是否生效可执行:

exportfs -v

客户端挂载 NFS 共享

安装客户端工具

Ubuntu 16.04 客户端需安装nfs-common包:

apt install nfs-common

CentOS 7 客户端需安装nfs-utils包:

yum install nfs-utils

使用 mount 命令临时挂载

使用mount命令挂载其他机器共享的 NFS 目录:

mount example.hostname.com:/ubuntu /local/ubuntu

注意:挂载点/local/ubuntu目录必须已经存在,且该目录中不能有文件或子目录,否则会被隐藏而无法访问。

写入 /etc/fstab 实现开机自动挂载

另一种常用方式是向/etc/fstab中添加一行,指明 NFS 服务器主机名、服务器导出的目录名以及本机挂载目录。常用语法如下:

example.hostname.com:/ubuntu /local/ubuntu nfs rsize=8192,wsize=8192,timeo=14,intr
  • rsize/wsize:客户端与服务端之间每次读写的数据块大小(字节);
  • timeo:请求超时重传前的等待时间(十分之一秒),此处为 1.4 秒;
  • intr:允许信号中断阻塞中的 NFS 操作,避免进程长期卡死。

在 kubeasz 中启用 nfs-provisioner 动态 PV

NFS 服务端就绪后,即可让 Kubernetes 集群基于它动态创建 PV。kubeasz 在cluster-addon角色中集成了 nfs-subdir-external-provisioner 的部署,相关模板位于 roles/cluster-addon/templates/nfs-provisioner/。

1. 修改集群配置文件

编辑clusters/${集群名}/config.yml,在 cluster-addon 角色段中启用 nfs-provisioner(仓库示例配置见 example/config.yml):

... 省略 # nfs-provisioner 自动安装 nfs_provisioner_install: "yes" # 修改为 yes 启用 nfs_provisioner_namespace: "kube-system" # provisioner 部署的命名空间 nfs_provisioner_ver: "v4.0.1" # nfs-subdir-external-provisioner 镜像版本 nfs_storage_class: "managed-nfs-storage" # 动态供应使用的 StorageClass 名称 nfs_server: "192.168.31.244" # 修改为实际 nfs server 地址 nfs_path: "/data/nfs" # 修改为实际的 nfs 共享目录

其中nfs_servernfs_path必须与/etc/exports中实际共享的目录一致,且该目录在/etc/exports中应已对 Pod 网段开放rw,sync,insecure权限。

2. 执行安装并验证

$ dk ezctl setup ${集群名} 07 # 执行成功后验证 $ kubectl get pod --all-namespaces | grep nfs-client kube-system nfs-client-provisioner-84ff87c669-ksw95 1/1 Running 0 21m

安装逻辑由 roles/cluster-addon/tasks/nfs-provisioner.yml 驱动:将nfs-provisioner.yaml.j2test-pod.yaml.j2渲染到${cluster_dir}/yml/nfs-provisioner/目录后执行kubectl apply;在 roles/cluster-addon/tasks/main.yml 中还会先检查集群中是否已存在nfs-client-provisionerPod,避免重复部署。

3. 部署模板的组成解析

渲染后的部署清单nfs-provisioner.yaml由四个部分组成(模板见 nfs-provisioner.yaml.j2):

  • ServiceAccount + ClusterRole + ClusterRoleBinding:为 provisioner 授予操作 nodes、persistentvolumes、persistentvolumeclaims、storageclasses 与 events 的权限,这是动态供应 PV 所必需的 RBAC 授权;
  • Role + RoleBinding(leader-locking):通过 endpoints 资源实现多副本场景下的选主锁,保证同一时刻只有一个 provisioner 实例处理 PVC;
  • Deployment:运行easzlab.io.local:5000/easzlab/nfs-subdir-external-provisioner:{{ nfs_provisioner_ver }}镜像,通过环境变量NFS_SERVERNFS_PATH注入 NFS 地址与共享目录,并将该 NFS 目录以 volume 方式挂载到容器/persistentvolumes路径,PROVISIONER_NAME固定为k8s-sigs.io/nfs-subdir-external-provisioner
  • StorageClass:名为{{ nfs_storage_class }}provisioner指向上述名称,archiveOnDelete: "false"表示删除 PVC 时直接清理对应 NFS 子目录而不归档保留。

4. 验证动态 PV 使用

仓库在clusters/${集群名}/yml/nfs-provisioner/目录下生成了测试例子(模板见 test-pod.yaml.j2),它声明了一个 2Mi、ReadWriteMany的 PVC,再由 busybox Pod 在挂载点创建SUCCESS文件:

$ kubectl apply -f /etc/kubeasz/clusters/hello/yml/nfs-provisioner/test-pod.yaml # 验证测试 pod kubectl get pod NAME READY STATUS RESTARTS AGE test-pod 0/1 Completed 0 6h36m # 验证自动创建的 pv 资源 kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 2Mi RWX Delete Bound default/test-claim managed-nfs-storage 6h36m # 验证 PVC 已经绑定成功:STATUS 字段为 Bound kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim Bound pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 2Mi RWX managed-nfs-storage 6h37m

Pod 启动完成后,回到 NFS 服务器上查看共享目录,可以看到 provisioner 根据 PVC 自动创建的目录及写入的文件:

. └── default-test-claim-pvc-44d34a50-e00b-4f6c-8005-40f5cc54af18 └── SUCCESS

也就是说,Pod 中挂载的/mnt实际指向该自动生成的 NFS 子目录,/mnt下创建的SUCCESS文件也已落盘到 NFS 服务器。此后上层应用只需声明使用managed-nfs-storage这个 StorageClass 创建 PVC,即可获得动态供应的持久化存储。

静态 PV 与动态 PV 的取舍

如果不想部署 provisioner,也可以手工创建静态 PV 直接对接 NFS 共享目录,仓库文档 08-cluster-storage.md 给出了示例:在 PV 的spec.nfs字段中填写path(实际共享目录)与server(NFS 服务器地址),并指定容量、访问模式与storageClassName,随后创建对应 PVC 即可绑定使用。

两种方式的区别在于:静态 PV 需要管理员为每个存储需求手工创建 PV,而动态 PV 通过provisioner与 StorageClass 自动完成 PV 的创建与回收,更适应 PVC 请求频繁的生产集群。kubeasz 中除 NFS 外还集成了 local-path-provisioner(本地目录存储供应者,适合对磁盘 I/O 要求高、可本地挂载 SSD 的场景),可在 08-cluster-storage.md 中查看更多细节。

常见故障排查

| 现象 | 可能原因与处理 | | :- | :- | |mount.nfs: access denied by server while mounting|/etc/exports未放行发起挂载的源 IP(k8s 场景需放行 Pod 网段);或缺少insecure参数 | | provisioner Pod 处于 CrashLoopBackOff | 检查nfs_server/nfs_path配置是否与/etc/exports一致,确认 NFS 服务已启动且共享目录存在 | | PVC 一直 Pending | 查看kubectl describe pvc事件,确认 StorageClass 名称拼写正确、provisioner Pod 正常运行 | | 客户端挂载后目录为空 | 挂载点目录中原有内容被 NFS 覆盖隐藏,挂载前应保证挂载点为空 |

小结

NFS 服务器的搭建与权限配置是 Kubernetes 持久化存储链路上的第一环:/etc/exports中的共享目录、客户端授权与insecure参数决定了后续所有挂载是否成功;在此基础上,kubeasz 通过 nfs-provisioner 将 NFS 目录转换为动态 PV 供应能力,使集群内任意应用只需引用 StorageClass 即可获得持久化存储。掌握本文的安装、配置、挂载与验证流程,即可在生产集群中稳定落地 NFS 存储方案。

【免费下载链接】kubeasz使用Ansible脚本安装K8S集群,介绍组件交互原理,方便直接,不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeasz

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 17:13:45

RoboCup仿真2D从源码到上场:agent2d编译与连接全攻略

第一次把 Agent2D 的源码编译出可执行文件、然后看着 11 个自带编号的小球员在同一台机器上连进 rcssserver 时,我才真正理解 RoboCup 仿真2D 的“球队”不过是一堆遵守同一套通信协议的进程。很多新手卡在这个环节:教程只说到“下载源码”“编译”&…

作者头像 李华
网站建设 2026/9/15 17:13:10

资金核对平台进化史:从Excel手工对账到智能实时对账系统

资金核对平台的发展历程:从Excel大战到智能对账,我亲历的四个时代在支付公司干过资金链路的人,大概都记得那种深夜被财务叫醒的恐惧——银行流水和系统账对不上,差一分钱,所有人都别想睡。我做资金核对平台这门生意差不…

作者头像 李华
网站建设 2026/9/15 17:12:15

基于Java+springboot的驾校管理系统-附源码

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/15 17:11:28

基于Spring Boot的企业车辆管理系统源码解析与实战部署

简介:基于Spring Boot框架的企业车辆管理系统,面向Java开发者与高校计算机专业学生,适用于课程设计、毕业设计或企业车辆信息化管理场景。系统涵盖管理员、驾驶员、用户三类角色,核心模块包括车辆登记、车辆运营、通用接口和配置管…

作者头像 李华