kubernetes简单使用之持久化存储
Kubernetes提供多种持久化存储方案,满足不同场景需求: emptyDir:临时存储,生命周期与Pod绑定,适用于容器间数据共享 hostPath:直接挂载宿主机目录,开发调试适用但存在安全风险 NFS:网络共享存储,支持多Pod并发读写,需配置exports文件 PV/PVC:解耦式存储管理,支持静态/动态供给,生产环境首选 云存储:深度集成云平台,支持动态扩容和快照 关键特性对比: 持久
Kubernetes 持久化存储方式:
1. emptyDir:临时存储
原理:Pod 调度到节点时创建空目录,生命周期与 Pod 绑定(Pod 删除则数据清除)。
特点:
- 适用于临时数据缓存或容器间共享。
- 默认使用节点磁盘,可配置为内存(emptyDir: { medium: "Memory" })。
示例:
volumes:
- name: cache-volume
emptyDir: {}
2. hostPath:本地存储
原理:将宿主机目录直接挂载到 Pod 中10。
特点:
|
类型 |
用途 |
风险 |
|
Directory |
访问宿主机日志(如 /var/log) |
暴露主机文件系统 |
|
Socket |
容器与宿主机进程通信 |
需严格权限控制 |
限制:仅适用于单节点场景,Pod 迁移会导致数据不可用。
3. NFS:网络共享存储
原理:基于 RPC 协议实现客户端-服务器文件共享,支持多 Pod 并发读写。
配置示例:
volumes:
- name: nfs-vol
nfs:
server: 192.168.1.100
path: /shared_data
性能优化:
- 使用高性能 SSD 作为 NFS 服务器存储。
- 调整 rsize/wsize 参数优化传输块大小。
4. PV/PVC:解耦式存储
静态供给流程:
Admin[管理员创建 PV] --> User[用户创建 PVC]
User --> K8s[K8s 绑定 PV 和 PVC]
K8s --> Pod[Pod 使用 PVC]
动态供给:通过 StorageClass 定义模板(如云存储参数),自动按需创建 PV。
5. 云存储(如 AWS EBS/Azure Disk)
特点:
- 与云平台深度集成,支持动态扩容、快照备份。
- 通过 CSI(Container Storage Interface)插件对接。
示例(AWS EBS):
storageClassName: gp3
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
选型建议:
|
存储类型 |
适用场景 |
持久性 |
共享性 |
|
emptyDir |
临时计算中间结果 |
❌ |
单 Pod 多容器 |
|
hostPath |
开发调试、节点监控 |
⚠️(依赖节点) |
❌ |
|
PV/PVC |
生产环境数据库 |
✅ |
按访问模式 |
|
NFS |
多 Pod 共享配置 |
✅ |
✅ |
|
云存储 |
云原生应用 |
✅ |
按云服务能力 |
生产环境优先使用 PV/PVC 或云存储,避免直接使用 hostPath。

1、volumes
Volumes:提供Pod存储卷,用于数据持久化或数据共享。
Volume 是 Kubernetes 中为 Pod 提供持久化存储或共享数据的核心机制,解决了容器文件系统的临时性问题。其核心特点包括:
- Pod 级抽象:Volume 定义在 Pod 上,可被同一 Pod 内的多个容器挂载到不同路径,实现数据共享。
- 生命周期解耦:部分 Volume 类型(如 PV/PVC)的生命周期独立于 Pod,确保数据持久化。
- 多样化类型:支持本地存储、网络存储、云存储等多种后端,通过插件机制(VolumePlugin)实现扩展。
1、基于hostPath方式实现的volumes
编写一个volume-test-pd.yaml文件用于创建Pod对象,验证volumes和volumeMounts挂载功能。
apiVersion: v1
kind: Pod
metadata:
name: test-volume-pd
spec:
containers:
- image: nginx
name: nginx-volume
volumeMounts:
- mountPath: /test-pd # 容器内挂载路径,将主机目录与容器中该目录进行挂载
name: test-volume # 指定要挂载哪个数据卷
volumes: # 定义数据卷配置
- name: test-volume # 给数据卷起个名称
hostPath: # 主机路径模式,与主机共享目录
path: /data # 主机目录,也就是节点目录
type: DirectoryOrCreate # 挂载前检查类型,不存在则创建




