【一起来学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)使用详解

相关推荐
mingyuewu几秒前
MAC安装docker 后提示com.docker.vmnetd”将对您的电脑造成伤害
macos·docker·容器
企鹅侠客2 小时前
Prometheus operator怎么添加targets和告警规则
运维·云原生·kubernetes·prometheus·pod
专注代码七年3 小时前
Docker运维篇
运维·docker·容器
一杯敬朝阳 一杯敬月光4 小时前
WIN11 企业版 部署Dify+Docker
运维·docker·容器
Leo Han4 小时前
k8s常用命令(持续更新中)
docker·容器·kubernetes
KubeSphere 云原生4 小时前
云原生周刊:Kubernetes v1.33 要来了
云原生·容器·kubernetes
孔令飞5 小时前
关于 LLMOPS 的一些粗浅思考
人工智能·云原生·go
镜舟科技5 小时前
迈向云原生:理想汽车 OLAP 引擎变革之路
大数据·数据库·云原生
dessler5 小时前
Kubernetes(k8s)-日志(logs)和exec内部逻辑
linux·运维·kubernetes