当前位置: 首页 > news >正文

K8S存储管理:从Volume到PV/PVC实战

本章概述

K8S存储管理按照发展的历程,涉及到有Volume、PV/PVC、StorageClass,Volume是最早提出的存储卷,主要解决容器和数据存储的依赖关系,抽象底层驱动以及支持不同的存储类型,使用Volume需要了解底层存储细节,因此提出了PV,Persistent Volume是由k8s管理员定义的存储单元,应用端使用PersistentVolumeClaims声明去调用PV存储,进一步抽象了底层存储;随着PV数量的增加,管理员需要不停的定义PV的数量,衍生了通过StorageClass动态生成PV,StorageClass通过PVC中声明存储的容量,会调用底层的提供商生成PV。本文介绍Volume的使用,下篇文章介绍PV,PVC和StorageClass。

Volume 存储卷,独立于容器,后端和不同的存储驱动对接

PV Persistent Volume持久化存储卷,和node类似,是一种集群资源,由管理员定义,对接不同的存储

PVC PersistentVolumeClaims持久化存储声明,和pod类似,作为PV的使用者

StorageClass 动态存储类型,分为静态和动态两种类型,通过在PVC中定义存储类型,自动创建所需PV

存储的概述

kubernetes容器中的数据是临时的,即当重启重启或crash后容器的数据将会丢失,此外容器之间有共享存储的需求,所以kubernetes中提供了volume存储的抽象,volume后端能够支持多种不同的plugin驱动,通过.spec.volumes中定义一个存储,然后在容器中.spec.containers.volumeMounts调用,最终在容器内部以目录的形式呈现。

本地临时存储

本地临时存储包括emptyDir等。

emptyDir是一种临时存储,pod创建的时候会在node节点上为容器申请一个临时的目录,跟随容器的生命周期,如容器删除,emptyDir定义的临时存储空间也会随之删除,容器发生意外crash则不受影响,同时如果容器发生了迁移,其上的数据也会丢失,emptyDir一般用于测试,或者缓存场景。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除pod。

emptyDir 的一些用途:

缓存空间,例如基于磁盘的归并排序。

为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。

在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

[root@k8s-master pv]# cat emptydir.yamlapiVersion: v1 kind: Pod metadata: name: test-pod-emptydir spec: containers: - image: busybox:1.27 name: test-container command:["/bin/sh","-c","sleep 600"]volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir:{}[root@k8s-master pv]# kubectl apply -f emptydir.yaml

[root@k8s-master pv]# kubectl exec -it test-pod-emptydir /bin/shkubectlexec[POD][COMMAND]is DEPRECATED and will be removedina future version. Use kubectlexec[POD]--[COMMAND]instead. /# cd /cache//cache# ls/cache# echo "linux" > a.txt/cache# cat a.txtlinux

创建文件的路径可以通过如下步骤进行查找。首先查找改pod所在的node,然后登陆这台node,进行grep

[root@k8s-master pv]# kubectl get pod -o wide

[root@k8s-node1 ~]# docker inspect k8s_test-container_test-pod-emptydir_default_7a310cd3-8d93-422b-bbe1-1c405b22721f_0

[root@k8s-node1 ~]# cat /var/lib/kubelet/pods/7a310cd3-8d93-422b-bbe1-1c405b22721f/volumes/kubernetes.io~empty-dir/cache-volume/a.txtlinux

备注:当删除完这个pod时,这个文件也会自动删除的。

[root@k8s-master pv]# kubectl delete pod test-pod-emptydirpod"test-pod-emptydir"deleted[root@k8s-node1 ~]# cat /var/lib/kubelet/pods/7a310cd3-8d93-422b-bbe1-1c405b22721f/volumes/kubernetes.io~empty-dir/cache-volume/a.txtcat: /var/lib/kubelet/pods/7a310cd3-8d93-422b-bbe1-1c405b22721f/volumes/kubernetes.io~empty-dir/cache-volume/a.txt: No suchfileor directory

