【一起来学kubernetes】29、NFS使用详解


Kubernetes 中 NFS 存储使用详解

NFS(Network File System)是一种基于网络的分布式文件系统协议,允许多个节点共享同一存储目录。在 Kubernetes 中,NFS 常用于实现多节点读写(ReadWriteMany)的持久化存储,适用于需要共享数据的场景(如日志存储、配置文件共享、静态资源托管等)。NFS允许网络上的节点像访问本地文件一样来访问和共享文件系统。通过使用NFS,用户和程序可以方便地访问远端系统上的文件。


一、NFS 存储的核心特点
特性 说明
共享访问 支持多节点同时读写同一目录,适合多 Pod 共享数据的场景。
协议兼容性 兼容 Linux/Unix 系统,Windows 需额外配置。
网络依赖 依赖稳定的网络环境,高延迟或断网可能导致 I/O 性能下降或超时。
性能瓶颈 高并发场景下,NFS 服务器可能成为性能瓶颈(需优化硬件或使用分布式文件系统)。
NFS的优缺点
  • 优点:
    • 高稳定性 :NFS是一个非常稳定的网络文件系统。
    • 可移植性 :NFS支持多种操作系统平台,如Linux、Unix和Windows等。
    • 高性能 :随着网络速度的增加和延迟的降低,NFS系统已成为通过网络提供文件系统服务的有竞争力的选择。
  • 缺点:
    • 网络依赖 :NFS依赖于网络连接,若网络不稳定或中断,可能导致数据访问问题。
    • 权限管理 :NFS的权限管理相对复杂,需要仔细配置以确保数据的安全性。

二、NFS 存储的两种供应模式
模式 说明 适用场景
静态供应 管理员手动创建 NFS 服务器并定义 PV,用户通过 PVC 绑定 PV。 固定存储配置,适合小规模集群。
动态供应 通过 NFS Provisioner 自动创建 PV,用户只需声明 PVC(需配合 StorageClass)。 按需动态分配,适合大规模生产环境。
1、NFS作为持久化存储

在K8s中,Pod是应用实例的载体,但Pod具有短暂性,其生命周期可能因各种原因而终止。为了确保数据的持久性,需要将数据存储在Pod之外的持久化存储中。NFS作为一种网络文件系统,可以方便地挂载到多个Pod中,实现数据的持久化存储。

  • 创建NFS服务器:首先,需要在K8s集群外部或内部创建一个NFS服务器,并配置好共享目录和访问权限。
  • 配置PV和PVC:在K8s中,需要创建PersistentVolume(PV)和PersistentVolumeClaim(PVC)来管理NFS存储。PV定义了存储的具体细节,如容量、访问模式和存储类别等,而PVC则是用户对存储资源的申请。通过PVC与PV的绑定,K8s可以自动为用户分配合适的存储资源。
  • 挂载NFS卷到Pod:在Pod的配置中,可以使用volumeMounts字段将NFS卷挂载到Pod内的指定路径。这样,Pod就可以像访问本地文件一样访问NFS共享中的文件了。
2、NFS实现数据共享

NFS不仅可以用于持久化存储,还可以实现多个Pod之间的数据共享。这对于需要共享配置文件、日志文件或上传文件等场景非常有用。

  • 共享目录配置:在NFS服务器上,可以创建一个或多个共享目录,并配置好访问权限。这些共享目录可以被多个Pod同时挂载和访问。
  • 动态PVC创建:通过配置NFS动态卷提供器(如nfs-client-provisioner),K8s可以根据PVC的申请动态创建NFS卷。这样,用户无需手动创建和管理PV,只需提出PVC申请即可。
  • 多Pod访问:多个Pod可以通过挂载相同的NFS卷来实现数据共享。这需要注意权限管理和数据一致性等问题,但NFS提供了相应的机制来支持这些功能。
3、NFS的动态存储服务