2、基于emptyDir实现的Volumes
apiVersion: v1
kind: Pod
metadata:
name: empty-dir-pd
spec:
containers:
- image: alpine
name: nginx-emptydir1
command: ["/bin/sh", "-c", "sleep 3600;"] # 容器启动后睡眠3600秒,防止容器退出
volumeMounts:
- mountPath: /cache
name: cache-volume
- image: alpine
name: nginx-emptydir2
command: ["/bin/sh", "-c", "sleep 3600;"]
volumeMounts:
- mountPath: /opt
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}

由于这个Pod中有两个容器,所以需要-c参数指定进入到哪个容器中。


基于emptyDir实现的Volumes适用于临时数据缓存或容器间共享,如果Pod被删除了,数据就消失了,不能做持久化存储。
2、NFS挂载
NFS卷具有以下特点:
- 持久性:NFS卷能将网络文件系统(NFS)挂载到Pod中,其内容在删除Pod时不会被删除,只是被卸载。它与emptyDir卷不同,后者在Pod删除时会一并被删除。
- 数据共享:NFS卷可以预先填充数据,并且这些数据可以在不同的Pod之间共享,提高了数据的利用率和灵活性。
使用优势:由于数据的持久性和共享性,NFS卷非常适合需要持久存储或数据共享的应用场景,如数据库、文件服务器等。
安装NFS工具nfs-utils:(在主节点和每个node节点都安装nfs-utils)
- 在终端输入yum -y install nfs-utils命令,安装NFS所需工具。
- 输入systemctl start nfs-server,启动NFS服务。
- 使用命令cat /proc/fs/nfsd/version,查看当前NFS的版本信息。
- 创建基础目录:mkdir -p /home/nfs,进入到cd /home/nfs目录后,再创建两个子目录rw和ro。
- 设置共享目录:编辑/etc/exports文件,添加以下内容:
/home/nfs/rw 192.168.113.0/24(rw,sync,no_subtree_check,no_root_squash)
/ home/nfs/ro 192.168.113.0/24(ro,sync,no_subtree_check,no_root_squash)
注意:/etc/exports文件中配置的目录在下面PV yaml文件中的nfs.path属性需要使用。
- 依次输入命令exportfs -f和systemctl reload nfs-server,重新加载NFS服务配置。
- 在其他节点(如k8s-node2)测试挂载:
- 在测试节点创建挂载点:mkdir -p /mnt/nfs/rw,mkdir -p /mnt/nfs/ro
- 使用命令mount -t nfs 192.168.113.121:/home/nfs/rw /mnt/nfs/rw,挂载NFS共享目录。
k8s-master的IP是192.168.113.120,k8s-node1的IP是192.168.113.121,k8s-node2的IP是192.168.113.122。
/etc/exports文件配置规范
NFS服务器的/etc/exports文件需要包含PV配置的路径(nfs.path),典型配置格式如下:
/home/nfs/rw *(rw,sync,no_subtree_check,no_root_squash)
配置说明:
- 目录/home/nfs/rw:该目录需要是PV yaml中nfs.path配置目录的父目录,或两者一致。
- *:表示允许所有客户端访问(生产环境应限制为特定IP或网段,如192.168.113.0/24)。
- rw:读写权限(与PV的accessModes对应)。
- sync:同步写入磁盘。
- no_subtree_check:禁用子树检查提高性能。
- no_root_squash:允许root用户保持权限。
配置生效步骤:编辑/etc/exports文件,执行exportfs -a使配置生效,重启NFS服务:systemctl restart nfs-server。
生产环境最佳实践:
1. 路径规划建议:
- 使用专用目录如/data/nfs作为NFS根目录。
- 为不同应用创建子目录,如/data/nfs/mysql、/data/nfs/nginx等。
- 避免使用用户主目录如/home作为NFS共享根目录。
2. 权限管理:
- 为NFS目录设置专用用户和组:chown nobody:nogroup /data/nfs。
- 根据安全需求选择root_squash或no_root_squash选项。
3. 网络隔离:
- 在/etc/exports中限制客户端IP范围,如192.168.113.0/24
- 配置防火墙规则只允许Kubernetes节点访问NFS端口。
4. 监控与维护:
- 定期检查NFS共享状态:showmount -e
- 监控PV/PVC绑定状态和使用情况。
5. 常见错误排查
如果PV无法正常绑定或Pod挂载失败,请检查:
- NFS服务器上路径是否存在且权限正确。
- /etc/exports配置是否正确且已重新加载。
- NFS服务是否正常运行:systemctl status nfs-server。
- 防火墙是否放行了NFS相关端口(通常为2049)。
编写一个yaml文件创建Pod,用于验证nfs方式挂载Volumes、volumeMounts。
在k8s-node1节点上先创建一个文件:

在Master节点上编写一个yaml文件创建Pod:
apiVersion: v1
kind: Pod
metadata:
name: nfs-test-pd1
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
nfs:
server: 192.168.113.121
path: /home/nfs/rw/www/wolfcode
readOnly: false


3、PV与PVC


PV(Persistent Volume):持久化存储卷,由管理员创建和配置,用于存储持久化数据。
PVC(Persistent Volume Claim):持久化存储卷申领,由用户创建,用于声明需要的存储资源和访问模式。
区别与联系:
- 区别:PV是存储资源,PVC是对存储资源的请求。
- 联系:PVC请求PV,PV提供满足条件的存储资源,通过绑定关系在Pod中使用。
PV与PVC绑定:Kubernetes根据PVC的请求(大小、访问模式等)自动匹配可用PV,绑定后PV状态变为Bound。
1、PV的生命周期
PV作为集群级别的存储资源,其生命周期独立于任何使用它的Pod,主要经历以下几个阶段:
1. Available(可用)阶段
特征:存储资源已就绪且未被任何PVC绑定。
关键操作:
- 管理员手动创建PV或StorageClass动态创建PV。
- PV对象被注册到Kubernetes API服务器。
- 存储系统完成底层资源配置(如云磁盘创建、NFS共享配置等)。
检查命令:
kubectl get pv -l 'status.phase=Available'
kubectl get pv -o jsonpath='{.items[?(@.status.phase=="Available")].metadata.name}'
生产注意点:
- 确保PV容量配置合理,避免后续PVC绑定失败。
- 验证存储类配置是否正确:kubectl describe storageclass <name>。
2. Bound(已绑定)阶段
触发条件:PVC成功匹配并绑定PV。
关键机制:
- PVC与PV 1:1绑定(ReadWriteOnce模式)。
- 多PVC可共享PV(ReadWriteMany模式)。
- 绑定后PV状态从Available变为Bound。
绑定检查命令:
kubectl get pvc -o jsonpath='{.spec.volumeName}' mysql-pvc
监控指标:
PV容量使用率:kubelet_volume_stats_used_bytes{persistentvolumeclaim="<pvc-name>"} / kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="<pvc-name>"} * 100
生产注意点:
- 避免容量超售:PV容量应 ≥ PVC请求容量。
- 检查访问模式兼容性。
3. Released(已释放)阶段
触发条件:关联PVC被删除,PV的回收策略为Retain(保留)。
数据保护策略:
apiVersion: v1
kind: PersistentVolume
metadata:
name: critical-data-pv
spec:
persistentVolumeReclaimPolicy: Retain # 关键配置
# ...其他参数...
后续处理:
- 管理员需手动清理或重用PV。
- 可重新绑定到新PVC(需先手动清理数据)。
4. Terminating(终止中)阶段
动态PV特性:PVC删除触发PV自动回收,依赖StorageClass的reclaimPolicy。
配置示例:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-auto-delete
provisioner: ebs.csi
reclaimPolicy: Delete # 动态PV通常配置Delete策略
错误状态:回收失败时PV进入Failed状态,需要管理员干预排查问题。
2、PVC的生命周期
PVC作为用户对存储资源的请求,其生命周期与PV紧密关联:
1. 创建阶段
- 用户操作:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-example
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
- 系统处理:API服务器接收PVC创建请求,PV控制器开始查找匹配的PV。
2. 绑定阶段
静态供给:系统查找符合PVC条件的可用PV,匹配因素:存储类 > 容量 > 访问模式 > 标签选择器。
动态供给:当没有静态PV匹配时,若PVC指定了StorageClass,则会触发动态供给,根据StorageClass动态创建PV,动态创建的PV专用于该PVC。
3. 使用阶段
Pod挂载:
volumes:
- name: pvc-storage
persistentVolumeClaim:
claimName: pvc-example
状态监控:PVC状态从Pending变为Bound,关联PV状态同步更新。
4. 释放阶段
触发条件:使用PVC的Pod被删除,或者用户手动删除PVC。
后续处理:根据PV的回收策略(Retain/Recycle/Delete)处理,PVC状态变为Released。
PV控制器的工作机制
PV控制器是Kubernetes控制平面的核心组件,负责管理PV与PVC的生命周期。
控制循环流程:
- 监控变化:通过List-Watch机制监控PV和PVC对象。
- 状态比对:比较实际状态与期望状态。
- 执行操作:
- 静态供给:匹配可用PV与Pending状态的PVC。
- 动态供给:通过StorageClass创建新PV。
- 状态更新:更新PV和PVC的status字段。
静态供给与动态供给特性对比:
|
特性 |
静态供给 |
动态供给 |
|
PV创建方式 |
管理员手动创建 |
StorageClass自动创建 |
|
适用场景 |
存储资源稳定/可预测 |
弹性需求/云环境 |
|
管理复杂度 |
高(需预先规划) |
低(按需创建) |
|
回收策略 |
通常为Retain |
通常为Delete |
|
容量规划 |
需精确预估 |
弹性扩展 |
生命周期中常见错误场景及解决方案:
|
错误场景 |
可能原因 |
解决方案 |
|
PV创建失败 |
存储后端不可用/配置错误 |
检查存储系统日志和连接 |
|
PVC长期Pending |
无匹配PV/StorageClass配置错误 |
检查PVC请求条件和StorageClass |
|
绑定后无法使用 |
节点插件未安装/挂载权限问题 |
检查节点kubelet日志和存储插件 |
|
回收失败 |
存储系统故障/配额不足 |
检查存储系统状态和资源配额 |
3、PV的存储类型
Kubernetes中的Persistent Volume(PV)支持多种存储类型,主要包括以下几类:
1. 网络存储类型:
- NFS (Network File System):通过网络协议挂载外部存储系统
- iSCSI:基于IP的存储网络标准
- CephFS:开源分布式文件系统
- GlusterFS:可扩展的网络文件系统
2. 云提供商存储:
- AWS EBS (Elastic Block Store)
- Azure Disk
- GCE Persistent Disk
- OpenStack Cinder
3. 本地存储:
- hostPath:使用节点本地目录
- local:专为本地存储设计的卷类型
4. 其他类型:
- FC (Fibre Channel):光纤存储设备
- FlexVolume:插件式存储机制
- Flocker:开源共享存储系统
- CSI (Container Storage Interface):标准化存储插件架构
|
存储类型 |
典型代表 |
访问模式支持 |
适用场景 |
优缺点 |
|
网络文件存储 |
NFS, CephFS |
RWX(多读多写) |
内容共享、Web应用 |
易共享但性能较低 |
|
块存储 |
iSCSI, RBD |
RWO(单读写) |
数据库、高性能应用 |
高性能但难共享 |
|
云存储 |
AWS EBS, Azure Disk |
RWO/ROX |
云原生应用 |
集成好但依赖云平台 |
|
本地存储 |
hostPath, local |
RWO |
测试、单节点应用 |
高性能但无高可用 |
Kubernetes支持多种PV存储类型,选择时需综合考虑数据特性、性能需求和应用场景:
1. 是否需要多节点共享数据?
是 → 选择支持RWX的存储(NFS, CephFS)
否 → 考虑块存储或本地存储
2. 是否在云环境中运行?
是 → 优先使用云提供商存储(AWS EBS等)
否 → 评估自建存储方案(NFS, Ceph等)
3. 性能要求如何?
高IOPS需求 → 块存储(iSCSI, RBD)或本地SSD
高吞吐量 → 分布式文件系统(CephFS)
4. 数据持久性要求?
关键数据 → 选择支持快照/备份的存储
临时数据 → 简单存储方案(hostPath)1316
具体场景推荐
1. 数据库应用:
- 首选:块存储(RBD, iSCSI)或云块存储(AWS EBS)
- 原因:低延迟、高IOPS
- 配置:RWO访问模式 + Retain回收策略
2. Web应用共享存储:
- 首选:NFS或CephFS
- 原因:支持多Pod同时读写
- 配置:RWX访问模式 + Retain/Delete策略
3. 日志处理:
- 首选:云存储(AWS EBS)或分布式存储
- 原因:弹性扩展需求
- 配置:RWO访问模式 + Delete策略
4. 开发测试环境:
- 首选:hostPath或动态供应的本地存储
- 原因:低成本、易管理
- 配置:RWO访问模式 + Recycle策略。
4、PV和PVC的访问模式
Persistent Volume Claim(PVC)支持三种主要访问模式:
|
访问模式 |
缩写 |
描述 |
适用场景 |
|
ReadWriteOnce |
RWO |
单节点读写 |
只能被单个节点以读写方式挂载 |
|
ReadOnlyMany |
ROX |
多节点只读 |
可被多个节点以只读方式挂载 |
|
ReadWriteMany |
RWX |
多节点读写 |
可被多个节点以读写方式挂载 |
需要注意的是,不是所有存储类型都支持所有访问模式,例如:NFS通常支持RWX,AWS EBS通常只支持RWO,Azure File支持RWX。
5、PVC与PV的绑定机制
PV(Persistent Volume)与PVC(Persistent Volume Claim)的绑定是Kubernetes存储系统的核心功能之一,其绑定过程遵循以下机制:
1. 自动匹配原则:
Kubernetes会根据PVC中声明的存储需求(容量、访问模式、存储类等)自动匹配可用的PV。匹配优先级:存储类 > 容量 > 访问模式 > 其他标签选择器。一旦匹配成功,PV状态从Available变为Bound,PVC状态从Pending变为Bound。
2. 绑定条件:
- PVC请求的存储大小必须小于等于PV的容量。
- PVC的访问模式必须与PV支持的访问模式兼容。
- 如果PVC指定了StorageClass,PV必须属于同一StorageClass(或未指定StorageClass时使用默认类)。
- 可选的标签选择器(selector.matchLabels)可以进一步限制PV选择。
3. 绑定过程:
A[创建PVC] --> B{Kubernetes查找匹配PV}
B -->|找到匹配PV| C[绑定PV与PVC]
B -->|未找到PV| D[等待动态供应创建PV]
C --> E[Pod使用PVC]
D -->|StorageClass配置| F[动态创建PV]
F --> C
4. 绑定状态转换:
PV状态:Available → Bound → Released(根据回收策略)
PVC状态:Pending → Bound → Released(删除时)
5. 动态绑定:
- 通过StorageClass实现动态PV供应。
- 当没有静态PV匹配PVC时,系统会根据StorageClass自动创建PV。
- 动态绑定的PV通常使用Delete回收策略。
6、PV的回收策略
PV的回收策略决定了当PVC被删除后,PV及其存储资源如何处理。Kubernetes提供三种主要回收策略:
|
回收策略 |
行为描述 |
适用场景 |
注意事项 |
|
Retain |
保留PV和数据,需手动处理 |
关键数据存储(如数据库) |
管理员需手动清理或重用PV |
|
Recycle |
清除PV数据(类似rm -rf),使PV可重新使用 |
测试环境或可丢弃数据 |
仅支持部分存储类型(NFS、hostPath) |
|
Delete |
自动删除PV及后端存储资源 |
云平台动态存储(如AWS EBS) |
数据将永久丢失,慎用 |
各策略详细说明:
1. Retain策略:
PVC删除后,PV状态变为Released而非Available,数据完整保留在存储系统中,管理员需要手动执行以下操作之一:
- 删除PV并清理底层存储。
- 保留PV并手动清除数据后重新绑定。
- 直接创建新PVC绑定到该PV。
2. Recycle策略:
自动执行数据清除操作(非安全删除),PV状态从Released变回Available,适用于:
- 开发测试环境。
- 可重新生成的非关键数据。
- 需要频繁创建/删除PVC的场景。
3. Delete策略:
自动删除PV对象及后端存储资源,适用于云平台提供的动态存储卷。典型使用场景:
- 临时性数据存储。
- 日志系统。
- 可轻松重建的数据。
生产环境建议:
- 关键数据:始终使用Retain策略,配合备份方案。
- 云环境:动态供应的PV通常配置Delete策略,但需确认数据可重建。
- 性能敏感型应用:考虑Retain策略避免重复创建存储资源。
- 测试集群:可使用Recycle策略简化管理。
7、创建并使用PV和PVC
编写一个yaml文件,手动创建PV对象。
apiVersion: v1
kind: PersistentVolume # 资源类型,此处创建PV类型的对象
metadata:
name: pv0001 # PV对象的名称
spec:
capacity: # 容量配置
storage: 5Gi # PV的存储容量
volumeMode: Filesystem # 存储类型,指定存储类型为文件系统
accessModes: # 访问模式,ReadWriteOnce、ReadWriteMany、ReadOnlyMany
- ReadWriteOnce # 单节点读写,只能被一个PVC绑定
persistentVolumeReclaimPolicy: Retain # 回收策略
storageClassName: slow # 创建PV对象的存储类名,需要与PVC的相同
mountOptions: # 挂载配置
- hard
- nfsvers=4.1
nfs:
path: /home/nfs/rw/test-pv #NFS存储路径,必须在/etc/exports文件中配置该目录或其父目录
server: 192.168.113.121 # NFS服务器地址