hostPath主机存储

hostPath 卷能将node宿主机节点文件系统上的文件或目录挂载到您的 Pod 中。

基础主机上创建的文件或目录只能由 root 用户写入。您需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

[root@k8s-node1 ~]# mkdir /data[root@k8s-node1 ~]# ls /data/[root@k8s-master pv]# cat hostpath.ymlapiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: test-container volumeMounts: - mountPath: /test-pod name: test-volume volumes: - name: test-volume hostPath: path: /data type: Directory[root@k8s-master pv]# kubectl create -f hostpath.ymlpod/nginx created[root@k8s-master pv]# kubectl get pod

[root@k8s-node1 ~]# echo "cloud" > /data/b.txt[root@k8s-master pv]# kubectl exec -it nginx /bin/bashkubectlexec[POD][COMMAND]is DEPRECATED and will be removedina future version. Use kubectlexec[POD]--[COMMAND]instead. root@nginx:/# cd /test-pod/root@nginx:/test-pod# lsb.txt

持久化存储PV和PVC

1.PV和PVC的引入

pv(PersistentVolume 持久卷) PV 是集群中的一块网络存储,它独立于 Pod 存在。PV 可以是各种存储系统,如云提供商的存储、NFS、iSCSI、本地存储等。 管理员负责创建 PV,并配置其细节,如容量、访问模式(ReadWriteOnce、ReadOnlyMany、ReadWriteMany)、存储类别等。 PV 有自己的生命周期,它的状态包括可用(Available)、绑定(Bound)、释放(Released)、回收(Retained)等状态。 pvc(PersistentVolumeClaim 持久卷声明) PVC 是对 PV 的请求,它定义了 Pod 对存储的需求。在创建 Pod 时,可以通过 PVC 来请求存储资源。 PVC 可以指定所需的存储容量、访问模式等参数,但通常不需要指定具体的 PV,而是通过标签选择器来动态匹配 PV。 PVC 的存在使得 Pod 与具体的存储实现解耦,提高了可移植性。 关系: PVC 与 PV 之间是一种声明与提供的关系。PVC 声明了对存储资源的需求,而 PV 则是提供这些资源的实际载体。 当 PVC 被创建时,Kubernetes 会尝试将其与满足其要求的 PV 进行绑定。匹配的过程是根据 PVC 的标签选择器和 PV 的标签进行匹配,只有匹配成功的 PV 才能被绑定到 PVC。一旦绑定成功,Pod 可以通过 PVC 访问 PV 提供的存储资源。 如果没有合适的 PV 可以绑定,PVC 将处于 Pending 状态,直到有合适的 PV 可用为止。 总之,PV 和 PVC 之间的关系是一种动态的匹配和绑定关系,它们使得 Pod 与存储资源的具体实现解耦,提高了灵活性和可移植性。

2.通过NFS实现持久化存储

2.1 配置nfs

k8s-master nfs-server

k8s-node1 k8s-node2 nfs-client

所有节点安装nfs

yuminstall-ynfs-common nfs-utils

在nfs-server节点创建共享目录

[root@k8s-master k8s]# mkdir /nfsdata

授权共享目录

[root@k8s-master k8s]# chmod 666 /nfsdata

