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卷具有以下特点:

  1. ‌持久性‌:NFS卷能将网络文件系统(NFS)挂载到Pod中,其内容在删除Pod时不会被删除,只是被卸载。它与emptyDir卷不同,后者在Pod删除时会一并被删除。
  2. ‌数据共享‌:NFS卷可以预先填充数据,并且这些数据可以在不同的Pod之间共享,提高了数据的利用率和灵活性。

使用优势‌:由于数据的持久性和共享性,NFS卷非常适合需要持久存储或数据共享的应用场景,如数据库、文件服务器等。

‌安装NFS工具‌nfs-utils:(在主节点和每个node节点都安装nfs-utils)

  1. 在终端输入yum -y install nfs-utils命令,安装NFS所需工具。
  2. ‌输入systemctl start nfs-server,启动NFS服务。
  3. ‌使用命令cat /proc/fs/nfsd/version,查看当前NFS的版本信息。
  4. 创建基础目录:mkdir -p /home/nfs,进入到cd /home/nfs目录后,再创建两个子目录rw和ro。
  5. 设置共享目录‌:编辑/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属性需要使用。

  1. ‌依次输入命令exportfs -f和systemctl reload nfs-server,重新加载NFS服务配置。
  2. ‌在其他节点(如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挂载失败,请检查:

  1. NFS服务器上路径是否存在且权限正确。
  2. /etc/exports配置是否正确且已重新加载。
  3. NFS服务是否正常运行:systemctl status nfs-server。
  4. 防火墙是否放行了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。

1PV的生命周期

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状态,需要管理员干预排查问题‌。

2PVC的生命周期

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的生命周期。

控制循环流程:

  1. ‌监控变化‌:通过List-Watch机制监控PV和PVC对象。
  2. ‌状态比对‌:比较实际状态与期望状态。
  3. ‌执行操作‌:
    1. 静态供给:匹配可用PV与Pending状态的PVC。
    2. 动态供给:通过StorageClass创建新PV。
  4. ‌状态更新‌:更新PV和PVC的status字段‌。

静态供给与动态供给特性对比:

特性

静态供给

动态供给

‌PV创建方式‌

管理员手动创建

StorageClass自动创建

‌适用场景‌

存储资源稳定/可预测

弹性需求/云环境

‌管理复杂度‌

高(需预先规划)

低(按需创建)

‌回收策略‌

通常为Retain

通常为Delete

‌容量规划‌

需精确预估

弹性扩展‌

生命周期中常见错误场景及解决方案:

错误场景

可能原因

解决方案

‌PV创建失败‌

存储后端不可用/配置错误

检查存储系统日志和连接

‌PVC长期Pending‌

无匹配PV/StorageClass配置错误

检查PVC请求条件和StorageClass

‌绑定后无法使用‌

节点插件未安装/挂载权限问题

检查节点kubelet日志和存储插件

‌回收失败‌

存储系统故障/配额不足

检查存储系统状态和资源配额‌

3PV的存储类型

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策略。

4PVPVC的访问模式

Persistent Volume Claim(PVC)支持三种主要访问模式:

访问模式

缩写

描述

适用场景

ReadWriteOnce

RWO

单节点读写

只能被单个节点以读写方式挂载

ReadOnlyMany

ROX

多节点只读

可被多个节点以只读方式挂载

ReadWriteMany

RWX

多节点读写

可被多个节点以读写方式挂载

需要注意的是,不是所有存储类型都支持所有访问模式,例如:NFS通常支持RWX,AWS EBS通常只支持RWO,Azure File支持RWX‌。

5PVCPV的绑定机制

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回收策略。

6PV的回收策略

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、创建并使用PVPVC

编写一个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有足够权限。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