在Kubernetes中配置NFS PersistentVolume(PV)时,nfs.path参数必须满足以下关键要求:
1. 路径必须真实存在:NFS服务器上必须实际存在该路径,不能随意指定不存在的路径。当Pod尝试挂载PV时,如果路径不存在会导致挂载失败。
2. 路径权限配置:该路径在NFS服务器上需要设置正确的权限,通常建议:
创建目录:mkdir -p /home/nfs/rw/test-pv
设置权限:chmod 777 /home/nfs/rw/test-pv (生产环境应根据实际需求设置更严格的权限)。
3. 在/etc/exports文件配置:该路径或其父目录必须在NFS服务器的/etc/exports文件中进行正确配置并导出,这是NFS服务能够共享该目录的前提条件。
4. 修改/etc/exports文件之后,依次执行exportfs -f和systemctl reload nfs-server命令重新加载NFS服务配置,使修改生效。
如果PV无法正常绑定或Pod挂载失败,请检查:
- NFS服务器上路径是否存在且权限正确。
- /etc/exports配置是否正确且已重新加载。
- NFS服务是否正常运行:systemctl status nfs-server。
- 防火墙是否放行了NFS相关端口(通常为2049)。
编写一个yaml文件创建PVC对象。
apiVersion: v1
kind: PersistentVolumeClaim # 资源类型,此处创建PVC类型的对象
metadata:
name: nfs-pvc # PVC对象的名称
spec:
accessModes: # 访问模式,必须与要绑定的PV相同,否则无法绑定
- ReadWriteOnce # 单节点读写,只能被单个节点以读写方式访问
volumeMode: Filesystem # 存储类型,指定存储类型为文件系统,需要与PV保持一致
resources:
requests:
storage: 5Gi # 资源大小限制,不能大于要绑定PV的大小限制,否则无法绑定
storageClassName: slow #创建PVC对象的存储类名,需要与PV的相同,否则无法绑定
# selector: # 定义标签选择器,使用选择器选择PV
# matchLabels:
# release: "stable"
# matchExpressions:
# - {key: environment, operator: In, values: [dev]}