编辑exports文件(no_root_squash#root用户具有根目录的完全管理访问权限;no_all_squash#保留共享文件的UID和GID(默认);sync所有数据在请求时写入共享(数据实时同步))

[root@k8s-master k8s]# vim /etc/exports/nfsdata *(rw,no_root_squash,no_all_squash,sync)

配置生效

启动rpc和nfs(注意顺序)

[root@k8s-master k8s]# systemctl start rpcbind[root@k8s-master k8s]# systemctl start nfs

作为准备工作,我们已经在 k8s-master 节点上搭建了一个 NFS 服务器,目录为/nfsdata

测试NFS挂载是否可用

[root@k8s-node2 ~]# mkdir /test[root@k8s-node2 ~]# mount -t nfs 10.8.166.252:/nfsdata /test/[root@k8s-node2 ~]# df -Th|grep "/test"10.8.166.252:/nfsdata nfs4 19G9.9G9.0G53% /test[root@k8s-node2 ~]# touch /test/ip.txt[root@k8s-node2 ~]# ls /test/ip.txt

来到nfs-server查看,成功

[root@k8s-master ~]# ls /nfsdata/ip.txt[root@k8s-node2 ~]# umount /test #测试完成之后,就可以卸载了

2.2 创建PV

下面创建一个 PVmypv1,配置文件nfs-pv1.yml如下:

[root@k8s-master ~]# vim nfs-pv1.ymlapiVersion: v1 kind: PersistentVolume metadata: name: mypv1 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /nfsdata server:192.168.153.148#指定nfs目录所在的机器的地址

capacity指定 PV 的容量为 5G。

accessModes指定访问模式为ReadWriteOnce,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

persistentVolumeReclaimPolicy指定当 PV 的回收策略为Recycle,支持的策略有:
Retain – 当PVC被删除时,与之绑定的PV不会自动删除,需要手动清理。
Recycle – 清除 PV 中的数据,效果相当于执行rm -rf /nfsdata/*(已废弃。在Kubernetes 1.17中被移除,不再支持)。
Delete – 当PVC被删除时,与之绑定的PV会被自动删除(经实验,删除pvc之后pv不会被删除,只是状态变为failed,不可用了)。

storageClassName自定义存储类名称,相当于为 PV 设置了一个分类。

⑤ 指定 PV 在 NFS 服务器上对应的目录。

创建mypv1

[root@k8s-master ~]# kubectl apply -f nfs-pv1.yml

STATUSAvailable,表示mypv1就绪,可以被 PVC 申请/绑定。

2.3 创建PVC

接下来创建 PVCmypvc1,配置文件nfs-pvc1.yml如下:

[root@k8s-master ~]# cat nfs-pvc1.ymlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mypvc1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs

PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。

执行命令创建mypvc1

[root@k8s-master ~]# kubectl apply -f nfs-pvc1.yml

kubectl get pvc -o yaml/json 查看实际申请空间是多少

kubectl get pvckubectl get pv的输出可以看到mypvc1已经 Bound 到mypv1,申请成功。

2.4 创建pod

上面已经创建好了pv和pvc,pod中直接使用这个pvc即可

[root@k8s-master ~]# vim pod1.ymlapiVersion: v1 kind: Pod metadata: name: mypod1 labels: app: jiangege spec: containers: - name: mypod1 image: nginx ports: - containerPort:80volumeMounts: - mountPath:"/usr/share/nginx/html"name: mydata volumes: - name: mydata persistentVolumeClaim: claimName: mypvc1

与使用普通 Volume 的格式类似,在volumes中通过persistentVolumeClaim指定使用mypvc1申请的 Volume。

通过命令创建mypod1

[root@k8s-master ~]# kubectl apply -f pod1.yml

2.5 验证

[root@k8s-master ~]# kubectl exec -it mypod1 /bin/sh/# ls /usr/share/nginx/html/# echo "jiangege" > /usr/share/nginx/html/index.html[root@k8s-master ~]# ls /nfsdata/ #也可在nfs的共享目录中查看到,说明卷共享成功index.html[root@k8s-master ~]# cat /nfsdata/index.htmljiangege 可见,在 Pod 中创建的文件 /usr/share/nginx/html/index.html 确实已经保存到了 NFS 服务器目录 /nfsdata中。 如果不再需要使用 PV,可用删除 PVC 回收 PV。 在这里,可以尝试在任何一方删除文件,文件在两端都会消失;

3.PV的回收

当 PV 不再需要时,可通过删除 Pod, PVC 回收。未删除pvc之前 pv的状态是Bound

删除pod

[root@k8s-master pvc]# kubectl delete pod mypod1

删除pvc

[root@k8s-master pvc]# kubectl delete pvc mypvc1

查看/nfsdata下面的内容,应该还在

4.PV&PVC在应用在Mysql的持久化存储实战项目

下面演示如何为 MySQL 数据库提供持久化存储,步骤为:

  1. 创建 PV 和 PVC。
  2. 部署 MySQL。
  3. 向 MySQL 添加数据。
  4. 模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到其他节点。
  5. 验证数据一致性。

首先创建 PV 和 PVC,配置如下:

mysql-pv.yml

[root@k8s-master mysqlpv]# cat mysql-pv.ymlapiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: nfs nfs: path: /nfsdata/mysql-pv server:192.168.153.148[root@k8s-master mysqlpv]# kubectl apply -f mysqlpv.yml

mysql-pvc.yml

[root@k8s-master mysqlpv]# cat mysql-pvc.ymlapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs[root@k8s-master mysqlpv]# kubectl apply -f mysql-pvc.yml

接下来部署 MySQL,配置文件如下:

[root@k8s-master mysqlpv]# cat mysqlpod.ymlapiVersion:v1kind:Servicemetadata:name:mysqlspec:ports:-port:3306selector:app:mysql---apiVersion:apps/v1kind:Deploymentmetadata:name:mysqlspec:selector:matchLabels:app:mysqltemplate:metadata:labels:app:mysqlspec:containers:-image:mysql:5.7#这里的镜像一定要选对,能确保拉取到,而且能使用变量name:mysqlenv:-name:MYSQL_ROOT_PASSWORDvalue:"jiange@2024"ports:-containerPort:3306name:mysqlvolumeMounts:-name:mysql-persistent-storagemountPath:/var/lib/mysqlvolumes:-name:mysql-persistent-storagepersistentVolumeClaim:claimName:mysql-pvc[root@k8s-master mysqlpv]# kubectl apply -f mysqlpod.yml

PVCmysql-pvcBound 的 PVmysql-pv将被 mount 到 MySQL 的数据目录/var/lib/mysql

MySQL 被部署到k8s-node1

① 切换到数据库 mysql。

② 创建数据库表 my_id。

③ 插入一条数据。

④ 确认数据已经写入。

关闭k8s-node1,模拟节点宕机故障。

[root@k8s-master mysqlpv]# kubectl exec -it mysql-6654fcb867-mqtcl /bin/bashroot@mysql-6654fcb867-mqtcl:/# mysql -uroot -p'jiange@2024'mysql>create database xiaofeifei;mysql>create table xiaofeifei.t1(id int);mysql>insert into xiaofeifei.t1 values(2);

验证数据的一致性:

第一种:

删除deployment,pvc,pv;然后重新创建pv,pvc,deployment;数据在Mysql中,仍然挂载成功;

第二种:

由于node1节点已经宕机,node2节点接管了这个任务,pod转移,需要等待一段时间,我这里等待了8分钟左右。。

进入新的pod中,数据仍然存在,持久化成功。很安全[root@k8s-master mysqlpv]# kubectl exec -it mysql-6654fcb867-mqtcl /bin/bashroot@mysql-6654fcb867-mqtcl:/# mysql -uroot -p'password'mysql>select* from xiaofeifei.t1;+------+|id|+------+|1||2|+------+2rowsinset(0.01sec)

MySQL 服务恢复,数据也完好无损。
xiaofeifei.t1(id int);
mysql> insert into xiaofeifei.t1 values(2);

验证数据的一致性: 第一种: 删除deployment,pvc,pv;然后重新创建pv,pvc,deployment;数据在Mysql中,仍然挂载成功; 第二种: 由于node1节点已经宕机,node2节点接管了这个任务,pod转移,需要等待一段时间,我这里等待了8分钟左右。。 [外链图片转存中...(img-lbr9fcNi-1773105681439)] ```shell 进入新的pod中,数据仍然存在,持久化成功。很安全 [root@k8s-master mysqlpv]# kubectl exec -it mysql-6654fcb867-mqtcl /bin/bash root@mysql-6654fcb867-mqtcl:/# mysql -uroot -p'password' mysql> select * from xiaofeifei.t1; +------+ | id | +------+ | 1 | | 2 | +------+ 2 rows in set (0.01 sec)

MySQL 服务恢复,数据也完好无损。

http://www.jsqmd.com/news/457035/

相关文章:

  • 2026年企业人事服务推荐:厦门布瑞泽人才信息服务有限公司,人事代理/外包/招聘一站式解决方案 - 品牌推荐官
  • 2026年谷歌SEO公司权威榜单:十大顶级服务商深度评测 - 资讯焦点
  • 2026成人用品加盟平台哪家好?5大维度实测对比,找到最适合你的那一款 - 资讯焦点
  • [学点编程]python workout,每天10分钟学会python 读书笔记
  • 2026钢带增强螺旋波纹管厂家推荐:pe钢带增强波纹管/钢带增强pe波纹管/hdpe增强钢带螺旋波纹管厂家精选。 - 品牌推荐官
  • 2026年制砖机设备推荐:郑州不二精工设备有限公司,全系制砖机满足多样化生产需求 - 品牌推荐官
  • 3秒去除豆包AI图片水印(无需PS、美图秀秀等工具)
  • 2026年3月GEO服务商实力评测排名:Top7综合竞争力权威榜单发布 - 资讯焦点
  • 2026年外贸建站服务商深度评测:十大实力派机构助您出海无忧 - 资讯焦点
  • 复试专业课问答题
  • !!形成网页显示当前系统时间!!
  • 2026年管网监测设备推荐:安耐恩窖井数据采集器/管网RTU/遥测终端全系解决方案 - 品牌推荐官
  • 专精特新典范:绍兴镭斯特测径仪,小仪器撬动大制造的质量革命 - 资讯焦点
  • ssm+java2026年毕设奢品网站系统【源码+论文】
  • 【实时Linux工业PLC解决方案系列】第二十篇 - 实时Linux PLC故障诊断与报警机制
  • ssm+java2026年毕设舌象识别健康服务系统app【源码+论文】
  • 毕设程序java保险客户管理系统 基于SpringBoot的寿险客户全生命周期管理平台 数字化保险客户运营与保单服务中心系统
  • Highcharts旭日图(Sunburst)使用指南|层级数据的环形可视化艺术
  • ssm+java2026年毕设设备营销【源码+论文】
  • 帛书《周易》“家人”象不是《易经》“家人”卦
  • 多模态大模型学习笔记(十五)——Transformer 学习之 Masked-Attention
  • 帛书《周易》“益”象不是《易经》“益”卦
  • 2026降AI工具实测TOP12:从学生党到科研人,精准选品不踩坑 - 老米_专讲AIGC率
  • 长沙旧房改造优质服务商权威推荐榜:长沙二手房翻新公司、长沙二手房翻新工期、长沙二手房翻新设计、长沙二手房翻新预算选择指南 - 优质品牌商家
  • CSS:Less基础、Bootstrap前端开发框架
  • [省选2026游记]????
  • 2026年上海宠物牙科医院大比拼,哪家更靠谱?腹腔镜绝育/宠物牙科/猫咪绝育/宠物外科专家,宠物牙科医院哪家靠谱 - 品牌推荐师
  • 从零构建高精度关键词新闻监控系统:n8n保姆级全流程配置详解
  • 基于深度学习的密集人群行人检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Django+web+训练代码+数据集)
  • 效果佳气流膨化机口碑推荐榜单