在K8s中,通过配置NFS动态卷提供器,可以实现动态存储服务。这意味着当Pod需要存储资源时,K8s可以自动为其分配和管理NFS卷。

  • 动态卷提供器安装:首先,需要在K8s集群中安装NFS动态卷提供器,如nfs-client-provisioner。这通常通过Helm或其他Kubernetes包管理工具来完成。
  • 存储类配置:在创建PVC之前,需要配置一个存储类(StorageClass),指定使用NFS作为后端存储。这样,当PVC申请存储资源时,K8s就会根据存储类的配置来动态创建NFS卷。
  • PVC申请与绑定:用户只需创建一个PVC来申请所需的存储资源,K8s就会自动为其分配一个合适的NFS卷,并将其绑定到PVC上。这样,用户就可以在Pod中使用这个PVC来访问NFS存储了。

三、静态供应 NFS 存储

1. 部署 NFS 服务器
步骤 1:在服务器节点安装 NFS 服务
bash 复制代码
# Ubuntu/Debian
apt-get install nfs-kernel-server

# CentOS/RHEL
yum install nfs-utils
步骤 2:创建共享目录并配置权限
bash 复制代码
mkdir /data/nfs-share
chmod 777 /data/nfs-share

# 编辑 NFS 配置文件
vim /etc/exports
# 添加以下内容(允许所有客户端读写):
/data/nfs-share *(rw,sync,no_subtree_check,no_root_squash)

# 启动 NFS 服务
systemctl start nfs-server
systemctl enable nfs-server

# 验证共享目录
showmount -e
2. 在 Kubernetes 中创建 PV 和 PVC
PV 定义(手动创建)
yaml 复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs-static
  nfs:
    path: /data/nfs-share  # NFS 服务器共享路径
    server: 192.168.1.100  # NFS 服务器 IP
PVC 定义(用户请求存储)
yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  storageClassName: nfs-static
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
3. 在 Pod 中挂载 NFS 存储
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nfs-app
spec:
  containers:
    - name: nfs-container
      image: nginx
      volumeMounts:
        - name: nfs-volume
          mountPath: /usr/share/nginx/html
  volumes:
    - name: nfs-volume
      persistentVolumeClaim:
        claimName: nfs-pvc

四、动态供应 NFS 存储

动态供应通过 NFS Provisioner 自动创建 PV,需提前部署 Provisioner 并定义 StorageClass。

1. 部署 NFS Provisioner
使用 Helm 安装(推荐)
bash 复制代码
# 添加 Helm 仓库
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner

# 安装 Provisioner
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
  --set nfs.server=192.168.1.100 \
  --set nfs.path=/data/nfs-share \
  --set storageClass.name=nfs-dynamic
手动部署 YAML
yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-provisioner
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      containers:
        - name: nfs-provisioner
          image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs  # Provisioner 的唯一标识
            - name: NFS_SERVER
              value: 192.168.1.100
            - name: NFS_PATH
              value: /data/nfs-share
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.1.100
            path: /data/nfs-share
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-dynamic
provisioner: example.com/nfs  # 必须与 Deployment 中的 PROVISIONER_NAME 一致
parameters:
  archiveOnDelete: "false"  # 删除 PVC 时是否保留数据目录
2. 使用动态供应的 PVC
yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-nfs-pvc
spec:
  storageClassName: nfs-dynamic
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
3. 验证动态 PV 创建
bash 复制代码
kubectl get pv  # 查看自动创建的 PV
kubectl get pvc dynamic-nfs-pvc  # 确认 PVC 状态为 Bound

五、NFS 存储的最佳实践

1. 性能优化
  • NFS 服务器硬件:使用 SSD 磁盘、万兆网络,提升 I/O 性能。

  • 内核参数调优 :调整 NFS 服务器和客户端的 TCP 缓冲区大小。

    bash 复制代码
    # 在 NFS 服务器上优化
    echo "net.core.rmem_max=67108864" >> /etc/sysctl.conf
    echo "net.core.wmem_max=67108864" >> /etc/sysctl.conf
    sysctl -p