编写一个yaml文件创建Pod对象,将Pod与PVC绑定。

8、动态创建PV
参考:
https://www.bilibili.com/video/BV1MT411x7GH?spm_id_from=333.788.videopod.episodes&vd_source=504a440cc2b1e270fb0f32279de0de00&p=67

managed-nfs-storage是Kubernetes中的一种动态存储类(StorageClass),用于自动创建基于NFS(网络文件系统)的持久卷(PV)。它通过NFS Client Provisioner实现动态存储供应,用户只需声明存储需求(如PVC),无需手动管理PV。
动态创建PV主要有以下两步:
1. 创建managed-nfs-storage
- 创建ServiceAccount对象,配置RBAC(Role-Based Access Control)权限。
- 创建StorageClass对象,指定NFS供应器的行为和参数。
- 创建Deployment对象,创建NFS动态供应器的Pod。
说明:这三个yaml文件具有关联关系,Deployment的PROVISIONER_NAME与StorageClass的provisioner必须一致。权限链:Deployment使用ServiceAccount → ClusterRoleBinding绑定ClusterRole → 规则授权PV/PVC操作。
2. 使用managed-nfs-storage
创建Pod、Deployment或StatefulSet使用managed-nfs-storage,验证是否动态创建PV。
下面是创建managed-nfs-storage的步骤,编写yaml文件创建ServiceAccount、StorageClass和Deployment对象。
1. 编写一个nfs-provisioner-rbac.yaml文件,创建ServiceAccount对象,为NFS动态供应器配置RBAC权限,包括ServiceAccount、ClusterRole和ClusterRoleBinding。
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner#服务账号名称,用于Pod身份认证,下面创建Deployment会引用此名称
namespace: kube-system # 指定服务账号所属命名空间,通常与供应器部署位置一致
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner # 集群角色名称
rules: # 定义权限规则,覆盖PV、PVC和StorageClass的常见操作
- apiGroups: [""] # verbs:create/delete用于动态创建PV,update用于绑定PVC
resources: ["persistentvolumes"] # 管理PV资源
verbs: ["get", "list", "watch", "create", "delete"] # 允许操作PV的完整生命周期
- apiGroups: [""]
resources: ["persistentvolumeclaims"] # 管理PVC资源
verbs: ["get", "list", "watch", "update"] # 允许查询和更新PVC
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"] # 管理StorageClass资源
verbs: ["get", "list", "watch"] # 仅允许查询操作
---
kind: ClusterRoleBinding # 此处将subjects中的服务账号与roleRef中的角色进行绑定
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner # 集群角色绑定名称
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner # 绑定的服务账号
namespace: kube-system # 服务账号所在命名空间
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner # ClusterRole的名称,指定要绑定的角色
apiGroup: rbac.authorization.k8s.io


