Files
Deploy-Laboratory/docs/03-06-k3s-使用nfs存储.md
jack 8c43761962 feat: 按 doc_id 重组 ansible/files 与验证框架
- ansible/files 改为与文档 XX-YY 对齐的目录结构,更新相关 playbook 路径
- 新增 scripts/verify.sh 与 ansible/playbooks/verify/*.yml,移除单体 verify-matrix.yml
- 补充 docs/00-02 矩阵状态、00-05 验证框架与流程、00-04 环境与 ylc65 工作机说明
- 增加 k3s 存储准备、Longhorn、local-path 等 playbook 与辅助脚本

Made-with: Cursor
2026-03-26 07:01:14 +08:00

7.2 KiB
Raw Blame History

03-06-k3s 使用 NFS 存储

本文只讲 K3s 集群侧如何使用已安装好的 NFS。

前置条件

  • 已完成 01-05-armv7-nfs服务安装.md
  • 可从 K3s 节点访问 NFS 服务器与导出目录

方式对比(从简单到复杂)

方式 1Pod 直接挂 NFS 方式 2静态 NFSPV + PVC 方式 3动态 NFS选装 provisioner
复杂度
最少 YAML 段数 1 段Deployment/Pod 2 段PV+PVC 通常 1 段 PVCPV/目录动态生成)
目录创建 需手工提前创建 需手工提前创建 通常由 provisioner 自动创建子目录
与应用耦合 高(写死 server/path 低(应用只引用 PVC 低(应用只引用 PVC
适用场景 临时验证、概念验证(先跑通) 稳定运行、团队协作 大规模/多团队、追求自动化

操作步骤

  1. 按复杂度选择一种方式
  2. 应用清单
  3. 验证读写

结论K3s 使用 NFS 不需要先把 NFS 手工挂到每台节点主机Pod/PVC 可直接挂远端 NFS。

方式 1Pod 直接挂 NFS最简单快速验证

说明:nfs.path 指向的目录(或子目录)需要在 NFS 服务端提前创建并设置好权限K3s 不会自动在 NFS 服务端创建该目录。

例如在 onecloud 上预创建子目录:

sudo mkdir -p /sdcard/app-a
sudo chown 1000:1000 /sdcard/app-a
sudo chmod 0770 /sdcard/app-a
apiVersion: apps/v1 # Deployment 使用的 API 版本
kind: Deployment # 资源类型Deployment
metadata: # 资源元信息
  name: nfs-direct-demo # Deployment 名称
  namespace: default # 命名空间
spec: # Deployment 规格
  replicas: 1 # 副本数
  selector: # Pod 选择器
    matchLabels: # 标签匹配条件
      app: nfs-direct-demo # 选择带 app=nfs-direct-demo 的 Pod
  template: # Pod 模板
    metadata: # Pod 元信息
      labels: # Pod 标签
        app: nfs-direct-demo # Pod 标签值
    spec: # Pod 规格
      containers: # 容器列表
        - name: app # 容器名称
          image: nginx:alpine # 容器镜像
          volumeMounts: # 容器内挂载点
            - name: nfs-data # 引用下方 volumes 的卷名
              mountPath: /usr/share/nginx/html # 挂载到容器内目录
      volumes: # Pod 卷定义
        - name: nfs-data # 卷名
          nfs: # 直接使用 NFS 卷
            server: <NFS_SERVER_IP> # NFS 服务器地址(应用前替换)
            path: <NFS_EXPORT_PATH_OR_SUBDIR> # NFS 导出目录或子目录(应用前替换)

方式 2静态 NFSPV + PVC推荐

唯一真源ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml

为减少硬编码,示例清单已改为占位符:<NFS_SERVER_IP><NFS_EXPORT_PATH>
应用前必须先替换(例如 192.168.2.22/sdcard)。

静态 NFS 同样需要在服务端提前创建目录并设置权限;不会自动创建目录。

方式 3动态 NFS选装 provisioner

这是选装增强,不是 K3s 内置默认能力。常见组件是 nfs-subdir-external-provisioner

3.1 安装 provisionerHelm

前提NFS 服务端已可用(例如 192.168.2.22:/sdcard),且 K3s 节点网络可达。

# 1) 添加 chart 仓库
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm repo update

# 2) 安装(建议放到 kube-system
helm upgrade --install nfs-subdir-external-provisioner \
  nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
  -n kube-system --create-namespace \
  --set nfs.server=192.168.2.22 \
  --set nfs.path=/sdcard \
  --set storageClass.name=nfs-client \
  --set storageClass.defaultClass=false \
  --set storageClass.reclaimPolicy=Delete \
  --set storageClass.archiveOnDelete=true

参数说明(最常改):

  • nfs.serverNFS 服务器地址
  • nfs.pathNFS 导出根目录provisioner 会在其下创建子目录)
  • storageClass.name:动态供给使用的 StorageClass 名称
  • archiveOnDelete:删除 PVC 时是否归档目录(true 更稳妥,false 更干净)

3.2 验证 provisioner 与 StorageClass

kubectl -n kube-system get pod -l app.kubernetes.io/name=nfs-subdir-external-provisioner -o wide
kubectl get storageclass

3.3 用动态 PVC 验证自动建卷

创建一个最小 PVC示例

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-dynamic-pvc-demo
  namespace: default
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client
  resources:
    requests:
      storage: 5Gi

应用并验证:

kubectl apply -f /tmp/nfs-dynamic-pvc-demo.yaml
kubectl get pvc nfs-dynamic-pvc-demo -n default
kubectl get pv | grep nfs-dynamic-pvc-demo

当 PVC Bound 后,通常可在 NFS 服务器的 /sdcard 下看到自动创建的子目录(命名规则由 provisioner 管理)。

3.5 本次实机验证记录ylc61 + onecloud

  • nfs-subdir-external-provisioner 安装成功并 Running
  • StorageClass nfs-client 创建成功
  • 动态 PVC nfs-dynamic-pvc-demo 成功 Bound
  • 自动创建 PV 成功,并在 NFS 服务端目录下生成子目录:
    • /sdcard/default-nfs-dynamic-pvc-demo-pvc-<uid>
  • 删除临时 PVC 后PV 按 Delete 回收完成

备注:验证中曾出现过镜像拉取 EOF(偶发网络抖动),重试后官方镜像 registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 已可正常拉取并启动。

3.4 何时选动态 NFS

  • 目录数量多、变更频繁
  • 希望减少手工维护 PV/PVC 对应关系
  • 团队里希望应用只声明 PVC平台统一管理 StorageClass

验证命令(若 YAML 在 manifests 目录,按实际路径选择其一复制执行)

# 仓库根直接应用
# 先替换 ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml 里的占位符
# <NFS_SERVER_IP> -> 例如 192.168.2.22
# <NFS_EXPORT_PATH> -> 例如 /sdcard
kubectl apply -f ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml
# 或默认路径(已拷贝到 manifests 时)
kubectl apply -f /var/lib/rancher/k3s/server/manifests/nfs-pv-pvc.yaml
kubectl get pv,pvc -A
kubectl describe pv nfs-pv-demo
# 自定义 data-dir如 /storage
kubectl apply -f /storage/server/manifests/nfs-pv-pvc.yaml
kubectl get pv,pvc -A
kubectl describe pv nfs-pv-demo
# 对方式 1Pod 直挂)可这样验证
kubectl apply -f /tmp/nfs-direct-demo.yaml
kubectl rollout status deploy/nfs-direct-demo --timeout=180s
kubectl exec deploy/nfs-direct-demo -- sh -c 'echo nfs-direct-ok > /usr/share/nginx/html/nfs.txt && cat /usr/share/nginx/html/nfs.txt'

预期

  • PV/PVC 状态为 Bound
  • 业务 Pod 可读写挂载目录

失败排查

  • 检查 NFS 服务与导出目录权限
  • 检查节点到 NFS 服务器网络
  • 检查 pathserver 配置是否正确
  • 若报 Permission denied,回到 01-05root_squash 权限章节,确认导出目录与业务 UID/GID 对齐

下一步

  • 03-05-k3s-local-path-pvc.md:单副本应用用 K3s 自带 local-path 即可,无需 NFS
  • 05-06-openlist挂载网盘与自动备份.md