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 数据。bashrsync -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。
-
排查命令:
bashkubectl describe pvc <pvc-name> kubectl logs -n <namespace> <nfs-provisioner-pod> showmount -e <nfs-server-ip> # 在客户端验证共享目录可见性
2. Pod 挂载失败
- 错误现象 :
mount.nfs: Connection timed out
或Access 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
中指定运行用户。yamlsecurityContext: 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)使用详解