2. 编写nfs-storage-class.yaml文件创建StorageClass对象,定义动态存储类,指定NFS供应器的行为和参数。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage # 存储类名称,PVC需引用此名称
provisioner: fuseim.pri/ifs #供应器标识符,需与Deployment中PROVISIONER_NAME一致
# provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
archiveOnDelete: "false" #是否在删除PVC时存档(保留数据),false表示不存档直接删除
reclaimPolicy: Retain # PV回收策略(Retain / Delete),Retain表示保留PV
volumeBindingMode: Immediate #卷绑定模式,Immediate表示立即绑定(WaitForFirstConsumer延迟至Pod调度)

3. 编写一个Deployment类型的nfs-provisioner-deployment.yaml文件,部署NFS动态供应器的Pod,配置NFS服务器连接和存储路径
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: kube-system
labels: # 定义标签,给Deployment对象打标签
app: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate # 更新策略:先删除旧Pod再创建新Pod
selector: #标签选择器,创建deployment对象时根据这个标签找到Pod模板创建Pod对象
matchLabels:
app: nfs-client-provisioner # 匹配Pod模板的标签
template: # Pod模板配置
metadata:
labels:
app: nfs-client-provisioner # 给Pod打标签,deployment就是根据这个标签找到Pod模板的
spec:
serviceAccountName: nfs-client-provisioner # 使用之前创建的ServiceAccount
containers:
- name: nfs-client-provisioner # 指定供应器的名称和镜像
image: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0
# image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes # NFS挂载到容器内的路径
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs #供应器的名称,需要与StorageClass yaml文件中的保持一致
- name: NFS_SERVER
value: 192.168.113.121
- name: NFS_PATH
value: /data/nfs/rw # nfs挂载路径,需要在/etc/exports文件中配置
volumes:
- name: nfs-client-root
nfs:
server: 192.168.113.121
path: /data/nfs/rw # nfs挂载路径,需要在/etc/exports文件中配置

