66·存储进阶

NFS 存储

kubernetesstoragenfsnetwork-storage

NFS 存储

学习目标

  1. 理解 NFS 在 Kubernetes 中的使用方式
  2. 掌握 NFS Volume 和 NFS Provisioner 的配置
  3. 了解 NFS 存储的优缺点和适用场景

核心概念

NFS 是什么

NFS (Network File System):
┌─────────────────────────────────────────┐
│              NFS Server                 │
│         /exports/k8s-data              │
└─────────────────┬───────────────────────┘
                  │ 网络共享
        ┌─────────┼─────────┐
        ▼         ▼         ▼
    ┌──────┐  ┌──────┐  ┌──────┐
    │Node A│  │Node B│  │Node C│
    │ Pod1 │  │ Pod2 │  │ Pod3 │
    └──────┘  └──────┘  └──────┘

特点:
- 所有节点/Pod 可同时读写同一目录
- 数据集中在 NFS 服务器
- 适合多 Pod 共享数据

方式一:直接使用 NFS Volume

apiVersion: v1
kind: Pod
metadata:
  name: nfs-pod
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - mountPath: /data
          name: nfs-volume
  volumes:
    - name: nfs-volume
      nfs:
        server: 192.168.1.100    # NFS 服务器地址
        path: /exports/data      # NFS 共享路径
        readOnly: false
优点:简单直接
缺点:
- 不支持动态供给
- 需要预先知道 NFS 服务器信息
- 无法通过 PVC 申请

方式二:NFS + PV/PVC(静态)

# PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany      # NFS 支持多节点读写
  nfs:
    server: 192.168.1.100
    path: /exports/data
  persistentVolumeReclaimPolicy: Retain

---
# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

方式三:NFS Subdir External Provisioner(动态供给)

动态供给架构:

┌─────────────────────────────────────────┐
│         NFS Subdir External Provisioner │
│              (Deployment)               │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│              NFS Server                 │
│         /exports/k8s-data              │
│           ├── pvc-uuid-1/              │
│           ├── pvc-uuid-2/              │
│           └── pvc-uuid-3/              │
└─────────────────────────────────────────┘

每创建一个 PVC,自动在 NFS 上创建子目录

安装 Provisioner

# 使用 Helm 安装
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner

helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
  --set nfs.server=192.168.1.100 \
  --set nfs.path=/exports/k8s-data \
  --set storageClass.name=nfs-client

StorageClass 定义

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  pathPattern: "${.PVC.namespace}-${.PVC.name}"  # 目录命名模式
  onDelete: delete                               # PVC 删除时行为
reclaimPolicy: Delete
volumeBindingMode: Immediate

使用动态 NFS

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-dynamic-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client
  resources:
    requests:
      storage: 5Gi
NFS 上自动创建:/exports/k8s-data/default-nfs-dynamic-pvc/

NFS 访问模式

模式NFS 支持说明
ReadWriteOnce单节点读写
ReadOnlyMany多节点只读
ReadWriteMany多节点读写
NFS 的优势:
- 完整支持所有访问模式
- 特别适合 ReadWriteMany 场景
- 多个 Pod 可同时读写同一目录

NFS 子目录命名

# 常用 pathPattern 模式
parameters:
  # 默认:pvc-{uuid}
  pathPattern: ""

  # 按命名空间和 PVC 名
  pathPattern: "${.PVC.namespace}-${.PVC.name}"

  # 按命名空间分目录
  pathPattern: "${.PVC.namespace}/${.PVC.name}"

  # 自定义前缀
  pathPattern: "k8s-volumes/${.PVC.namespace}-${.PVC.name}"

实践练习

练习 1:搭建测试 NFS

# 在 NFS 服务器上(或使用容器模拟)
# 创建共享目录
sudo mkdir -p /exports/k8s-data
sudo chmod 777 /exports/k8s-data

# 配置 /etc/exports
echo "/exports/k8s-data *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -ra

练习 2:使用 NFS Volume

# nfs-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nfs-test
spec:
  containers:
    - name: writer
      image: busybox
      command: ["sh", "-c", "echo 'Hello NFS' > /data/test.txt && sleep 3600"]
      volumeMounts:
        - mountPath: /data
          name: nfs-vol
  volumes:
    - name: nfs-vol
      nfs:
        server: 192.168.1.100  # 替换为实际地址
        path: /exports/k8s-data
kubectl apply -f nfs-pod.yaml
kubectl exec nfs-test -- cat /data/test.txt

练习 3:验证多 Pod 共享

# 创建两个 Pod 共享同一 NFS
apiVersion: v1
kind: Pod
metadata:
  name: nfs-reader
spec:
  containers:
    - name: reader
      image: busybox
      command: ["sh", "-c", "cat /data/test.txt && sleep 3600"]
      volumeMounts:
        - mountPath: /data
          name: nfs-vol
  volumes:
    - name: nfs-vol
      nfs:
        server: 192.168.1.100
        path: /exports/k8s-data
kubectl apply -f nfs-reader.yaml
kubectl exec nfs-reader -- cat /data/test.txt

常见误解

1. NFS 性能不是最优的

NFS 是网络存储,性能不如本地磁盘
高 IOPS 场景(数据库)应使用块存储
NFS 适合文件共享、日志、配置等场景

2. NFS 不是高可用的

NFS 服务器是单点
生产环境需要:
- NFS 高可用方案(如 GlusterFS、Ceph)
- 或使用云厂商的托管文件存储(EFS、Azure Files)

小结

要点说明
NFS网络文件系统,支持多节点共享
访问模式完整支持 RWO/ROX/RWX
静态使用直接指定 NFS 服务器和路径
动态供给使用 nfs-subdir-external-provisioner
适用场景文件共享、日志、配置
注意事项性能有限、单点风险

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「云存储」 以巩固所学知识。