2. 安全配置
  • 限制访问范围 :在 /etc/exports 中指定允许访问的 IP 段。

    bash 复制代码
    /data/nfs-share 192.168.1.0/24(rw,sync,no_subtree_check)
  • 启用 Kerberos 认证:在 NFSv4 中配置加密和身份验证。

3. 数据备份
  • 定期快照 :使用 rsync 或存储厂商的快照工具备份 NFS 数据。

    bash 复制代码
    rsync -avz /data/nfs-share backup-server:/backup/nfs
  • Velero 备份:集成 Velero 实现 Kubernetes 应用数据的全量/增量备份。

4. 高可用方案*
  • NFS 服务器集群:使用 DRBD + Pacemaker 或云厂商的托管 NFS 服务(如 AWS EFS、Azure Files)。
  • 客户端重试机制 :在 Pod 中配置 mountPropagation: Bidirectional 以容忍网络波动。

六、常见问题与排查

1. PVC 处于 Pending 状态
  • 可能原因

    • NFS 服务器不可达(检查网络连通性)。
    • 共享目录权限不足(确保 no_root_squash 配置正确)。
    • StorageClass 未正确关联 Provisioner。
  • 排查命令

    bash 复制代码
    kubectl describe pvc <pvc-name>
    kubectl logs -n <namespace> <nfs-provisioner-pod>
    showmount -e <nfs-server-ip>  # 在客户端验证共享目录可见性
2. Pod 挂载失败
  • 错误现象mount.nfs: Connection timed outAccess denied
  • 解决方案
    • 检查 Pod 所在节点是否安装 NFS 客户端工具。

      bash 复制代码
      # Ubuntu/Debian
      apt-get install nfs-common
      # CentOS/RHEL
      yum install nfs-utils
    • 验证 NFS 服务器的防火墙规则(开放 TCP/UDP 111、2049 端口)。

3. 文件权限问题
  • 现象:Pod 写入 NFS 目录时提示权限不足。
  • 解决
    • 在 NFS 服务器上设置共享目录权限为 777

    • 在 Pod 的 securityContext 中指定运行用户。

      yaml 复制代码
      securityContext:
        runAsUser: 1000
        fsGroup: 1000

七、总结

NFS 是 Kubernetes 中实现多节点共享存储的经典方案,适合需要 ReadWriteMany 访问模式的应用场景。通过静态供应或动态供应(结合 NFS Provisioner),可以灵活管理存储资源。但在生产环境中需重点关注网络稳定性、性能瓶颈和数据安全性,必要时可替换为分布式文件系统(如 Ceph、GlusterFS)或云托管的共享存储服务(如 AWS EFS)。

八、拓展

【一起来学kubernetes】24、Service使用详解
【一起来学kubernetes】27、PersistentVolume(PV)使用详解
【一起来学kubernetes】25、Master使用详解
【一起来学kubernetes】26、PersistentVolumeClaim(PVC)使用详解

相关推荐
遇见火星21 小时前
Docker入门:快速部署你的第一个Web应用
前端·docker·容器
阿里云云原生21 小时前
移动端性能监控探索:iOS RUM SDK 技术架构与实践
云原生
阿里云云原生21 小时前
Nacos 3.1.0 正式发布,支持 A2A 注册中心与 MCP 注册协议增强
微服务·云原生
阿里云云原生1 天前
Qoder 上线提示词增强功能,将开发者从“提示词”的负担中解放出来
云原生
suknna1 天前
通过命令模拟pod创建
kubernetes
维诺菌1 天前
k8s java应用pod内存占用过高问题排查
java·jvm·云原生·容器·性能优化·kubernetes
回忆是昨天里的海1 天前
k8s安装-kubeadm join,将工作节点加入k8s集群
java·服务器·kubernetes
浪飘1 天前
k8s device plugin
java·docker·kubernetes
冬夜戏雪1 天前
milvus容器restart不成功,但docker仍在running问题排查
docker·容器·milvus
m0_579146651 天前
docker desktop的容器间通信
docker·容器·php