4. 上面三个yaml文件编写好之后,通过kubectl apply(或create) -f <yaml文件>命令创建对象,并通过kubectl get storageclass或kubectl get sc(sc是storageclass的缩写)命令查看是否成功创建managed-nfs-storage。

5. 编写nfs-sc-demo-statefulset.yaml文件创建Service和StatefulSet对象,使用上面创建的managed-nfs-storage,自动创建并绑定PV。
StatefulSet需要用到Service,所以创建StatefulSet之前需要先创建Service,此处将创建Service和StatefulSet对象写到一个yaml文件中,没有单独写创建Service的yaml文件。
---
apiVersion: v1
kind: Service
metadata:
name: nginx-sc
labels:
app: nginx-sc
spec:
type: NodePort
ports:
- name: web
port: 80
protocol: TCP
selector:
app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-sc
spec:
replicas: 1
serviceName: "nginx-sc"
selector:
matchLabels:
app: nginx-sc
template:
metadata:
labels:
app: nginx-sc
spec:
containers:
- image: nginx
name: nginx-sc
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-sc-test-pvc
volumeClaimTemplates:
- metadata:
name: nginx-sc-test-pvc
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

6. 检查PV是否自动创建:
kubectl get pvc
kubectl get pv
若PVC或PV处于pending状态,尝试通过以下方法进行排查:
- 检查NFS服务器是否可达。
- 确认Provisioner Pod运行正常:kubectl logs -n kube-system <provisioner-pod-name>。
- 确保RBAC配置正确,ServiceAccount有足够权限。
更多推荐
所有评论(0)