
kubeasz 实战NFS 服务器搭建与 Kubernetes 动态 PV 供应【免费下载链接】kubeasz使用Ansible脚本安装K8S集群介绍组件交互原理方便直接不受国内网络环境影响项目地址: https://gitcode.com/GitHub_Trending/ku/kubeaszNFSNetwork 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-utilsyum install nfs-utils说明nfs-utils在红帽系中同时包含服务端与客户端组件启动的服务名为nfs-serverUbuntu 系服务端包为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 用户具有根目录的完全管理访问权限 | | anonuidxxx | 指定 nfs 服务器 /etc/passwd 文件中匿名用户的 UID | | anongidxxx | 指定 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未放行该网段挂载即被拒绝。注 2insecure参数必须添加。经测试缺少该参数会导致客户端挂载失败同样报错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-commonCentOS 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 rsize8192,wsize8192,timeo14,intrrsize/wsize客户端与服务端之间每次读写的数据块大小字节timeo请求超时重传前的等待时间十分之一秒此处为 1.4 秒intr允许信号中断阻塞中的 NFS 操作避免进程长期卡死。在 kubeasz 中启用 nfs-provisioner 动态 PVNFS 服务端就绪后即可让 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_server与nfs_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.j2与test-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.j2ServiceAccount ClusterRole ClusterRoleBinding为 provisioner 授予操作 nodes、persistentvolumes、persistentvolumeclaims、storageclasses 与 events 的权限这是动态供应 PV 所必需的 RBAC 授权Role RoleBindingleader-locking通过 endpoints 资源实现多副本场景下的选主锁保证同一时刻只有一个 provisioner 实例处理 PVCDeployment运行easzlab.io.local:5000/easzlab/nfs-subdir-external-provisioner:{{ nfs_provisioner_ver }}镜像通过环境变量NFS_SERVER、NFS_PATH注入 NFS 地址与共享目录并将该 NFS 目录以 volume 方式挂载到容器/persistentvolumes路径PROVISIONER_NAME固定为k8s-sigs.io/nfs-subdir-external-provisionerStorageClass名为{{ 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 6h37mPod 启动完成后回到 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实际共享目录与serverNFS 服务器地址并指定容量、访问模式与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未放行发起挂载的源 IPk8s 场景需放行 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),仅供参考